1
|
|
|
<?php defined('SYSPATH') OR die('No direct script access.'); |
2
|
|
|
/** |
3
|
|
|
* Jam Core |
4
|
|
|
* |
5
|
|
|
* This core class is the main interface to all |
6
|
|
|
* models, builders, and meta data. |
7
|
|
|
* |
8
|
|
|
* @package Jam |
9
|
|
|
* @category Base |
10
|
|
|
* @author Ivan Kerin |
11
|
|
|
* @copyright (c) 2011-2013 Despark Ltd. |
12
|
|
|
* @author Jonathan Geiger |
13
|
|
|
* @copyright (c) 2010-2011 Jonathan Geiger |
14
|
|
|
* @license http://www.opensource.org/licenses/isc-license.txt |
15
|
|
|
*/ |
16
|
|
|
abstract class Kohana_Jam { |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* @var string The prefix to use for all model's class names |
20
|
|
|
* This can be overridden to allow you to place |
21
|
|
|
* models and collections in a different location. |
22
|
|
|
*/ |
23
|
|
|
protected static $_model_prefix = 'Model_'; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* @var string The prefix to use for all model's collection class names |
27
|
|
|
* This can be overridden to allow you to place |
28
|
|
|
* models and collections in a different location. |
29
|
|
|
*/ |
30
|
|
|
protected static $_collection_prefix = 'Model_Collection_'; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* @var string This prefix to use for all model's field classes |
34
|
|
|
* This can be overridden to allow you to place |
35
|
|
|
* field classes in a different location. |
36
|
|
|
*/ |
37
|
|
|
protected static $_field_prefix = 'Jam_Field_'; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* @var string This prefix to use for all behavior classes |
41
|
|
|
* This can be overridden to allow you to place |
42
|
|
|
* behavior classes in a different location. |
43
|
|
|
*/ |
44
|
|
|
protected static $_behavior_prefix = 'Jam_Behavior_'; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* @var string This prefix to use for all model's association classes |
48
|
|
|
* This can be overridden to allow you to place |
49
|
|
|
* association classes in a different location. |
50
|
|
|
*/ |
51
|
|
|
protected static $_association_prefix = 'Jam_Association_'; |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* @var string This prefix to use for all model's form classes |
55
|
|
|
* This can be overridden to allow you to place |
56
|
|
|
* form classes in a different location. |
57
|
|
|
*/ |
58
|
|
|
protected static $_form_prefix = 'Jam_Form_'; |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* @var string This prefix to use for all attribute's validator rule classes |
62
|
|
|
* This can be overridden to allow you to place |
63
|
|
|
* form classes in a different location. |
64
|
|
|
*/ |
65
|
|
|
protected static $_validator_rule_prefix = 'Jam_Validator_Rule_'; |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* @var array Contains all of the meta classes related to models |
69
|
|
|
*/ |
70
|
|
|
public static $_models = array(); |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* Hold model objects for templates |
74
|
|
|
* @var array |
75
|
|
|
*/ |
76
|
|
|
protected static $_build_templates = array(); |
77
|
|
|
|
78
|
|
|
/** |
79
|
|
|
* Make a new object of the given model, optionally setting some fields |
80
|
|
|
* @param string $model_name |
81
|
|
|
* @param array $attributes |
82
|
|
|
* @return Jam_Model |
83
|
|
|
*/ |
84
|
362 |
|
public static function build($model_name, array $attributes = NULL) |
85
|
|
|
{ |
86
|
362 |
|
$meta = Jam::meta($model_name); |
87
|
|
|
|
88
|
362 |
|
if ($meta AND $meta->polymorphic_key() AND ! empty($attributes[$meta->polymorphic_key()])) |
89
|
362 |
|
{ |
90
|
2 |
|
$model_name = $attributes[$meta->polymorphic_key()]; |
91
|
2 |
|
} |
92
|
|
|
|
93
|
362 |
|
$class = Jam::class_name($model_name); |
94
|
|
|
|
95
|
362 |
|
$object = new $class(); |
96
|
|
|
|
97
|
|
|
if ($attributes) |
98
|
362 |
|
{ |
99
|
9 |
|
$object->set($attributes); |
100
|
9 |
|
} |
101
|
|
|
|
102
|
362 |
|
return $object; |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
/** |
106
|
|
|
* Create a new object of a given model, optionally setting some fields, and then save it to the database |
107
|
|
|
* @param string $model |
108
|
|
|
* @param array $attributes |
109
|
|
|
* @return Jam_Model |
110
|
|
|
*/ |
111
|
2 |
|
public static function create($model, array $attributes = array()) |
112
|
|
|
{ |
113
|
2 |
|
return Jam::build($model, $attributes)->save(); |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* Gets a particular set of metadata about a model. If the model |
118
|
|
|
* isn't registered, it will attempt to register it. |
119
|
|
|
* |
120
|
|
|
* FALSE is returned on failure. |
121
|
|
|
* |
122
|
|
|
* @param string|Jam_Model $model |
123
|
|
|
* @return Jam_Meta |
124
|
|
|
*/ |
125
|
644 |
|
public static function meta($model) |
126
|
|
|
{ |
127
|
644 |
|
$model = Jam::model_name($model); |
128
|
|
|
|
129
|
644 |
|
if ( ! isset(Jam::$_models[$model])) |
130
|
644 |
|
{ |
131
|
79 |
|
if ( ! Jam::register($model)) |
132
|
79 |
|
{ |
133
|
78 |
|
return FALSE; |
|
|
|
|
134
|
|
|
} |
135
|
1 |
|
} |
136
|
|
|
|
137
|
644 |
|
return Jam::$_models[$model]; |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
/** |
141
|
|
|
* Factory for instantiating fields. |
142
|
|
|
* |
143
|
|
|
* @param string $type |
144
|
|
|
* @param mixed $options |
145
|
|
|
* @return Jam_Field |
146
|
|
|
*/ |
147
|
38 |
|
public static function field($type, $options = NULL) |
148
|
|
|
{ |
149
|
38 |
|
$field = Jam::$_field_prefix.Jam::capitalize_class_name($type); |
|
|
|
|
150
|
|
|
|
151
|
38 |
|
return new $field($options); |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
/** |
155
|
|
|
* Factory for instantiating associations. |
156
|
|
|
* |
157
|
|
|
* @param string $type |
158
|
|
|
* @param mixed $options |
159
|
|
|
* @return Jam_Association |
160
|
|
|
*/ |
161
|
1 |
|
public static function association($type, $options = NULL) |
162
|
|
|
{ |
163
|
1 |
|
$association = Jam::$_association_prefix.Jam::capitalize_class_name($type); |
|
|
|
|
164
|
|
|
|
165
|
1 |
|
return new $association($options); |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
|
169
|
|
|
/** |
170
|
|
|
* Factoring for instantiating behaviors. |
171
|
|
|
* |
172
|
|
|
* @param string $type |
173
|
|
|
* @param mixed $options |
174
|
|
|
* @return Jam_Behavior |
175
|
|
|
*/ |
176
|
|
|
public static function behavior($type, $options = array()) |
177
|
|
|
{ |
178
|
|
|
$behavior = Jam::$_behavior_prefix.Jam::capitalize_class_name($type); |
|
|
|
|
179
|
|
|
|
180
|
|
|
return new $behavior($options); |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* Factoring for instantiating behaviors. |
185
|
|
|
* |
186
|
|
|
* @param string $type |
187
|
|
|
* @param mixed $options |
188
|
|
|
* @return Jam_Validator_Rule |
189
|
|
|
*/ |
190
|
182 |
|
public static function validator_rule($type, $options = array()) |
191
|
|
|
{ |
192
|
182 |
|
$rule = Jam::$_validator_rule_prefix.Jam::capitalize_class_name($type); |
|
|
|
|
193
|
|
|
|
194
|
182 |
|
return new $rule($options); |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
|
198
|
|
|
|
199
|
|
|
/** |
200
|
|
|
* Automatically loads a model, if it exists, |
201
|
|
|
* into the meta table. |
202
|
|
|
* |
203
|
|
|
* Models are not required to register |
204
|
|
|
* themselves; it happens automatically. |
205
|
|
|
* |
206
|
|
|
* @param string $model |
207
|
|
|
* @return boolean |
208
|
|
|
*/ |
209
|
84 |
|
public static function register($model) |
210
|
|
|
{ |
211
|
84 |
|
$class = Jam::class_name($model); |
212
|
84 |
|
$model = Jam::model_name($model); |
213
|
|
|
|
214
|
|
|
// Don't re-initialize! |
215
|
84 |
|
if (isset(Jam::$_models[$model])) |
216
|
84 |
|
{ |
217
|
2 |
|
return TRUE; |
218
|
|
|
} |
219
|
|
|
|
220
|
|
|
// Can we find the class? |
221
|
82 |
|
if (class_exists($class)) |
222
|
82 |
|
{ |
223
|
|
|
// Prevent accidentally trying to load ORM or Sprig models |
224
|
3 |
|
if ( ! is_subclass_of($class, 'Jam_Validated')) |
225
|
3 |
|
{ |
226
|
2 |
|
return FALSE; |
227
|
|
|
} |
228
|
1 |
|
} |
229
|
|
|
else |
230
|
|
|
{ |
231
|
79 |
|
return FALSE; |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
// Load it into the registry |
235
|
1 |
|
Jam::$_models[$model] = $meta = new Jam_Meta($model); |
236
|
|
|
|
237
|
|
|
// Let the intialize() method override defaults. |
238
|
1 |
|
call_user_func(array($class, 'initialize'), $meta); |
239
|
|
|
|
240
|
|
|
// Finalize the changes |
241
|
1 |
|
$meta->finalize($model); |
242
|
|
|
|
243
|
1 |
|
return TRUE; |
244
|
|
|
} |
245
|
|
|
|
246
|
439 |
|
public static function capitalize_class_name($class_name) |
247
|
|
|
{ |
248
|
439 |
|
return str_replace(' ', '_', ucwords(str_replace('_', ' ', $class_name))); |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
/** |
252
|
|
|
* Returns the class name of a model |
253
|
|
|
* |
254
|
|
|
* @param string|Jam_Validated $model |
255
|
|
|
* @return string |
256
|
|
|
*/ |
257
|
417 |
|
public static function class_name($model) |
258
|
|
|
{ |
259
|
417 |
|
if ($model instanceof Jam_Validated) |
260
|
417 |
|
{ |
261
|
2 |
|
return get_class($model); |
262
|
|
|
} |
263
|
|
|
else |
264
|
|
|
{ |
265
|
415 |
|
return Jam::$_model_prefix.Jam::capitalize_class_name($model); |
|
|
|
|
266
|
|
|
} |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
/** |
270
|
|
|
* Returns the model name of a class |
271
|
|
|
* |
272
|
|
|
* @param string|Jam_Validated $model |
273
|
|
|
* @return string |
274
|
|
|
*/ |
275
|
644 |
|
public static function model_name($model) |
276
|
|
|
{ |
277
|
644 |
|
if ($model instanceof Jam_Validated) |
278
|
644 |
|
{ |
279
|
644 |
|
$model = get_class($model); |
280
|
644 |
|
} |
281
|
|
|
|
282
|
644 |
|
$prefix_length = strlen(Jam::$_model_prefix); |
|
|
|
|
283
|
|
|
|
284
|
|
|
// Compare the first parts of the names and chomp if they're the same |
285
|
644 |
|
if (strtolower(substr($model, 0, $prefix_length)) === strtolower(Jam::$_model_prefix)) |
|
|
|
|
286
|
644 |
|
{ |
287
|
644 |
|
$model = substr($model, $prefix_length); |
288
|
644 |
|
} |
289
|
|
|
|
290
|
644 |
|
return strtolower($model); |
291
|
|
|
} |
292
|
|
|
|
293
|
|
|
/** |
294
|
|
|
* Returns the prefix to use for all models and collections. |
295
|
|
|
* |
296
|
|
|
* @return string |
297
|
|
|
*/ |
298
|
|
|
public static function model_prefix() |
299
|
|
|
{ |
300
|
|
|
return Jam::$_model_prefix; |
|
|
|
|
301
|
|
|
} |
302
|
|
|
|
303
|
|
|
/** |
304
|
|
|
* Returns the prefix to use for all models and collections. |
305
|
|
|
* |
306
|
|
|
* @return string |
307
|
|
|
*/ |
308
|
2 |
|
public static function collection_prefix() |
309
|
|
|
{ |
310
|
2 |
|
return Jam::$_collection_prefix; |
|
|
|
|
311
|
|
|
} |
312
|
|
|
|
313
|
|
|
/** |
314
|
|
|
* Returns the prefix to use for all fields. |
315
|
|
|
* |
316
|
|
|
* @return string |
317
|
|
|
*/ |
318
|
|
|
public static function field_prefix() |
319
|
|
|
{ |
320
|
|
|
return Jam::$_field_prefix; |
|
|
|
|
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
/** |
324
|
|
|
* Returns the prefix to use for forms. |
325
|
|
|
* |
326
|
|
|
* @return string |
327
|
|
|
*/ |
328
|
|
|
public static function form_prefix() |
329
|
|
|
{ |
330
|
|
|
return Jam::$_form_prefix; |
|
|
|
|
331
|
|
|
} |
332
|
|
|
|
333
|
|
|
|
334
|
|
|
/** |
335
|
|
|
* Returns the prefix to use for all behaviors. |
336
|
|
|
* |
337
|
|
|
* @return string |
338
|
|
|
*/ |
339
|
2 |
|
public static function behavior_prefix() |
340
|
|
|
{ |
341
|
2 |
|
return Jam::$_behavior_prefix; |
|
|
|
|
342
|
|
|
} |
343
|
|
|
|
344
|
|
|
/** |
345
|
|
|
* Clear the cache of the models. You should do this only when you dynamically change models |
346
|
|
|
* @param string $name optionally clear only one model |
347
|
|
|
*/ |
348
|
|
|
public static function clear_cache($name = NULL) |
349
|
|
|
{ |
350
|
|
|
if ($name !== NULL) |
351
|
|
|
{ |
352
|
|
|
unset(Jam::$_models[$name]); |
353
|
|
|
} |
354
|
|
|
else |
355
|
|
|
{ |
356
|
|
|
Jam::$_models = array(); |
357
|
|
|
} |
358
|
|
|
} |
359
|
|
|
|
360
|
|
|
/** |
361
|
|
|
* Make an object of class Jam_Query_Builder_Delete |
362
|
|
|
* @param string $model |
363
|
|
|
* @return Jam_Query_Builder_Delete |
364
|
|
|
*/ |
365
|
10 |
|
public static function delete($model) |
366
|
|
|
{ |
367
|
10 |
|
return new Jam_Query_Builder_Delete($model); |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
/** |
371
|
|
|
* Make an object of class Jam_Query_Builder_Update |
372
|
|
|
* @param string $model |
373
|
|
|
* @return Jam_Query_Builder_Update |
374
|
|
|
*/ |
375
|
17 |
|
public static function update($model) |
376
|
|
|
{ |
377
|
17 |
|
return new Jam_Query_Builder_Update($model); |
378
|
|
|
} |
379
|
|
|
|
380
|
|
|
/** |
381
|
|
|
* Make an object of class Jam_Query_Builder_Insert |
382
|
|
|
* @param string $model |
383
|
|
|
* @return Jam_Query_Builder_Insert |
384
|
|
|
*/ |
385
|
9 |
|
public static function insert($model, array $columns = array()) |
386
|
|
|
{ |
387
|
9 |
|
return Jam_Query_Builder_Insert::factory($model, $columns); |
388
|
|
|
} |
389
|
|
|
|
390
|
|
|
/** |
391
|
|
|
* Make an object of class Jam_Query_Builder_Select |
392
|
|
|
* @param string $model |
393
|
|
|
* @return Jam_Query_Builder_Select |
394
|
|
|
*/ |
395
|
2 |
|
public static function select($model) |
396
|
|
|
{ |
397
|
2 |
|
return new Jam_Query_Builder_Select($model); |
398
|
|
|
} |
399
|
|
|
|
400
|
|
|
/** |
401
|
|
|
* Make an object of class Jam_Query_Builder_Collection |
402
|
|
|
* @param string $model |
403
|
|
|
* @return Jam_Query_Builder_Collection |
404
|
|
|
*/ |
405
|
47 |
|
public static function all($model) |
406
|
|
|
{ |
407
|
47 |
|
if ( ! ($meta = Jam::meta($model))) |
408
|
47 |
|
throw new Kohana_Exception('Model :model does not exist', array(':model' => $model)); |
409
|
|
|
|
410
|
47 |
|
$class = $meta->collection(); |
411
|
|
|
|
412
|
47 |
|
if ( ! $class) |
413
|
47 |
|
{ |
414
|
45 |
|
$class = 'Jam_Query_Builder_Collection'; |
415
|
45 |
|
} |
416
|
47 |
|
return new $class($model); |
417
|
|
|
} |
418
|
|
|
|
419
|
1 |
|
protected static function find_or($method, $model, array $values) |
420
|
|
|
{ |
421
|
1 |
|
$collection = Jam::all($model); |
422
|
1 |
|
$converted_keys = array(); |
423
|
1 |
|
foreach ($values as $key => $value) |
424
|
|
|
{ |
425
|
1 |
|
$key = Jam_Query_Builder::resolve_meta_attribute($key, Jam::meta($model), $value); |
426
|
|
|
|
427
|
1 |
|
$collection->where($key, '=', $value); |
428
|
1 |
|
$converted_keys[$key] = $value; |
429
|
1 |
|
} |
430
|
|
|
|
431
|
1 |
|
if ($item = $collection->first()) |
432
|
1 |
|
return $item; |
433
|
|
|
|
434
|
1 |
|
return call_user_func($method, $model, $converted_keys); |
435
|
|
|
} |
436
|
|
|
|
437
|
|
|
/** |
438
|
|
|
* Try to find a model with the given fields, if one cannot be found, |
439
|
|
|
* build it and set the fields we've search with to it. |
440
|
|
|
* @param string $model |
441
|
|
|
* @param array $values |
442
|
|
|
* @return Jam_Model |
443
|
|
|
*/ |
444
|
|
|
public static function find_or_build($model, array $values) |
445
|
|
|
{ |
446
|
|
|
return Jam::find_or('Jam::build', $model, $values); |
|
|
|
|
447
|
|
|
} |
448
|
|
|
|
449
|
|
|
/** |
450
|
|
|
* Try to find a model with the given fields, if one cannot be found, |
451
|
|
|
* create it and set the fields we've search with to it. Save the model to the database. |
452
|
|
|
* @param string $model |
453
|
|
|
* @param array $values |
454
|
|
|
* @return Jam_Model |
455
|
|
|
*/ |
456
|
1 |
|
public static function find_or_create($model, array $values) |
457
|
|
|
{ |
458
|
1 |
|
return Jam::find_or('Jam::create', $model, $values); |
|
|
|
|
459
|
|
|
} |
460
|
|
|
|
461
|
|
|
/** |
462
|
|
|
* Find a model with its unique key. Return NULL on failure. |
463
|
|
|
* You can pass an array - then it tries to find all the models corresponding to the keys |
464
|
|
|
* @param string $model |
465
|
|
|
* @param string|array $key |
466
|
|
|
* @return Jam_Model |
467
|
|
|
*/ |
468
|
23 |
|
public static function find($model, $key) |
469
|
|
|
{ |
470
|
23 |
|
if ( ! $key) |
471
|
23 |
|
throw new Jam_Exception_Invalidargument(':model - no id specified', $model); |
472
|
|
|
|
473
|
21 |
|
$collection = Jam::all($model); |
474
|
21 |
|
$collection->where_key($key); |
475
|
21 |
|
return is_array($key) ? $collection : $collection->first(); |
|
|
|
|
476
|
|
|
} |
477
|
|
|
|
478
|
|
|
/** |
479
|
|
|
* Find a model with its unique key. Throw Jam_Exception_Notfound on failure |
480
|
|
|
* You can pass an array of unique keys. If even one of them is not found, through Jam_Exception_Notfound |
481
|
|
|
* @param string $model |
482
|
|
|
* @param string|array $key |
483
|
|
|
* @throws Jam_Exception_Invalidargument If id is array() or null |
484
|
|
|
* @throws Jam_Exception_Notfound If no model was found |
485
|
|
|
* @return Jam_Model |
486
|
|
|
*/ |
487
|
7 |
|
public static function find_insist($model, $key) |
488
|
|
|
{ |
489
|
7 |
|
if ( ! $key) |
490
|
7 |
|
throw new Jam_Exception_Invalidargument(':model - no id specified', $model); |
491
|
|
|
|
492
|
5 |
|
$result = Jam::find($model, $key); |
493
|
|
|
|
494
|
5 |
|
if (is_array($key)) |
495
|
5 |
|
{ |
496
|
2 |
|
$missing = array_diff(array_values($key), array_values($result->ids())); |
|
|
|
|
497
|
2 |
|
} |
498
|
|
|
else |
499
|
|
|
{ |
500
|
4 |
|
$missing = $result ? array() : array($key); |
501
|
|
|
} |
502
|
|
|
|
503
|
|
|
if ($missing) |
|
|
|
|
504
|
5 |
|
throw new Jam_Exception_Notfound(':model (:missing) not found', $model, array(':missing' => join(', ', $missing))); |
505
|
|
|
|
506
|
3 |
|
return $result; |
507
|
|
|
} |
508
|
|
|
|
509
|
|
|
/** |
510
|
|
|
* Filter the $data array by removing everything that does not have a key in the permit array |
511
|
|
|
* @param array $permit array of permitted keys |
512
|
|
|
* @param array $data |
513
|
|
|
* @return array |
514
|
|
|
*/ |
515
|
1 |
|
public static function permit(array $permit = array(), array $data = array()) |
516
|
|
|
{ |
517
|
1 |
|
return Jam_Validator_Attributes::factory($permit)->data($data)->clean(); |
518
|
|
|
} |
519
|
|
|
|
520
|
14 |
|
public static function form($model, $class = NULL) |
521
|
|
|
{ |
522
|
14 |
|
if ($class === NULL) |
523
|
14 |
|
{ |
524
|
5 |
|
$class = Kohana::$config->load('jam.default_form'); |
525
|
5 |
|
} |
526
|
|
|
|
527
|
14 |
|
$class = Jam::capitalize_class_name($class); |
528
|
|
|
|
529
|
14 |
|
if (is_string($model)) |
530
|
14 |
|
{ |
531
|
|
|
$model = Jam::build($model); |
532
|
|
|
} |
533
|
|
|
|
534
|
14 |
|
if (class_exists(Jam::$_form_prefix.$class)) |
|
|
|
|
535
|
14 |
|
{ |
536
|
14 |
|
$class = Jam::$_form_prefix.$class; |
|
|
|
|
537
|
14 |
|
} |
538
|
|
|
|
539
|
14 |
|
return new $class($model); |
540
|
|
|
} |
541
|
|
|
|
542
|
45 |
|
public static function build_template($model_name, array $values = NULL) |
543
|
|
|
{ |
544
|
45 |
|
$meta = Jam::meta($model_name); |
545
|
|
|
|
546
|
45 |
|
$model_name = ($meta AND $meta->polymorphic_key()) ? Arr::get($values, $meta->polymorphic_key(), $model_name) : $model_name; |
|
|
|
|
547
|
|
|
|
548
|
45 |
|
if ( ! isset(Jam::$_build_templates[$model_name])) |
|
|
|
|
549
|
45 |
|
{ |
550
|
6 |
|
Jam::$_build_templates[$model_name] = Jam::build($model_name); |
|
|
|
|
551
|
6 |
|
} |
552
|
|
|
|
553
|
45 |
|
return Jam::$_build_templates[$model_name]; |
|
|
|
|
554
|
|
|
} |
555
|
|
|
|
556
|
|
|
} // End Kohana_Jam |
557
|
|
|
|
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.