Utilities
Version 11 (Steve Erhart, 2011-08-17 01:59 PM)
1 | 2 | Kien La | h2. Utilities |
---|---|---|---|
2 | 1 | ||
3 | 3 | Kien La | *(#topic-list) "Delegators":/projects/main/wiki/Utilities#delegators |
4 | 3 | Kien La | * "Attribute Setters":/projects/main/wiki/Utilities#attribute-setters |
5 | 6 | Kien La | * "Attribute Getters":/projects/main/wiki/Utilities#attribute-getters |
6 | 3 | Kien La | * "Aliased attributes":/projects/main/wiki/Utilities#aliased-attributes |
7 | 3 | Kien La | * "Protected attributes":/projects/main/wiki/Utilities#protected-attributes |
8 | 3 | Kien La | * "Accessible attributes":/projects/main/wiki/Utilities#accessible-attributes |
9 | 3 | Kien La | * "Serialization":/projects/main/wiki/Utilities#serialization |
10 | 7 | Kien La | * "Automatic Timestamps":/projects/main/wiki/Utilities#automatic-timestamps |
11 | 3 | Kien La | |
12 | 1 | ActiveRecord offers numerous ways to make your life easier by adding some interesting features to your models. |
|
13 | 1 | ||
14 | 3 | Kien La | h4(#delegators). Delegators |
15 | 1 | ||
16 | 4 | Kien La | This is similar to "attribute aliasing":/projects/main/wiki/Utilities#aliased-attributes, except that it works via your associations. You can alias an attribute on your model to use a particular attribute on an association. Let's take a look. |
17 | 1 | ||
18 | 1 | <pre class="code"><code class="php"> |
|
19 | 1 | class Person extends ActiveRecord\Model { |
|
20 | 1 | static $belongs_to = array(array('venue'),array('host')); |
|
21 | 1 | static $delegate = array( |
|
22 | 1 | array('name', 'state', 'to' => 'venue'), |
|
23 | 1 | array('name', 'to' => 'host', 'prefix' => 'host')); |
|
24 | 1 | } |
|
25 | 1 | ||
26 | 1 | $person = Person::first(); |
|
27 | 1 | $person->state # same as calling $person->venue->state |
|
28 | 1 | $person->name # same as calling $person->venue->name |
|
29 | 1 | $person->host_name # same as calling $person->host->name |
|
30 | 1 | </code></pre> |
|
31 | 6 | Kien La | |
32 | 3 | Kien La | h4(#attribute-setters). Attribute setters |
33 | 1 | ||
34 | 4 | Kien La | Setters allow you to define custom methods for assigning a value to one of your attributes. This means you can intercept the assign process and filter/modify the data to your needs. This is helpful in a situation such as encrypting user passwords. Normally, you define a setter which does not carry the same name as your attribute, but you can set your attribute inside of the method. In the example below, *$user->password* is a virtual attribute: if you try to read/access the attribute instead of assign, an "UndefinedPropertyException":/docs/ActiveRecord/UndefinedPropertyException will be thrown. |
35 | 1 | ||
36 | 1 | <pre class="code"><code class="php"> |
|
37 | 1 | class User extends ActiveRecord\Model { |
|
38 | 1 | ||
39 | 1 | # A setter method must have set_ prepended to its name to qualify. |
|
40 | 1 | # $this->encrypted_password is the actual attribute for this model. |
|
41 | 1 | public function set_password($plaintext) { |
|
42 | 1 | $this->encrypted_password = md5($plaintext); |
|
43 | 1 | } |
|
44 | 1 | } |
|
45 | 1 | ||
46 | 1 | $user = new User; |
|
47 | 1 | $user->password = 'plaintext'; # will call $user->set_password('plaintext') |
|
48 | 1 | # if you did an echo $user->password you would get an UndefinedPropertyException |
|
49 | 1 | </code></pre> |
|
50 | 1 | ||
51 | 4 | Kien La | If you define a custom setter with the same name as an attribute then you will need to use "assign_attribute()":/docs/ActiveRecord/Model#methodassign_attribute to assign the value to the attribute. This is necessary due to the way "Model::__set()":/docs/ActiveRecord/Model#method__set works. For example, assume 'name' is a field on the table and we're defining a custom setter called 'name': |
52 | 1 | ||
53 | 1 | <pre class="code"><code class="php"> |
|
54 | 1 | class User extends ActiveRecord\Model { |
|
55 | 1 | ||
56 | 1 | # INCORRECT: |
|
57 | 1 | # function set_name($name) { |
|
58 | 1 | # $this->name = strtoupper($name); |
|
59 | 1 | # } |
|
60 | 1 | ||
61 | 1 | public function set_name($name) { |
|
62 | 1 | $this->assign_attribute('name',strtoupper($name)); |
|
63 | 1 | } |
|
64 | 1 | } |
|
65 | 1 | ||
66 | 1 | $user = new User; |
|
67 | 1 | $user->name = 'bob'; |
|
68 | 1 | echo $user->name; # => BOB |
|
69 | 1 | </code></pre> |
|
70 | 6 | Kien La | |
71 | 1 | h4(#attribute-getters). Attribute getters |
|
72 | 6 | Kien La | |
73 | 9 | Jacques Fuentes | Getters allow you to intercept attribute/property value retrieval on your models. They are defined in a similar manner to setters. See "Model::__get":/docs/ActiveRecord/Model#method__get for details. |
74 | 1 | ||
75 | 3 | Kien La | h4(#aliased-attributes). Aliased attributes |
76 | 1 | ||
77 | 10 | Benjamin P | This option is fairly straight-forward. An aliased attribute allows you to set/get the attribute via a different name. This comes in handy when you have terrible field names like field_one, field_two, or for legacy tables. In this example, the alias first_name is created to reference the existing field person_first_name. |
78 | 1 | ||
79 | 1 | <pre class="code"><code class="php"> |
|
80 | 1 | class Person extends ActiveRecord\Model { |
|
81 | 1 | static $alias_attribute = array( |
|
82 | 1 | 'first_name' => 'person_first_name', |
|
83 | 1 | 'last_name' => 'person_last_name'); |
|
84 | 1 | } |
|
85 | 1 | ||
86 | 1 | $person = Person::first(); |
|
87 | 1 | echo $person->person_first_name; # => Jax |
|
88 | 1 | ||
89 | 1 | $person->first_name = 'Tito'; |
|
90 | 1 | echo $person->first_name; # => Tito |
|
91 | 1 | echo $person->person_first_name; # => Tito |
|
92 | 1 | </code></pre> |
|
93 | 1 | ||
94 | 3 | Kien La | h4(#protected-attributes). Protected attributes |
95 | 1 | ||
96 | 4 | Kien La | Blacklist of attributes that cannot be mass-assigned. Protecting these attributes allows you to avoid security problems where a malicious user may try to create additional post values. This is the opposite of "accessible attributes":/projects/main/wiki/Utilities#accessible-attributes. |
97 | 1 | ||
98 | 1 | <pre class="code"><code class="php"> |
|
99 | 1 | class User extends ActiveRecord\Model { |
|
100 | 1 | static $attr_protected = array('admin'); |
|
101 | 1 | } |
|
102 | 1 | ||
103 | 1 | $attributes = array('first_name' => 'Tito','admin' => 1); |
|
104 | 1 | $user = new User($attributes); |
|
105 | 1 | ||
106 | 1 | echo $user->first_name; # => Tito |
|
107 | 1 | echo $user->admin; # => null |
|
108 | 1 | # now no one can fake post values and make themselves an admin against your will! |
|
109 | 1 | </code></pre> |
|
110 | 1 | ||
111 | 3 | Kien La | h4(#accessible-attributes). Accessible attributes |
112 | 1 | ||
113 | 4 | Kien La | Whitelist of attributes that are checked from mass-assignment calls such as constructing a model or using "Model::update_attributes()":/docs/ActiveRecord/Model#methodupdate_attributes. This is the opposite of "protected attributes":/projects/main/wiki/Utilities#protected-attributes. Accessible attributes can also be used as a security measure against fake post values, except that it is often more pragmatic because it is a whitelist approach. |
114 | 1 | ||
115 | 1 | <pre class="code"><code class="php"> |
|
116 | 1 | class User extends ActiveRecord\Model { |
|
117 | 1 | static $attr_accessible = array('first_name'); |
|
118 | 1 | } |
|
119 | 1 | ||
120 | 1 | $attributes = array('first_name' => 'Tito','last_name' => 'J.','admin' => 1); |
|
121 | 1 | $user = new User($attributes); |
|
122 | 1 | ||
123 | 1 | echo $person->last_name; # => null |
|
124 | 1 | echo $person->admin; # => null |
|
125 | 1 | echo $person->first_name; # => Tito |
|
126 | 1 | # first_name is the only attribute that can be mass-assigned, so the other 2 are null |
|
127 | 1 | </code></pre> |
|
128 | 1 | ||
129 | 1 | h4(#serialization). Serialization |
|
130 | 3 | Kien La | |
131 | 1 | This is not the normal kind of PHP serialization you are used to. This will not serialize your entire object; however, it will serialize the attributes of your model to either an xml or a json representation. An options array can take the following parameters: |
|
132 | 1 | ||
133 | 4 | Kien La | *only*: a string or array of attributes to be included. |
134 | 11 | Steve Erhart | *except*: a string or array of attributes to be excluded. |
135 | 4 | Kien La | *methods*: a string or array of methods to invoke. The method's name will be used as a key for the final attributes array along with the method's returned value |
136 | 4 | Kien La | *include*: a string or array of associated models to include in the final serialized product. |
137 | 4 | Kien La | *skip_instruct*: set to true to skip the <?xml ...?> declaration. |
138 | 1 | ||
139 | 4 | Kien La | Below only includes "Model::to_json()":/docs/ActiveRecord/Model#methodto_json examples; however, you can use all of the examples with "Model::to_xml()":/docs/ActiveRecord/Model#methodto_xml |
140 | 4 | Kien La | |
141 | 1 | <pre class="code"><code class="php"> |
|
142 | 1 | class User extends ActiveRecord\Model { |
|
143 | 1 | static $has_many = array(array('orders')); |
|
144 | 1 | ||
145 | 1 | public function name() { |
|
146 | 1 | return $this->first_name .' '. $this->last_name; |
|
147 | 1 | } |
|
148 | 1 | } |
|
149 | 1 | ||
150 | 1 | # assume these fields are on our `users` table: |
|
151 | 1 | # id, first_name, last_name, email, social_security, phone_number |
|
152 | 1 | ||
153 | 1 | $user = User::first(); |
|
154 | 1 | ||
155 | 1 | # json should only contain id and email |
|
156 | 1 | $json = $user->to_json(array( |
|
157 | 1 | 'only' => array('id', 'email') |
|
158 | 1 | )); |
|
159 | 1 | ||
160 | 1 | echo $json; # => {"id":1,"email":"[email protected]"} |
|
161 | 1 | ||
162 | 1 | # limit via exclusion (here we use a string, but an array can be passed) |
|
163 | 1 | $json = $user->to_json(array( |
|
164 | 1 | 'except' => 'social_security' |
|
165 | 1 | )); |
|
166 | 1 | ||
167 | 1 | echo $json; # => {"id":1,"first_name":"George","last_name":"Bush", |
|
168 | 1 | # "email":"[email protected]","phone_number":"555-5555"} |
|
169 | 1 | ||
170 | 1 | # call $user->name() and the returned value will be in our json |
|
171 | 1 | $json = $user->to_json(array( |
|
172 | 1 | 'only' => array('email', 'name'), |
|
173 | 1 | 'methods' => 'name' |
|
174 | 1 | )); |
|
175 | 1 | ||
176 | 1 | echo $json; # => {"name":"George Bush","email":"[email protected]"} |
|
177 | 1 | ||
178 | 1 | # call $user->name() and the returned value will be in our json |
|
179 | 1 | $json = $user->to_json(array( |
|
180 | 1 | 'only' => array('email', 'name'), |
|
181 | 1 | 'methods' => 'name' |
|
182 | 1 | )); |
|
183 | 1 | ||
184 | 1 | # include the orders association |
|
185 | 1 | $json = $user->to_json(array( |
|
186 | 1 | 'include' => array('orders') |
|
187 | 1 | )); |
|
188 | 1 | ||
189 | 1 | # you can nest includes .. here orders also has a payments association |
|
190 | 1 | $json = $user->to_json(array( |
|
191 | 1 | 'include' => array('orders' => array('except' => 'id', 'include' => 'payments') |
|
192 | 1 | )); |
|
193 | 1 | </code></pre> |
|
194 | 1 | ||
195 | 8 | Kien La | DateTime fields are serialized to "ISO8601":http://www.php.net/manual/en/class.datetime.php#datetime.constants.iso8601 format by default. This format can be changed by setting *ActiveRecord\Serialization::$DATETIME_FORMAT*. You can use a raw formatter or any of the pre-defined formats defined in "DateTime::$FORMAT":/docs/ActiveRecord/DateTime#var$FORMATS |
196 | 1 | ||
197 | 1 | <pre class="code"><code class="php"> |
|
198 | 8 | Kien La | ActiveRecord\Serialization::$DATETIME_FORMAT = 'Y-m-d'; |
199 | 8 | Kien La | ActiveRecord\Serialization::$DATETIME_FORMAT = 'atom'; |
200 | 8 | Kien La | ActiveRecord\Serialization::$DATETIME_FORMAT = 'long'; |
201 | 8 | Kien La | ActiveRecord\Serialization::$DATETIME_FORMAT = \DateTime::RSS; |
202 | 1 | </code></pre> |
|
203 | 7 | Kien La | |
204 | 7 | Kien La | h4(#automatic-timestamps). Automatic Timestamps |
205 | 7 | Kien La | |
206 | 7 | Kien La | Models with fields named *created_at* and *updated_at* will have those fields automatically updated upon model creation and model updates. |