~coughphp/coughphp/2.0

« back to all changes in this revision

Viewing changes to design/Overview - What is Cough.markdown

  • Committer: Anthony Bush
  • Date: 2008-08-23 03:35:08 UTC
  • mfrom: (262.1.18 coughphp-release-1.3)
  • Revision ID: anthony@anthonybush.com-20080823033508-uy4yn5pmio6wcetv
Accept release-1.3 branch changes into trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
ORM / Model: Cough
2
 
------------------
3
 
 
4
 
1. A way to get and set fields from a persistent layer.
5
 
 
6
 
2. A way to ensure fields meet certain validation criteria before being allowed into the persistent layer. {
7
 
        * A way to easily set customer validation error messages that can be passed to the view later.
8
 
                * e.g. "Passwords do not match", "Username is already taken", "Password must contain at least 6 characters"
9
 
}
10
 
 
11
 
3. A way to manage related objects {
12
 
        * A way to easily construct the related object from the FK.
13
 
                * Ability to optimize query so that one query pulls an object and all the related data.
14
 
}
15
 
 
16
 
4. A way to manage related collections of objects (one-to-many) {
17
 
        * Easily pull an entity's related collections with no SQL knowledge.
18
 
                * Easily customize which data is retrieved or how data is retrieved using what you already know about SQL.
19
 
        * Easily add and remove entities from a collection with an id or object.
20
 
                * Easily add or override additional functionality to adders/removers to perform custom business logic.
21
 
}
22
 
 
23
 
5. A way to manage related collections of objects (many-to-many) {
24
 
        * Same as one-to-one, even looping through the collection (i.e. no need to loop through join table collection), plus
25
 
        * A way to manage additional join fields easily.
26
 
        * Supports retiring of columns (aka delete_flag).
27
 
        * Supports DELETEs in addition to the above.
28
 
}
29
 
 
30
 
 
31
 
 
32
 
 
33
 
 
34
 
 
35
 
 
36
 
 
37
 
 
38
 
 
39
 
Make this clear
40
 
---------------
41
 
 
42
 
Basically, some marketing things for the web site.
43
 
 
44
 
* Rules of OO programming
45
 
 
46
 
* High performance
47
 
        * Will not do needless loads
48
 
 
49
 
 
50
 
 
51
 
 
52
 
 
53
 
 
54
 
 
55
 
 
56
 
 
57
 
 
58
 
 
59
 
 
60
 
 
61
 
 
62
 
 
63
 
 
64
 
 
65
 
 
66
 
### 1. Getting/Setting Fields ###
67
 
get<field>() // gets the field. easy to override.
68
 
set<field>($value) // sets the field and toggles a modified flag so that save works. easy to override
69
 
 
70
 
### 2. Validation Functions ###
71
 
doValidateData(&$fields) // validate passed in data.
72
 
invalidateField(<field>, <message>)
73
 
getValidationErrors()
74
 
// etc...
75
 
 
76
 
### 3. Manage related objects ###
77
 
get<object>_Object() // get an object, initializing it if needed.
78
 
set<object>_Object() // set an object to a value you know. override if you want it to also set the FK or supported out of box?
79
 
 
80
 
### 4. Manage related one-to-many collections ###
81
 
get<collection>_Collection()
82
 
 
83
 
### 5. Manage related many-to-many collections ###
84
 
get<collection>_Collection() // careful here... we ran into some naming conflicts before when there was more than one way to join into a collection...this is cause for reconsidering they way many-to-many collections are iterated through.
85
 
 
86
 
person
87
 
        person_id name
88
 
school
89
 
        school_id name
90
 
student
91
 
        person_id school_id start_date end_date
92
 
school_rating
93
 
        person_id school_id rating
94
 
 
95
 
With this model person has two school collections, a collection of schools they were students at, and a collection of schools they rated. If we require that join tables be retrieved first, we solve the naming conflict problem. Example code:
96
 
 
97
 
        <?php
98
 
        $person = new Person(1);
