Utilities

Version 10 (Benjamin P, 2010-10-17 02:57 AM)

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 4 Kien La
*exclude*: 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.