Complex classes like BaseUser often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use BaseUser, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
30 | class BaseUser extends ActiveRecord implements IdentityInterface |
||
31 | { |
||
32 | // Status |
||
33 | const STATUS_BLOCKED = 0; |
||
34 | const STATUS_ACTIVE = 1; |
||
35 | const STATUS_WAIT = 2; |
||
36 | const STATUS_DELETED = 3; |
||
37 | |||
38 | // Type of registration |
||
39 | const TYPE_REGISTRATION_SYSTEM = 0; |
||
40 | |||
41 | /** |
||
42 | * @inheritdoc |
||
43 | */ |
||
44 | public static function tableName() |
||
48 | |||
49 | /** |
||
50 | * @inheritdoc |
||
51 | */ |
||
52 | public function behaviors() |
||
60 | |||
61 | /** |
||
62 | * @inheritdoc |
||
63 | */ |
||
64 | public function rules() |
||
85 | |||
86 | /** |
||
87 | * @inheritdoc |
||
88 | */ |
||
89 | public function attributeLabels() |
||
105 | |||
106 | /** |
||
107 | * @inheritdoc |
||
108 | */ |
||
109 | public static function findIdentity($id) |
||
113 | |||
114 | /** |
||
115 | * @param mixed $token |
||
116 | * @param null $type |
||
117 | * @return null|static |
||
118 | */ |
||
119 | public static function findIdentityByAccessToken($token, $type = null) |
||
123 | |||
124 | /** |
||
125 | * Finds user by username |
||
126 | * |
||
127 | * @param string $username |
||
128 | * @return static|null |
||
129 | */ |
||
130 | public static function findByUsername($username) |
||
134 | |||
135 | /** |
||
136 | * Finds user by email |
||
137 | * |
||
138 | * @param string $email |
||
139 | * @return static|null |
||
140 | */ |
||
141 | public static function findByUsernameEmail($email) |
||
145 | |||
146 | /** |
||
147 | * Finds user by username or email |
||
148 | * |
||
149 | * @param string $string |
||
150 | * @return static|null |
||
151 | */ |
||
152 | public static function findByUsernameOrEmail($string) |
||
159 | |||
160 | /** |
||
161 | * Finds user by password reset token |
||
162 | * |
||
163 | * @param string $token password reset token |
||
164 | * @return static|null |
||
165 | */ |
||
166 | public static function findByPasswordResetToken($token) |
||
176 | |||
177 | /** |
||
178 | * Finds out if password reset token is valid |
||
179 | * |
||
180 | * @param string $token password reset token |
||
181 | * @return boolean |
||
182 | */ |
||
183 | public static function isPasswordResetTokenValid($token) |
||
193 | |||
194 | /** |
||
195 | * @inheritdoc |
||
196 | */ |
||
197 | public function getId() |
||
201 | |||
202 | /** |
||
203 | * @inheritdoc |
||
204 | */ |
||
205 | public function getAuthKey() |
||
209 | |||
210 | /** |
||
211 | * @inheritdoc |
||
212 | */ |
||
213 | public function validateAuthKey($authKey) |
||
217 | |||
218 | /** |
||
219 | * Validates password |
||
220 | * |
||
221 | * @param string $password password to validate |
||
222 | * @return boolean if password provided is valid for current user |
||
223 | */ |
||
224 | public function validatePassword($password) |
||
228 | |||
229 | /** |
||
230 | * Generates password hash from password and sets it to the model |
||
231 | * |
||
232 | * @param string $password |
||
233 | */ |
||
234 | public function setPassword($password) |
||
238 | |||
239 | /** |
||
240 | * Generates "remember me" authentication key |
||
241 | */ |
||
242 | public function generateAuthKey() |
||
246 | |||
247 | /** |
||
248 | * Generates new password reset token |
||
249 | */ |
||
250 | public function generatePasswordResetToken() |
||
254 | |||
255 | /** |
||
256 | * Removes password reset token |
||
257 | */ |
||
258 | public function removePasswordResetToken() |
||
262 | |||
263 | /** |
||
264 | * @param string $email_confirm_token |
||
265 | * @return static|null |
||
266 | */ |
||
267 | public static function findByEmailConfirmToken($email_confirm_token) |
||
271 | |||
272 | /** |
||
273 | * Generates email confirmation token |
||
274 | */ |
||
275 | public function generateEmailConfirmToken() |
||
279 | |||
280 | /** |
||
281 | * Removes email confirmation token |
||
282 | */ |
||
283 | public function removeEmailConfirmToken() |
||
287 | |||
288 | /** |
||
289 | * @return bool |
||
290 | */ |
||
291 | public function isDeleted() |
||
295 | |||
296 | /** |
||
297 | * Actions before saving |
||
298 | * |
||
299 | * @param bool $insert |
||
300 | * @return bool |
||
301 | */ |
||
302 | public function beforeSave($insert) |
||
312 | |||
313 | /** |
||
314 | * @return array |
||
315 | */ |
||
316 | public static function getStatusesArray() |
||
325 | |||
326 | /** |
||
327 | * @return mixed |
||
328 | */ |
||
329 | public function getStatusName() |
||
333 | |||
334 | /** |
||
335 | * Return <span class="label label-success">Active</span> |
||
336 | * @return string |
||
337 | */ |
||
338 | public function getStatusLabelName() |
||
343 | |||
344 | /** |
||
345 | * @return array |
||
346 | */ |
||
347 | public static function getLabelsArray() |
||
356 | |||
357 | /** |
||
358 | * Type of registration |
||
359 | * How the user is created |
||
360 | * If the system registration type is registered by itself, |
||
361 | * if it is created from the admin area, |
||
362 | * then the login type that created the account |
||
363 | * |
||
364 | * @return mixed|string |
||
365 | */ |
||
366 | public function getRegistrationType() |
||
375 | |||
376 | /** |
||
377 | * Returns the registration type string |
||
378 | * @return mixed |
||
379 | */ |
||
380 | public function getRegistrationTypeName() |
||
384 | |||
385 | /** |
||
386 | * Returns an array of log types |
||
387 | * @return array |
||
388 | */ |
||
389 | public static function getRegistrationTypesArray() |
||
395 | |||
396 | /** |
||
397 | * @return string |
||
398 | */ |
||
399 | public function getUserFullName() |
||
415 | } |
||
416 |
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.