99
 
        foreach ($person->getSchoolRating_Collection() as $schoolRating) {
100
 
                $school = $schoolRating->getSchool(); // no extra query run by default on many-to-many queries like this.
101
 
                echo $person->getName() . ' rated ' . $school->getName() . ' ' . $schoolRating->getRating() . '.';
102
 
        }
103
 
        foreach ($person->getStudent_Collection() as $student) {
104
 
                $school = $student->getSchool(); // no extra query run by default on many-to-many queries like this.
105
 
                echo $person->getName() . ' attended ' . $school->getName()
106
 
                     . ' from ' . $student->getStartDate()
107
 
                     . ' to ' . $student->getEndDate() . '.';
108
 
        }
109
 
        ?>
110
 
 
111
 
The terminology for adding/removing also makes more sense:
112
 
 
113
 
        <?php
114
 
        $person = new Person(1);
115
 
        
116
 
        // Old way:
117
 
        $person->removeSchool($schoolId); // which school collection gets an item removed from?
118
 
        
119
 
        // New way:
120
 
        $person->removeSchoolRating(/* BUT, what to pass? PK is what it currently expects, but doesn't it make more sense to pass the school_id? probably not, see next example */);
121
 
        
122
 
        // Let's using the remove on the join but passing the id of the PK of the other side of the join:
123
 
        $person->removeStudent($schoolId); // which record in the join gets removed? person might have been a student at the same school for many different date ranges. THUS, we must keep it simple (but maybe also confusing? See following examples)
124
 
        
125
 
        // Right way:
126
 
        $person->removeStudent($primaryKey); // either a separate primary key column, student_id, or multi-key PK for person_id, school_id, start_date, and end_date.
127
 
        
128
 
        ?>
129
 
 
130
 
Okay, so what about adding?
131
 
 
132
 
        <?php
133
 
        $person = Person(1);
134
 
        $person->addSchoolRating($schoolRatingId); // makes no sense, we have no PK yet.
135
 
        $person->addSchoolRating($schoolId, $rating); // ?
136
 
        $person->addSchoolRating($schoolId, $joinFields = array('rating' => 0)); // ?
137
 
        ?>
138
 
 
139
 
The above is confusing... The correct way to do it is the same as with one-to-many collections (basically everything is a "one-to-many" unless it is the direct access "many-to-many")
140
 
 
141
 
        <?php
142
 
        $person = Person(1);
143
 
        // Prototype: addSchoolRating($schoolRatingFields_or_schoolRatingObject);
144
 
        $person->addSchoolRating(array('school_id' => $schoolId, 'rating' => 0)); // ?
145
 
        
146
 
        $schoolRating = new SchoolRating();
147
 
        $schoolRating->setSchoolId($schoolId);
148
 
        $schoolRating->setRating(0);
149
 
        $person->addSchoolRating($schoolRating);
150
 
        ?>
151
 
 
152
 
 
153
 
Okay, so how is adding join name confusing (i.e. why did we go the route that causes naming conflicts)? Well, consider the data model:
154
 
 
155
 
        product
156
 
                product_id name
157
 
        os
158
 
                os_id name
159
 
        product2os
160
 
                product2os_id product_id os_id
161
 
 
162
 
It makes a lot of since to say:
163
 
 
164
 
        <?php
165
 
        $product = new Product(1);
166
 
        $product->addOs($osId);
167
 
        // or
168
 
        $product->setOs_Collection(array($osId1, $osId2/*, etc. */));
169
 
        ?>
170
 
 
171
 
But if we fix the naming conflicts it would then become:
172
 
 
173
 
        <?php
174
 
        $product = new Product(1);
175
 
        $product->addProduct2Os($osId, $joinFields=array());
176
 
        $product->setProduct2Os_Collection(array($osId1, $osId2/*, etc. */)); // ? kind of weird, isn't it? maybe we need a toggle point at the generator level... [ ] This is a simple join table, make it look like a one-to-many.
177
 
        ?>
178