Associations
Version 8 (Kien La, 2010-11-02 12:45 PM)
1 | 1 | h2. Associations |
|
---|---|---|---|
2 | 1 | ||
3 | 3 | Kien La | *(#topic-list) "Common options":/projects/main/wiki/Associations#common-options |
4 | 1 | * "has_many":/projects/main/wiki/Associations#has_many |
|
5 | 8 | Kien La | * "has_many through (many to many)":/projects/main/wiki/Associations#has_many_through |
6 | 1 | * "belongs_to":/projects/main/wiki/Associations#belongs_to |
|
7 | 1 | * "has_one":/projects/main/wiki/Associations#has_one |
|
8 | 1 | * "Self-referential":/projects/main/wiki/Associations#self-referential |
|
9 | 1 | ||
10 | 1 | What are associations? By declaring associations on your models, you allow them to communicate with each other. These associations should match the way data in your tables relate to each other. |
|
11 | 1 | ||
12 | 2 | Kien La | h4(#common-options). Common options |
13 | 1 | ||
14 | 1 | These are available amongst each type of association. |
|
15 | 1 | ||
16 | 1 | *conditions*: string/array of "finder conditions":/projects/main/wiki/Finders#conditions |
|
17 | 1 | *readonly*: whether associated objects can be "saved/destroyed":/projects/main/wiki/Finders#read-only |
|
18 | 1 | *select*: specify fields in the "select clause":/projects/main/wiki/Finders#select |
|
19 | 1 | *class_name*: the class name of the associated model |
|
20 | 1 | *foreign_key*: name of foreign_key |
|
21 | 1 | ||
22 | 1 | Let's take a look at these options with a few different association types |
|
23 | 1 | ||
24 | 2 | Kien La | h5. conditions |
25 | 1 | ||
26 | 1 | Below, we specify that associated payments of an order object should not be void. |
|
27 | 1 | ||
28 | 1 | <pre class="code"><code class="php"> |
|
29 | 1 | class Order extends ActiveRecord\Model { |
|
30 | 1 | static $has_many = array( |
|
31 | 1 | array('payments', 'conditions' => array('void = ?' => array(0))) |
|
32 | 1 | ); |
|
33 | 1 | } |
|
34 | 1 | </code></pre> |
|
35 | 1 | ||
36 | 1 | h5. readonly |
|
37 | 1 | ||
38 | 1 | If you add a readonly option to your association, then the associatied object cannot be saved, although, the base object can still be saved. |
|
39 | 1 | ||
40 | 1 | <pre class="code"><code class="php"> |
|
41 | 1 | class Payment extends ActiveRecord\Model { |
|
42 | 1 | static $belongs_to = array( |
|
43 | 1 | array('user', 'readonly' => true) |
|
44 | 1 | ); |
|
45 | 1 | } |
|
46 | 1 | ||
47 | 1 | $payment = Payment::first(); |
|
48 | 1 | $payment->paid = 1; |
|
49 | 1 | $payment->save(); # this will save just fine |
|
50 | 1 | ||
51 | 1 | $payment->user->first_name = 'John'; |
|
52 | 1 | $payment->user->save(); # this will throw a ReadOnlyException |
|
53 | 1 | </code></pre> |
|
54 | 1 | ||
55 | 1 | h5. select |
|
56 | 1 | ||
57 | 1 | Sometimes you may not need all of the fields back from one of your associations (e.g. it may be a ridiculously large table) and so you can specify the particular fields you want. |
|
58 | 1 | ||
59 | 1 | <pre class="code"><code class="php"> |
|
60 | 1 | class Payment extends ActiveRecord\Model { |
|
61 | 1 | static $belongs_to = array( |
|
62 | 1 | array('person', 'select' => 'id, first_name, last_name') |
|
63 | 1 | ); |
|
64 | 1 | } |
|
65 | 1 | </code></pre> |
|
66 | 1 | ||
67 | 5 | Kien La | h5(#class_name). class_name |
68 | 1 | ||
69 | 1 | In this example payment has a one-to-one relationship with a user, but we want to access the association thru "person." Thus, we have to provide the class name of the associated model; otherwise, ActiveRecord would try to look for a "Person" class. |
|
70 | 1 | ||
71 | 1 | <pre class="code"><code class="php"> |
|
72 | 1 | class Payment extends ActiveRecord\Model { |
|
73 | 1 | static $belongs_to = array( |
|
74 | 1 | array('person', 'class_name' => 'User') |
|
75 | 1 | ); |
|
76 | 1 | } |
|
77 | 1 | </code></pre> |
|
78 | 1 | ||
79 | 4 | Kien La | h4(#has_many). has_many |
80 | 1 | ||
81 | 2 | Kien La | A one-to-many relationship. You should use a pluralized form of the associated model when declaring a has_many association, unless you want to use the "class_name":/projects/main/wiki/Associations#class_name option. |
82 | 1 | ||
83 | 1 | <pre class="code"><code class="php"> |
|
84 | 1 | # one-to-many association with the model "Payment" |
|
85 | 1 | class User extends ActiveRecord\Model { |
|
86 | 1 | static $has_many = array( |
|
87 | 1 | array('payments') |
|
88 | 1 | ); |
|
89 | 1 | } |
|
90 | 1 | ||
91 | 1 | $user = User::first(); |
|
92 | 1 | print_r($user->payments); # => will print an array of Payment objects |
|
93 | 7 | Kien La | </code></pre> |
94 | 1 | ||
95 | 7 | Kien La | !/images/guides/has_many.png! |
96 | 7 | Kien La | |
97 | 2 | Kien La | Options (not part of "common options":/projects/main/wiki/Associations#common-options) |
98 | 1 | ||
99 | 2 | Kien La | *limit/offset*: limit the number of records |
100 | 2 | Kien La | *primary_key*: name of the primary_key of the association (assumed to be "id") |
101 | 2 | Kien La | *group*: GROUP BY clause |
102 | 2 | Kien La | *order*: ORDER BY clause |
103 | 2 | Kien La | *through*: the association used to go "through" |
104 | 1 | ||
105 | 1 | <pre class="code"><code class="php"> |
|
106 | 1 | class Order extends ActiveRecord\Model { |
|
107 | 1 | static $has_many = array( |
|
108 | 1 | array('payments', 'limit' => 5), |
|
109 | 1 | array('items', 'order' => 'name asc', 'group' => 'type') |
|
110 | 1 | ); |
|
111 | 1 | } |
|
112 | 1 | </code></pre> |
|
113 | 1 | ||
114 | 8 | Kien La | h5(#has_many_through). has_many through (many to many) |
115 | 1 | ||
116 | 1 | This is a convenient way to configure a many-to-many association. In this example an order is associated with users by going the its payments association. |
|
117 | 1 | ||
118 | 1 | <pre class="code"><code class="php"> |
|
119 | 1 | class Order extends ActiveRecord\Model { |
|
120 | 1 | static $has_many = array( |
|
121 | 1 | array('payments'), |
|
122 | 1 | array('users', 'through' => 'payments') |
|
123 | 1 | ); |
|
124 | 1 | } |
|
125 | 1 | ||
126 | 1 | class Payment extends ActiveRecord\Model { |
|
127 | 1 | static $belongs_to = array( |
|
128 | 1 | array('user'), |
|
129 | 1 | array('order') |
|
130 | 1 | ); |
|
131 | 1 | } |
|
132 | 1 | ||
133 | 1 | class User extends ActiveRecord\Model { |
|
134 | 1 | static $has_many = array( |
|
135 | 1 | array('payments') |
|
136 | 1 | ); |
|
137 | 1 | } |
|
138 | 1 | ||
139 | 1 | $order = Order::first(); |
|
140 | 1 | # direct access to users |
|
141 | 1 | print_r($order->users); # will print an array of User object |
|
142 | 1 | </code></pre> |
|
143 | 1 | ||
144 | 7 | Kien La | !/images/guides/has_many_through.png! |
145 | 7 | Kien La | |
146 | 2 | Kien La | h4(#belongs_to). belongs_to |
147 | 1 | ||
148 | 2 | Kien La | This indicates a one-to-one relationship. Its difference from "has_one":/projects/main/wiki/Associations#has_one is that the foreign key will be on the table which declares a belongs_to association. You should use a singular form of the associated model when declaring this association, unless you want to use the "class_name":/projects/main/wiki/Associations#class_name option. |
149 | 1 | ||
150 | 1 | <pre class="code"><code class="php"> |
|
151 | 1 | class Payment extends ActiveRecord\Model { |
|
152 | 1 | static $belongs_to = array( |
|
153 | 1 | array('user') |
|
154 | 1 | ); |
|
155 | 1 | } |
|
156 | 1 | ||
157 | 1 | $payment = Payment::first(); |
|
158 | 1 | echo $payment->user->first_name; # first_name of associated User object |
|
159 | 1 | </code></pre> |
|
160 | 1 | ||
161 | 7 | Kien La | !/images/guides/belongs_to.png! |
162 | 7 | Kien La | |
163 | 2 | Kien La | Options (not part of "common options":/projects/main/wiki/Associations#common-options) |
164 | 1 | ||
165 | 1 | *primary_key*: name of the primary_key of the association (assumed to be "id") |
|
166 | 4 | Kien La | |
167 | 4 | Kien La | h4(#has_one). has_one |
168 | 1 | ||
169 | 2 | Kien La | This indicates a one-to-one relationship. A has_one will have the foreign key on the associated table unlike "belongs_to":/projects/main/wiki/Associations#belongs_to. You should use a singular form of the associated model when declaring this association, unless you want to use the "class_name":/projects/main/wiki/Associations#class_name option. |
170 | 1 | ||
171 | 1 | <pre class="code"><code class="php"> |
|
172 | 1 | class Payment extends ActiveRecord\Model { |
|
173 | 1 | static $has_one = array( |
|
174 | 1 | array('receipt') |
|
175 | 1 | ); |
|
176 | 1 | } |
|
177 | 7 | Kien La | </code></pre> |
178 | 1 | ||
179 | 7 | Kien La | !/images/guides/has_one.png! |
180 | 7 | Kien La | |
181 | 2 | Kien La | Options (not part of "common options":/projects/main/wiki/Associations#common-options) |
182 | 1 | ||
183 | 2 | Kien La | *primary_key*: name of the primary_key of the association (assumed to be "id") |
184 | 2 | Kien La | *through*: the association used to go "through" |
185 | 1 | ||
186 | 2 | Kien La | h5. has_one through |
187 | 2 | Kien La | |
188 | 1 | A one-to-one association. In this example, an owner has a quarter_back by going through its team association. |
|
189 | 1 | ||
190 | 1 | <pre class="code"><code class="php"> |
|
191 | 1 | class Owner extends ActiveRecord\Model { |
|
192 | 1 | static $has_one = array( |
|
193 | 1 | array('team'), |
|
194 | 1 | array('quarter_back', 'through' => 'team') |
|
195 | 1 | ); |
|
196 | 1 | } |
|
197 | 1 | ||
198 | 1 | class Team extends ActiveRecord\Model { |
|
199 | 1 | static $belongs_to = array( |
|
200 | 1 | array('owner') |
|
201 | 1 | ); |
|
202 | 1 | ||
203 | 1 | static $has_one = array( |
|
204 | 1 | array('quarter_back') |
|
205 | 1 | ); |
|
206 | 1 | } |
|
207 | 1 | ||
208 | 1 | class QuarterBack extends ActiveRecord\Model { |
|
209 | 1 | static $belongs_to = array( |
|
210 | 1 | array('team') |
|
211 | 1 | ); |
|
212 | 1 | } |
|
213 | 1 | </code></pre> |
|
214 | 1 | ||
215 | 7 | Kien La | !/images/guides/has_one_through.png! |
216 | 7 | Kien La | |
217 | 2 | Kien La | h4(#self-referential). Self-referential |
218 | 1 | ||
219 | 1 | Model's can declare associations to themselves. This can be helpful for table auditing, or in the example below, where a post would need to know about its parent. |
|
220 | 1 | ||
221 | 1 | <pre class="code"><code class="php"> |
|
222 | 1 | class Post extends ActiveRecord\Model { |
|
223 | 1 | static $belongs_to = array(array('parent_post', 'class_name' => 'Post')); |
|
224 | 1 | } |
|
225 | 1 | </code></pre> |
|
226 | 7 | Kien La | |
227 | 7 | Kien La | !/images/guides/belongs_to_self_referential.png! |