This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php defined('SYSPATH') or die('No direct access allowed.'); |
||
2 | /** |
||
3 | * [Object Relational Mapping][ref-orm] (ORM) is a method of abstracting database |
||
4 | * access to standard PHP calls. All table rows are represented as model objects, |
||
5 | * with object properties representing row data. ORM in Kohana generally follows |
||
6 | * the [Active Record][ref-act] pattern. |
||
7 | * |
||
8 | * [ref-orm]: http://wikipedia.org/wiki/Object-relational_mapping |
||
9 | * [ref-act]: http://wikipedia.org/wiki/Active_record |
||
10 | * |
||
11 | * $Id: ORM.php 4354 2009-05-15 16:51:37Z kiall $ |
||
12 | * |
||
13 | * @package ORM |
||
14 | * @author Kohana Team |
||
15 | * @copyright (c) 2007-2008 Kohana Team |
||
16 | * @license http://kohanaphp.com/license.html |
||
17 | */ |
||
18 | class ORM_Core |
||
19 | { |
||
20 | |||
21 | // Current relationships |
||
22 | protected $has_one = array(); |
||
23 | protected $belongs_to = array(); |
||
24 | protected $has_many = array(); |
||
25 | protected $has_and_belongs_to_many = array(); |
||
0 ignored issues
–
show
|
|||
26 | |||
27 | // Relationships that should always be joined |
||
28 | protected $load_with = array(); |
||
29 | |||
30 | // Current object |
||
31 | protected $object = array(); |
||
32 | protected $changed = array(); |
||
33 | protected $related = array(); |
||
34 | protected $loaded = false; |
||
35 | protected $saved = false; |
||
36 | protected $sorting; |
||
37 | |||
38 | // Related objects |
||
39 | protected $object_relations = array(); |
||
40 | protected $changed_relations = array(); |
||
41 | |||
42 | // Model table information |
||
43 | protected $object_name; |
||
44 | protected $object_plural; |
||
45 | protected $table_name; |
||
46 | protected $table_columns; |
||
47 | protected $ignored_columns; |
||
48 | |||
49 | // Table primary key and value |
||
50 | protected $primary_key = 'id'; |
||
51 | protected $primary_val = 'name'; |
||
52 | |||
53 | // Array of foreign key name overloads |
||
54 | protected $foreign_key = array(); |
||
55 | |||
56 | // Model configuration |
||
57 | protected $table_names_plural = true; |
||
58 | protected $reload_on_wakeup = true; |
||
59 | |||
60 | // Database configuration |
||
61 | protected $db = 'default'; |
||
0 ignored issues
–
show
|
|||
62 | protected $db_applied = array(); |
||
63 | |||
64 | // With calls already applied |
||
65 | protected $with_applied = array(); |
||
66 | |||
67 | // Stores column information for ORM models |
||
68 | protected static $column_cache = array(); |
||
69 | |||
70 | /** |
||
71 | * Creates and returns a new model. |
||
72 | * |
||
73 | * @chainable |
||
74 | * @param string model name |
||
75 | * @param mixed parameter for find() |
||
76 | * @return ORM |
||
77 | */ |
||
78 | public static function factory($model, $id = null) |
||
79 | { |
||
80 | // Set class name |
||
81 | $model = ucfirst($model).'_Model'; |
||
82 | |||
83 | return new $model($id); |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * Prepares the model database connection and loads the object. |
||
88 | * |
||
89 | * @param mixed parameter for find or object to load |
||
90 | * @return void |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Adding a
@return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.
Adding a Please refer to the PHP core documentation on constructors. ![]() |
|||
91 | */ |
||
92 | public function __construct($id = null) |
||
93 | { |
||
94 | // Set the object name and plural name |
||
95 | $this->object_name = strtolower(substr(get_class($this), 0, -6)); |
||
96 | $this->object_plural = inflector::plural($this->object_name); |
||
97 | |||
98 | if (!isset($this->sorting)) { |
||
99 | // Default sorting |
||
100 | $this->sorting = array($this->primary_key => 'asc'); |
||
101 | } |
||
102 | |||
103 | // Initialize database |
||
104 | $this->__initialize(); |
||
105 | |||
106 | // Clear the object |
||
107 | $this->clear(); |
||
108 | |||
109 | if (is_object($id)) { |
||
110 | // Load an object |
||
111 | $this->load_values((array) $id); |
||
112 | } elseif (!empty($id)) { |
||
113 | // Find an object |
||
114 | $this->find($id); |
||
115 | } |
||
116 | } |
||
117 | |||
118 | /** |
||
119 | * Prepares the model database connection, determines the table name, |
||
120 | * and loads column information. |
||
121 | * |
||
122 | * @return void |
||
123 | */ |
||
124 | public function __initialize() |
||
125 | { |
||
126 | if (! is_object($this->db)) { |
||
127 | // Get database instance |
||
128 | $this->db = Database::instance($this->db); |
||
129 | } |
||
130 | |||
131 | if (empty($this->table_name)) { |
||
132 | // Table name is the same as the object name |
||
133 | $this->table_name = $this->object_name; |
||
134 | |||
135 | if ($this->table_names_plural === true) { |
||
136 | // Make the table name plural |
||
137 | $this->table_name = inflector::plural($this->table_name); |
||
138 | } |
||
139 | } |
||
140 | |||
141 | if (is_array($this->ignored_columns)) { |
||
142 | // Make the ignored columns mirrored = mirrored |
||
143 | $this->ignored_columns = array_combine($this->ignored_columns, $this->ignored_columns); |
||
144 | } |
||
145 | |||
146 | // Load column information |
||
147 | $this->reload_columns(); |
||
148 | } |
||
149 | |||
150 | /** |
||
151 | * Allows serialization of only the object data and state, to prevent |
||
152 | * "stale" objects being unserialized, which also requires less memory. |
||
153 | * |
||
154 | * @return string[] |
||
155 | */ |
||
156 | public function __sleep() |
||
157 | { |
||
158 | // Store only information about the object |
||
159 | return array('object_name', 'object', 'changed', 'loaded', 'saved', 'sorting'); |
||
160 | } |
||
161 | |||
162 | /** |
||
163 | * Prepares the database connection and reloads the object. |
||
164 | * |
||
165 | * @return void |
||
166 | */ |
||
167 | public function __wakeup() |
||
168 | { |
||
169 | // Initialize database |
||
170 | $this->__initialize(); |
||
171 | |||
172 | if ($this->reload_on_wakeup === true) { |
||
173 | // Reload the object |
||
174 | $this->reload(); |
||
175 | } |
||
176 | } |
||
177 | |||
178 | /** |
||
179 | * Handles pass-through to database methods. Calls to query methods |
||
180 | * (query, get, insert, update) are not allowed. Query builder methods |
||
181 | * are chainable. |
||
182 | * |
||
183 | * @param string method name |
||
184 | * @param array method arguments |
||
185 | * @return mixed |
||
186 | */ |
||
187 | public function __call($method, array $args) |
||
188 | { |
||
189 | if (method_exists($this->db, $method)) { |
||
190 | if (in_array($method, array('query', 'get', 'insert', 'update', 'delete'))) { |
||
191 | throw new Kohana_Exception('orm.query_methods_not_allowed'); |
||
192 | } |
||
193 | |||
194 | // Method has been applied to the database |
||
195 | $this->db_applied[$method] = $method; |
||
196 | |||
197 | // Number of arguments passed |
||
198 | $num_args = count($args); |
||
199 | |||
200 | if ($method === 'select' and $num_args > 3) { |
||
201 | // Call select() manually to avoid call_user_func_array |
||
202 | $this->db->select($args); |
||
0 ignored issues
–
show
|
|||
203 | } else { |
||
204 | // We use switch here to manually call the database methods. This is |
||
205 | // done for speed: call_user_func_array can take over 300% longer to |
||
206 | // make calls. Most database methods are 4 arguments or less, so this |
||
207 | // avoids almost any calls to call_user_func_array. |
||
208 | |||
209 | switch ($num_args) { |
||
210 | case 0: |
||
211 | if (in_array($method, array('open_paren', 'close_paren', 'enable_cache', 'disable_cache'))) { |
||
212 | // Should return ORM, not Database |
||
213 | $this->db->$method(); |
||
0 ignored issues
–
show
|
|||
214 | } else { |
||
215 | // Support for things like reset_select, reset_write, list_tables |
||
216 | return $this->db->$method(); |
||
0 ignored issues
–
show
|
|||
217 | } |
||
218 | break; |
||
219 | case 1: |
||
220 | $this->db->$method($args[0]); |
||
0 ignored issues
–
show
|
|||
221 | break; |
||
222 | case 2: |
||
223 | $this->db->$method($args[0], $args[1]); |
||
0 ignored issues
–
show
|
|||
224 | break; |
||
225 | View Code Duplication | case 3: |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
226 | $this->db->$method($args[0], $args[1], $args[2]); |
||
0 ignored issues
–
show
|
|||
227 | break; |
||
228 | View Code Duplication | case 4: |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
229 | $this->db->$method($args[0], $args[1], $args[2], $args[3]); |
||
0 ignored issues
–
show
|
|||
230 | break; |
||
231 | default: |
||
232 | // Here comes the snail... |
||
233 | call_user_func_array(array($this->db, $method), $args); |
||
234 | break; |
||
235 | } |
||
236 | } |
||
237 | |||
238 | return $this; |
||
239 | } else { |
||
240 | throw new Kohana_Exception('core.invalid_method', $method, get_class($this)); |
||
241 | } |
||
242 | } |
||
243 | |||
244 | /** |
||
245 | * Handles retrieval of all model values, relationships, and metadata. |
||
246 | * |
||
247 | * @param string column name |
||
248 | * @return mixed |
||
249 | */ |
||
250 | public function __get($column) |
||
251 | { |
||
252 | if (array_key_exists($column, $this->object)) { |
||
253 | return $this->object[$column]; |
||
254 | } elseif (isset($this->related[$column])) { |
||
255 | return $this->related[$column]; |
||
256 | } elseif ($column === 'primary_key_value') { |
||
257 | return $this->object[$this->primary_key]; |
||
258 | } elseif ($model = $this->related_object($column)) { |
||
259 | // This handles the has_one and belongs_to relationships |
||
260 | |||
261 | if (in_array($model->object_name, $this->belongs_to) or ! array_key_exists($this->foreign_key($column), $model->object)) { |
||
262 | // Foreign key lies in this table (this model belongs_to target model) OR an invalid has_one relationship |
||
263 | $where = array($model->table_name.'.'.$model->primary_key => $this->object[$this->foreign_key($column)]); |
||
264 | } else { |
||
265 | // Foreign key lies in the target table (this model has_one target model) |
||
266 | $where = array($this->foreign_key($column, $model->table_name) => $this->primary_key_value); |
||
0 ignored issues
–
show
The property
primary_key_value does not seem to exist. Did you mean primary_key ?
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
267 | } |
||
268 | |||
269 | // one<>alias:one relationship |
||
270 | return $this->related[$column] = $model->find($where); |
||
271 | } elseif (isset($this->has_many[$column])) { |
||
272 | // Load the "middle" model |
||
273 | $through = ORM::factory(inflector::singular($this->has_many[$column])); |
||
274 | |||
275 | // Load the "end" model |
||
276 | $model = ORM::factory(inflector::singular($column)); |
||
277 | |||
278 | // Join ON target model's primary key set to 'through' model's foreign key |
||
279 | // User-defined foreign keys must be defined in the 'through' model |
||
280 | $join_table = $through->table_name; |
||
281 | $join_col1 = $through->foreign_key($model->object_name, $join_table); |
||
282 | $join_col2 = $model->table_name.'.'.$model->primary_key; |
||
283 | |||
284 | // one<>alias:many relationship |
||
285 | return $this->related[$column] = $model |
||
286 | ->join($join_table, $join_col1, $join_col2) |
||
287 | ->where($through->foreign_key($this->object_name, $join_table), $this->object[$this->primary_key]) |
||
288 | ->find_all(); |
||
289 | } elseif (in_array($column, $this->has_many)) { |
||
290 | // one<>many relationship |
||
291 | $model = ORM::factory(inflector::singular($column)); |
||
292 | return $this->related[$column] = $model |
||
293 | ->where($this->foreign_key($column, $model->table_name), $this->object[$this->primary_key]) |
||
294 | ->find_all(); |
||
295 | } elseif (in_array($column, $this->has_and_belongs_to_many)) { |
||
296 | // Load the remote model, always singular |
||
297 | $model = ORM::factory(inflector::singular($column)); |
||
298 | |||
299 | if ($this->has($model, true)) { |
||
300 | // many<>many relationship |
||
301 | return $this->related[$column] = $model |
||
302 | ->in($model->table_name.'.'.$model->primary_key, $this->changed_relations[$column]) |
||
303 | ->find_all(); |
||
304 | } else { |
||
305 | // empty many<>many relationship |
||
306 | return $this->related[$column] = $model |
||
307 | ->where($model->table_name.'.'.$model->primary_key, null) |
||
308 | ->find_all(); |
||
309 | } |
||
310 | } elseif (isset($this->ignored_columns[$column])) { |
||
311 | return null; |
||
312 | } elseif (in_array($column, array( |
||
313 | 'object_name', 'object_plural', // Object |
||
314 | 'primary_key', 'primary_val', 'table_name', 'table_columns', // Table |
||
315 | 'loaded', 'saved', // Status |
||
316 | 'has_one', 'belongs_to', 'has_many', 'has_and_belongs_to_many', 'load_with' // Relationships |
||
317 | ))) { |
||
318 | // Model meta information |
||
319 | return $this->$column; |
||
320 | } else { |
||
321 | throw new Kohana_Exception('core.invalid_property', $column, get_class($this)); |
||
322 | } |
||
323 | } |
||
324 | |||
325 | /** |
||
326 | * Handles setting of all model values, and tracks changes between values. |
||
327 | * |
||
328 | * @param string column name |
||
329 | * @param mixed column value |
||
330 | * @return void |
||
331 | */ |
||
332 | public function __set($column, $value) |
||
333 | { |
||
334 | if (isset($this->ignored_columns[$column])) { |
||
335 | return null; |
||
336 | } elseif (isset($this->object[$column]) or array_key_exists($column, $this->object)) { |
||
337 | if (isset($this->table_columns[$column])) { |
||
338 | // Data has changed |
||
339 | $this->changed[$column] = $column; |
||
340 | |||
341 | // Object is no longer saved |
||
342 | $this->saved = false; |
||
343 | } |
||
344 | |||
345 | $this->object[$column] = $this->load_type($column, $value); |
||
346 | } elseif (in_array($column, $this->has_and_belongs_to_many) and is_array($value)) { |
||
347 | // Load relations |
||
348 | $model = ORM::factory(inflector::singular($column)); |
||
349 | |||
350 | if (! isset($this->object_relations[$column])) { |
||
351 | // Load relations |
||
352 | $this->has($model); |
||
353 | } |
||
354 | |||
355 | // Change the relationships |
||
356 | $this->changed_relations[$column] = $value; |
||
357 | |||
358 | if (isset($this->related[$column])) { |
||
359 | // Force a reload of the relationships |
||
360 | unset($this->related[$column]); |
||
361 | } |
||
362 | } else { |
||
363 | throw new Kohana_Exception('core.invalid_property', $column, get_class($this)); |
||
364 | } |
||
365 | } |
||
366 | |||
367 | /** |
||
368 | * Checks if object data is set. |
||
369 | * |
||
370 | * @param string column name |
||
371 | * @return boolean |
||
372 | */ |
||
373 | public function __isset($column) |
||
374 | { |
||
375 | return (isset($this->object[$column]) or isset($this->related[$column])); |
||
376 | } |
||
377 | |||
378 | /** |
||
379 | * Unsets object data. |
||
380 | * |
||
381 | * @param string column name |
||
382 | * @return void |
||
383 | */ |
||
384 | public function __unset($column) |
||
385 | { |
||
386 | unset($this->object[$column], $this->changed[$column], $this->related[$column]); |
||
387 | } |
||
388 | |||
389 | /** |
||
390 | * Displays the primary key of a model when it is converted to a string. |
||
391 | * |
||
392 | * @return string |
||
393 | */ |
||
394 | public function __toString() |
||
395 | { |
||
396 | return (string) $this->object[$this->primary_key]; |
||
397 | } |
||
398 | |||
399 | /** |
||
400 | * Returns the values of this object as an array. |
||
401 | * |
||
402 | * @return array |
||
403 | */ |
||
404 | public function as_array() |
||
405 | { |
||
406 | $object = array(); |
||
407 | |||
408 | foreach ($this->object as $key => $val) { |
||
409 | // Reconstruct the array (calls __get) |
||
410 | $object[$key] = $this->$key; |
||
411 | } |
||
412 | |||
413 | return $object; |
||
414 | } |
||
415 | |||
416 | /** |
||
417 | * Binds another one-to-one object to this model. One-to-one objects |
||
418 | * can be nested using 'object1:object2' syntax |
||
419 | * |
||
420 | * @param string $target_path |
||
421 | * @return ORM_Core |
||
422 | */ |
||
423 | public function with($target_path) |
||
424 | { |
||
425 | if (isset($this->with_applied[$target_path])) { |
||
426 | // Don't join anything already joined |
||
427 | return $this; |
||
428 | } |
||
429 | |||
430 | // Split object parts |
||
431 | $objects = explode(':', $target_path); |
||
432 | $target = $this; |
||
433 | foreach ($objects as $object) { |
||
434 | // Go down the line of objects to find the given target |
||
435 | $parent = $target; |
||
436 | $target = $parent->related_object($object); |
||
437 | |||
438 | if (! $target) { |
||
439 | // Can't find related object |
||
440 | return $this; |
||
441 | } |
||
442 | } |
||
443 | |||
444 | $target_name = $object; |
||
0 ignored issues
–
show
The variable
$object seems to be defined by a foreach iteration on line 433 . Are you sure the iterator is never empty, otherwise this variable is not defined?
It seems like you are relying on a variable being defined by an iteration: foreach ($a as $b) {
}
// $b is defined here only if $a has elements, for example if $a is array()
// then $b would not be defined here. To avoid that, we recommend to set a
// default value for $b.
// Better
$b = 0; // or whatever default makes sense in your context
foreach ($a as $b) {
}
// $b is now guaranteed to be defined here.
![]() |
|||
445 | |||
446 | // Pop-off top object to get the parent object (user:photo:tag becomes user:photo - the parent table prefix) |
||
447 | array_pop($objects); |
||
448 | $parent_path = implode(':', $objects); |
||
449 | |||
450 | if (empty($parent_path)) { |
||
451 | // Use this table name itself for the parent object |
||
452 | $parent_path = $this->table_name; |
||
453 | } else { |
||
454 | if (! isset($this->with_applied[$parent_path])) { |
||
455 | // If the parent object hasn't been joined yet, do it first (otherwise LEFT JOINs fail) |
||
456 | $this->with($parent_path); |
||
457 | } |
||
458 | } |
||
459 | |||
460 | // Add to with_applied to prevent duplicate joins |
||
461 | $this->with_applied[$target_path] = true; |
||
462 | |||
463 | // Use the keys of the empty object to determine the columns |
||
464 | $select = array_keys($target->object); |
||
465 | foreach ($select as $i => $column) { |
||
466 | // Add the prefix so that load_result can determine the relationship |
||
467 | $select[$i] = $target_path.'.'.$column.' AS '.$target_path.':'.$column; |
||
468 | } |
||
469 | |||
470 | |||
471 | // Select all of the prefixed keys in the object |
||
472 | $this->db->select($select); |
||
0 ignored issues
–
show
|
|||
473 | |||
474 | if (in_array($target->object_name, $parent->belongs_to) or ! isset($target->object[$parent->foreign_key($target_name)])) { |
||
475 | // Parent belongs_to target, use target's primary key as join column |
||
476 | $join_col1 = $target->foreign_key(true, $target_path); |
||
477 | $join_col2 = $parent->foreign_key($target_name, $parent_path); |
||
0 ignored issues
–
show
The variable
$parent does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
478 | } else { |
||
479 | // Parent has_one target, use parent's primary key as join column |
||
480 | $join_col2 = $parent->foreign_key(true, $parent_path); |
||
481 | $join_col1 = $parent->foreign_key($target_name, $target_path); |
||
482 | } |
||
483 | |||
484 | // This allows for models to use different table prefixes (sharing the same database) |
||
485 | $join_table = new Database_Expression($target->db->table_prefix().$target->table_name.' AS '.$this->db->table_prefix().$target_path); |
||
0 ignored issues
–
show
|
|||
486 | |||
487 | // Join the related object into the result |
||
488 | $this->db->join($join_table, $join_col1, $join_col2, 'LEFT'); |
||
0 ignored issues
–
show
|
|||
489 | |||
490 | return $this; |
||
491 | } |
||
492 | |||
493 | /** |
||
494 | * Finds and loads a single database row into the object. |
||
495 | * |
||
496 | * @chainable |
||
497 | * @param mixed primary key or an array of clauses |
||
498 | * @return ORM |
||
0 ignored issues
–
show
|
|||
499 | */ |
||
500 | public function find($id = null) |
||
501 | { |
||
502 | if ($id !== null) { |
||
503 | if (is_array($id)) { |
||
504 | // Search for all clauses |
||
505 | $this->db->where($id); |
||
0 ignored issues
–
show
|
|||
506 | } else { |
||
507 | // Search for a specific column |
||
508 | $this->db->where($this->table_name.'.'.$this->unique_key($id), $id); |
||
0 ignored issues
–
show
|
|||
509 | } |
||
510 | } |
||
511 | |||
512 | return $this->load_result(); |
||
513 | } |
||
514 | |||
515 | /** |
||
516 | * Finds multiple database rows and returns an iterator of the rows found. |
||
517 | * |
||
518 | * @chainable |
||
519 | * @param integer SQL limit |
||
520 | * @param integer SQL offset |
||
521 | * @return ORM_Iterator |
||
522 | */ |
||
523 | public function find_all($limit = null, $offset = null) |
||
524 | { |
||
525 | if ($limit !== null and ! isset($this->db_applied['limit'])) { |
||
526 | // Set limit |
||
527 | $this->limit($limit); |
||
0 ignored issues
–
show
The method
limit does not exist on object<ORM_Core> ? Since you implemented __call , maybe consider adding a @method annotation.
If you implement This is often the case, when class ParentClass {
private $data = array();
public function __call($method, array $args) {
if (0 === strpos($method, 'get')) {
return $this->data[strtolower(substr($method, 3))];
}
throw new \LogicException(sprintf('Unsupported method: %s', $method));
}
}
/**
* If this class knows which fields exist, you can specify the methods here:
*
* @method string getName()
*/
class SomeClass extends ParentClass { }
![]() |
|||
528 | } |
||
529 | |||
530 | if ($offset !== null and ! isset($this->db_applied['offset'])) { |
||
531 | // Set offset |
||
532 | $this->offset($offset); |
||
0 ignored issues
–
show
The method
offset does not exist on object<ORM_Core> ? Since you implemented __call , maybe consider adding a @method annotation.
If you implement This is often the case, when class ParentClass {
private $data = array();
public function __call($method, array $args) {
if (0 === strpos($method, 'get')) {
return $this->data[strtolower(substr($method, 3))];
}
throw new \LogicException(sprintf('Unsupported method: %s', $method));
}
}
/**
* If this class knows which fields exist, you can specify the methods here:
*
* @method string getName()
*/
class SomeClass extends ParentClass { }
![]() |
|||
533 | } |
||
534 | |||
535 | return $this->load_result(true); |
||
0 ignored issues
–
show
|
|||
536 | } |
||
537 | |||
538 | /** |
||
539 | * Creates a key/value array from all of the objects available. Uses find_all |
||
540 | * to find the objects. |
||
541 | * |
||
542 | * @param string key column |
||
543 | * @param string value column |
||
544 | * @return array |
||
545 | */ |
||
546 | public function select_list($key = null, $val = null) |
||
547 | { |
||
548 | if ($key === null) { |
||
549 | $key = $this->primary_key; |
||
550 | } |
||
551 | |||
552 | if ($val === null) { |
||
553 | $val = $this->primary_val; |
||
554 | } |
||
555 | |||
556 | // Return a select list from the results |
||
557 | return $this->select($key, $val)->find_all()->select_list($key, $val); |
||
0 ignored issues
–
show
|
|||
558 | } |
||
559 | |||
560 | /** |
||
561 | * Validates the current object. This method should generally be called |
||
562 | * via the model, after the $_POST Validation object has been created. |
||
563 | * |
||
564 | * @param object Validation array |
||
565 | * @return boolean |
||
566 | */ |
||
567 | public function validate(Validation $array, $save = false) |
||
568 | { |
||
569 | $safe_array = $array->safe_array(); |
||
570 | |||
571 | if (! $array->submitted()) { |
||
572 | foreach ($safe_array as $key => $value) { |
||
573 | // Get the value from this object |
||
574 | $value = $this->$key; |
||
575 | |||
576 | if (is_object($value) and $value instanceof ORM_Iterator) { |
||
0 ignored issues
–
show
The class
ORM_Iterator does not exist. Did you forget a USE statement, or did you not list all dependencies?
This error could be the result of: 1. Missing dependenciesPHP Analyzer uses your Are you sure this class is defined by one of your dependencies, or did you maybe
not list a dependency in either the 2. Missing use statementPHP does not complain about undefined classes in if ($x instanceof DoesNotExist) {
// Do something.
}
If you have not tested against this specific condition, such errors might go unnoticed. ![]() |
|||
577 | // Convert the value to an array of primary keys |
||
578 | $value = $value->primary_key_array(); |
||
579 | } |
||
580 | |||
581 | // Pre-fill data |
||
582 | $array[$key] = $value; |
||
583 | } |
||
584 | } |
||
585 | |||
586 | // Validate the array |
||
587 | if ($status = $array->validate()) { |
||
588 | // Grab only set fields (excludes missing data, unlike safe_array) |
||
589 | $fields = $array->as_array(); |
||
590 | |||
591 | foreach ($fields as $key => $value) { |
||
592 | if (isset($safe_array[$key])) { |
||
593 | // Set new data, ignoring any missing fields or fields without rules |
||
594 | $this->$key = $value; |
||
595 | } |
||
596 | } |
||
597 | |||
598 | if ($save === true or is_string($save)) { |
||
599 | // Save this object |
||
600 | $this->save(); |
||
601 | |||
602 | if (is_string($save)) { |
||
603 | // Redirect to the saved page |
||
604 | url::redirect($save); |
||
605 | } |
||
606 | } |
||
607 | } |
||
608 | |||
609 | // Return validation status |
||
610 | return $status; |
||
611 | } |
||
612 | |||
613 | /** |
||
614 | * Saves the current object. |
||
615 | * |
||
616 | * @chainable |
||
617 | * @return ORM_Core |
||
618 | */ |
||
619 | public function save() |
||
620 | { |
||
621 | if (! empty($this->changed)) { |
||
622 | $data = array(); |
||
623 | foreach ($this->changed as $column) { |
||
624 | // Compile changed data |
||
625 | $data[$column] = $this->object[$column]; |
||
626 | } |
||
627 | |||
628 | if ($this->loaded === true) { |
||
629 | $query = $this->db |
||
0 ignored issues
–
show
$query is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
630 | ->where($this->primary_key, $this->object[$this->primary_key]) |
||
631 | ->update($this->table_name, $data); |
||
632 | |||
633 | // Object has been saved |
||
634 | $this->saved = true; |
||
635 | } else { |
||
636 | $query = $this->db |
||
0 ignored issues
–
show
|
|||
637 | ->insert($this->table_name, $data); |
||
638 | |||
639 | if ($query->count() > 0) { |
||
640 | if (empty($this->object[$this->primary_key])) { |
||
641 | // Load the insert id as the primary key |
||
642 | $this->object[$this->primary_key] = $query->insert_id(); |
||
643 | } |
||
644 | |||
645 | // Object is now loaded and saved |
||
646 | $this->loaded = $this->saved = true; |
||
647 | } |
||
648 | } |
||
649 | |||
650 | if ($this->saved === true) { |
||
651 | // All changes have been saved |
||
652 | $this->changed = array(); |
||
653 | } |
||
654 | } |
||
655 | |||
656 | if ($this->saved === true and ! empty($this->changed_relations)) { |
||
657 | foreach ($this->changed_relations as $column => $values) { |
||
658 | // All values that were added |
||
659 | $added = array_diff($values, $this->object_relations[$column]); |
||
660 | |||
661 | // All values that were saved |
||
662 | $removed = array_diff($this->object_relations[$column], $values); |
||
663 | |||
664 | if (empty($added) and empty($removed)) { |
||
665 | // No need to bother |
||
666 | continue; |
||
667 | } |
||
668 | |||
669 | // Clear related columns |
||
670 | unset($this->related[$column]); |
||
671 | |||
672 | // Load the model |
||
673 | $model = ORM::factory(inflector::singular($column)); |
||
674 | |||
675 | if (($join_table = array_search($column, $this->has_and_belongs_to_many)) === false) { |
||
676 | continue; |
||
677 | } |
||
678 | |||
679 | if (is_int($join_table)) { |
||
680 | // No "through" table, load the default JOIN table |
||
681 | $join_table = $model->join_table($this->table_name); |
||
682 | } |
||
683 | |||
684 | // Foreign keys for the join table |
||
685 | $object_fk = $this->foreign_key(null); |
||
686 | $related_fk = $model->foreign_key(null); |
||
687 | |||
688 | if (! empty($added)) { |
||
689 | foreach ($added as $id) { |
||
690 | // Insert the new relationship |
||
691 | $this->db->insert($join_table, array( |
||
0 ignored issues
–
show
|
|||
692 | $object_fk => $this->object[$this->primary_key], |
||
693 | $related_fk => $id, |
||
694 | )); |
||
695 | } |
||
696 | } |
||
697 | |||
698 | if (! empty($removed)) { |
||
699 | $this->db |
||
0 ignored issues
–
show
|
|||
700 | ->where($object_fk, $this->object[$this->primary_key]) |
||
701 | ->in($related_fk, $removed) |
||
702 | ->delete($join_table); |
||
703 | } |
||
704 | |||
705 | // Clear all relations for this column |
||
706 | unset($this->object_relations[$column], $this->changed_relations[$column]); |
||
707 | } |
||
708 | } |
||
709 | |||
710 | return $this; |
||
711 | } |
||
712 | |||
713 | /** |
||
714 | * Deletes the current object from the database. This does NOT destroy |
||
715 | * relationships that have been created with other objects. |
||
716 | * |
||
717 | * @chainable |
||
718 | * @return ORM_Core |
||
719 | */ |
||
720 | public function delete($id = null) |
||
721 | { |
||
722 | if ($id === null and $this->loaded) { |
||
723 | // Use the the primary key value |
||
724 | $id = $this->object[$this->primary_key]; |
||
725 | } |
||
726 | |||
727 | // Delete this object |
||
728 | $this->db->where($this->primary_key, $id)->delete($this->table_name); |
||
0 ignored issues
–
show
|
|||
729 | |||
730 | return $this->clear(); |
||
731 | } |
||
732 | |||
733 | /** |
||
734 | * Delete all objects in the associated table. This does NOT destroy |
||
735 | * relationships that have been created with other objects. |
||
736 | * |
||
737 | * @chainable |
||
738 | * @param array ids to delete |
||
739 | * @return ORM_Core |
||
740 | */ |
||
741 | public function delete_all($ids = null) |
||
742 | { |
||
743 | if (is_array($ids)) { |
||
744 | // Delete only given ids |
||
745 | $this->db->in($this->primary_key, $ids); |
||
0 ignored issues
–
show
|
|||
746 | } elseif (is_null($ids)) { |
||
747 | // Delete all records |
||
748 | $this->db->where('1=1'); |
||
0 ignored issues
–
show
|
|||
749 | } else { |
||
750 | // Do nothing - safeguard |
||
751 | return $this; |
||
752 | } |
||
753 | |||
754 | // Delete all objects |
||
755 | $this->db->delete($this->table_name); |
||
0 ignored issues
–
show
|
|||
756 | |||
757 | return $this->clear(); |
||
758 | } |
||
759 | |||
760 | /** |
||
761 | * Unloads the current object and clears the status. |
||
762 | * |
||
763 | * @chainable |
||
764 | * @return ORM_Core |
||
765 | */ |
||
766 | public function clear() |
||
767 | { |
||
768 | // Create an array with all the columns set to NULL |
||
769 | $columns = array_keys($this->table_columns); |
||
770 | $values = array_combine($columns, array_fill(0, count($columns), null)); |
||
771 | |||
772 | // Replace the current object with an empty one |
||
773 | $this->load_values($values); |
||
774 | |||
775 | return $this; |
||
776 | } |
||
777 | |||
778 | /** |
||
779 | * Reloads the current object from the database. |
||
780 | * |
||
781 | * @chainable |
||
782 | * @return ORM |
||
0 ignored issues
–
show
|
|||
783 | */ |
||
784 | public function reload() |
||
785 | { |
||
786 | return $this->find($this->object[$this->primary_key]); |
||
787 | } |
||
788 | |||
789 | /** |
||
790 | * Reload column definitions. |
||
791 | * |
||
792 | * @chainable |
||
793 | * @param boolean force reloading |
||
794 | * @return ORM_Core |
||
795 | */ |
||
796 | public function reload_columns($force = false) |
||
797 | { |
||
798 | if ($force === true or empty($this->table_columns)) { |
||
799 | if (isset(ORM::$column_cache[$this->object_name])) { |
||
800 | // Use cached column information |
||
801 | $this->table_columns = ORM::$column_cache[$this->object_name]; |
||
802 | } else { |
||
803 | // Load table columns |
||
804 | ORM::$column_cache[$this->object_name] = $this->table_columns = $this->list_fields(); |
||
805 | } |
||
806 | } |
||
807 | |||
808 | return $this; |
||
809 | } |
||
810 | |||
811 | /** |
||
812 | * Tests if this object has a relationship to a different model. |
||
813 | * |
||
814 | * @param object related ORM model |
||
815 | * @param boolean check for any relations to given model |
||
816 | * @return boolean |
||
817 | */ |
||
818 | public function has(ORM $model, $any = false) |
||
819 | { |
||
820 | // Determine plural or singular relation name |
||
821 | $related = ($model->table_names_plural === true) ? $model->object_plural : $model->object_name; |
||
822 | |||
823 | if (($join_table = array_search($related, $this->has_and_belongs_to_many)) === false) { |
||
824 | return false; |
||
825 | } |
||
826 | |||
827 | if (is_int($join_table)) { |
||
828 | // No "through" table, load the default JOIN table |
||
829 | $join_table = $model->join_table($this->table_name); |
||
830 | } |
||
831 | |||
832 | if (! isset($this->object_relations[$related])) { |
||
833 | // Load the object relationships |
||
834 | $this->changed_relations[$related] = $this->object_relations[$related] = $this->load_relations($join_table, $model); |
||
835 | } |
||
836 | |||
837 | if (! $model->empty_primary_key()) { |
||
838 | // Check if a specific object exists |
||
839 | return in_array($model->primary_key_value, $this->changed_relations[$related]); |
||
840 | } elseif ($any) { |
||
841 | // Check if any relations to given model exist |
||
842 | return ! empty($this->changed_relations[$related]); |
||
843 | } else { |
||
844 | return false; |
||
845 | } |
||
846 | } |
||
847 | |||
848 | /** |
||
849 | * Adds a new relationship to between this model and another. |
||
850 | * |
||
851 | * @param object related ORM model |
||
852 | * @return boolean |
||
853 | */ |
||
854 | public function add(ORM $model) |
||
855 | { |
||
856 | if ($this->has($model)) { |
||
857 | return true; |
||
858 | } |
||
859 | |||
860 | // Get the faked column name |
||
861 | $column = $model->object_plural; |
||
862 | |||
863 | // Add the new relation to the update |
||
864 | $this->changed_relations[$column][] = $model->primary_key_value; |
||
865 | |||
866 | if (isset($this->related[$column])) { |
||
867 | // Force a reload of the relationships |
||
868 | unset($this->related[$column]); |
||
869 | } |
||
870 | |||
871 | return true; |
||
872 | } |
||
873 | |||
874 | /** |
||
875 | * Adds a new relationship to between this model and another. |
||
876 | * |
||
877 | * @param object related ORM model |
||
878 | * @return boolean |
||
879 | */ |
||
880 | public function remove(ORM $model) |
||
881 | { |
||
882 | if (! $this->has($model)) { |
||
883 | return false; |
||
884 | } |
||
885 | |||
886 | // Get the faked column name |
||
887 | $column = $model->object_plural; |
||
888 | |||
889 | if (($key = array_search($model->primary_key_value, $this->changed_relations[$column])) === false) { |
||
890 | return false; |
||
891 | } |
||
892 | |||
893 | // Remove the relationship |
||
894 | unset($this->changed_relations[$column][$key]); |
||
895 | |||
896 | if (isset($this->related[$column])) { |
||
897 | // Force a reload of the relationships |
||
898 | unset($this->related[$column]); |
||
899 | } |
||
900 | |||
901 | return true; |
||
902 | } |
||
903 | |||
904 | /** |
||
905 | * Count the number of records in the table. |
||
906 | * |
||
907 | * @return integer |
||
908 | */ |
||
909 | public function count_all() |
||
910 | { |
||
911 | // Return the total number of records in a table |
||
912 | return $this->db->count_records($this->table_name); |
||
0 ignored issues
–
show
|
|||
913 | } |
||
914 | |||
915 | /** |
||
916 | * Proxy method to Database list_fields. |
||
917 | * |
||
918 | * @param string table name or NULL to use this table |
||
919 | * @return array |
||
920 | */ |
||
921 | public function list_fields($table = null) |
||
922 | { |
||
923 | if ($table === null) { |
||
924 | $table = $this->table_name; |
||
925 | } |
||
926 | |||
927 | // Proxy to database |
||
928 | return $this->db->list_fields($table); |
||
0 ignored issues
–
show
|
|||
929 | } |
||
930 | |||
931 | /** |
||
932 | * Proxy method to Database field_data. |
||
933 | * |
||
934 | * @param string table name |
||
935 | * @return array |
||
936 | */ |
||
937 | public function field_data($table) |
||
938 | { |
||
939 | // Proxy to database |
||
940 | return $this->db->field_data($table); |
||
0 ignored issues
–
show
|
|||
941 | } |
||
942 | |||
943 | /** |
||
944 | * Proxy method to Database field_data. |
||
945 | * |
||
946 | * @chainable |
||
947 | * @param string SQL query to clear |
||
948 | * @return ORM_Core |
||
949 | */ |
||
950 | public function clear_cache($sql = null) |
||
951 | { |
||
952 | // Proxy to database |
||
953 | $this->db->clear_cache($sql); |
||
0 ignored issues
–
show
|
|||
954 | |||
955 | ORM::$column_cache = array(); |
||
956 | |||
957 | return $this; |
||
958 | } |
||
959 | |||
960 | /** |
||
961 | * Returns the unique key for a specific value. This method is expected |
||
962 | * to be overloaded in models if the model has other unique columns. |
||
963 | * |
||
964 | * @param mixed unique value |
||
965 | * @return string |
||
966 | */ |
||
967 | public function unique_key($id) |
||
0 ignored issues
–
show
|
|||
968 | { |
||
969 | return $this->primary_key; |
||
970 | } |
||
971 | |||
972 | /** |
||
973 | * Determines the name of a foreign key for a specific table. |
||
974 | * |
||
975 | * @param string related table name |
||
976 | * @param string prefix table name (used for JOINs) |
||
977 | * @return string |
||
978 | */ |
||
979 | public function foreign_key($table = null, $prefix_table = null) |
||
980 | { |
||
981 | if ($table === true) { |
||
982 | if (is_string($prefix_table)) { |
||
983 | // Use prefix table name and this table's PK |
||
984 | return $prefix_table.'.'.$this->primary_key; |
||
985 | } else { |
||
986 | // Return the name of this table's PK |
||
987 | return $this->table_name.'.'.$this->primary_key; |
||
988 | } |
||
989 | } |
||
990 | |||
991 | if (is_string($prefix_table)) { |
||
992 | // Add a period for prefix_table.column support |
||
993 | $prefix_table .= '.'; |
||
994 | } |
||
995 | |||
996 | if (isset($this->foreign_key[$table])) { |
||
997 | // Use the defined foreign key name, no magic here! |
||
998 | $foreign_key = $this->foreign_key[$table]; |
||
999 | } else { |
||
1000 | if (! is_string($table) or ! array_key_exists($table.'_'.$this->primary_key, $this->object)) { |
||
1001 | // Use this table |
||
1002 | $table = $this->table_name; |
||
1003 | |||
1004 | if (strpos($table, '.') !== false) { |
||
1005 | // Hack around support for PostgreSQL schemas |
||
1006 | list($schema, $table) = explode('.', $table, 2); |
||
0 ignored issues
–
show
The assignment to
$schema is unused. Consider omitting it like so list($first,,$third) .
This checks looks for assignemnts to variables using the Consider the following code example. <?php
function returnThreeValues() {
return array('a', 'b', 'c');
}
list($a, $b, $c) = returnThreeValues();
print $a . " - " . $c;
Only the variables Instead, the list call could have been. list($a,, $c) = returnThreeValues();
![]() |
|||
1007 | } |
||
1008 | |||
1009 | if ($this->table_names_plural === true) { |
||
1010 | // Make the key name singular |
||
1011 | $table = inflector::singular($table); |
||
1012 | } |
||
1013 | } |
||
1014 | |||
1015 | $foreign_key = $table.'_'.$this->primary_key; |
||
1016 | } |
||
1017 | |||
1018 | return $prefix_table.$foreign_key; |
||
1019 | } |
||
1020 | |||
1021 | /** |
||
1022 | * This uses alphabetical comparison to choose the name of the table. |
||
1023 | * |
||
1024 | * Example: The joining table of users and roles would be roles_users, |
||
1025 | * because "r" comes before "u". Joining products and categories would |
||
1026 | * result in categories_products, because "c" comes before "p". |
||
1027 | * |
||
1028 | * Example: zoo > zebra > robber > ocean > angel > aardvark |
||
1029 | * |
||
1030 | * @param string table name |
||
1031 | * @return string |
||
1032 | */ |
||
1033 | public function join_table($table) |
||
1034 | { |
||
1035 | if ($this->table_name > $table) { |
||
1036 | $table = $table.'_'.$this->table_name; |
||
1037 | } else { |
||
1038 | $table = $this->table_name.'_'.$table; |
||
1039 | } |
||
1040 | |||
1041 | return $table; |
||
1042 | } |
||
1043 | |||
1044 | /** |
||
1045 | * Returns an ORM model for the given object name; |
||
1046 | * |
||
1047 | * @param string object name |
||
1048 | * @return ORM |
||
1049 | */ |
||
1050 | protected function related_object($object) |
||
1051 | { |
||
1052 | if (isset($this->has_one[$object])) { |
||
1053 | $object = ORM::factory($this->has_one[$object]); |
||
1054 | } elseif (isset($this->belongs_to[$object])) { |
||
1055 | $object = ORM::factory($this->belongs_to[$object]); |
||
1056 | } elseif (in_array($object, $this->has_one) or in_array($object, $this->belongs_to)) { |
||
1057 | $object = ORM::factory($object); |
||
1058 | } else { |
||
1059 | return false; |
||
0 ignored issues
–
show
The return type of
return false; (false ) is incompatible with the return type documented by ORM_Core::related_object of type ORM .
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: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
1060 | } |
||
1061 | |||
1062 | return $object; |
||
1063 | } |
||
1064 | |||
1065 | /** |
||
1066 | * Loads an array of values into into the current object. |
||
1067 | * |
||
1068 | * @chainable |
||
1069 | * @param array values to load |
||
1070 | * @return ORM_Core |
||
1071 | */ |
||
1072 | public function load_values(array $values) |
||
1073 | { |
||
1074 | if (array_key_exists($this->primary_key, $values)) { |
||
1075 | // Replace the object and reset the object status |
||
1076 | $this->object = $this->changed = $this->related = array(); |
||
1077 | |||
1078 | // Set the loaded and saved object status based on the primary key |
||
1079 | $this->loaded = $this->saved = ($values[$this->primary_key] !== null); |
||
1080 | } |
||
1081 | |||
1082 | // Related objects |
||
1083 | $related = array(); |
||
1084 | |||
1085 | foreach ($values as $column => $value) { |
||
1086 | if (strpos($column, ':') === false) { |
||
1087 | if (isset($this->table_columns[$column])) { |
||
1088 | // The type of the value can be determined, convert the value |
||
1089 | $value = $this->load_type($column, $value); |
||
1090 | } |
||
1091 | |||
1092 | $this->object[$column] = $value; |
||
1093 | } else { |
||
1094 | list($prefix, $column) = explode(':', $column, 2); |
||
1095 | |||
1096 | $related[$prefix][$column] = $value; |
||
1097 | } |
||
1098 | } |
||
1099 | |||
1100 | if (! empty($related)) { |
||
1101 | foreach ($related as $object => $values) { |
||
1102 | // Load the related objects with the values in the result |
||
1103 | $this->related[$object] = $this->related_object($object)->load_values($values); |
||
1104 | } |
||
1105 | } |
||
1106 | |||
1107 | return $this; |
||
1108 | } |
||
1109 | |||
1110 | /** |
||
1111 | * Loads a value according to the types defined by the column metadata. |
||
1112 | * |
||
1113 | * @param string column name |
||
1114 | * @param mixed value to load |
||
1115 | * @return mixed |
||
1116 | */ |
||
1117 | protected function load_type($column, $value) |
||
1118 | { |
||
1119 | $type = gettype($value); |
||
1120 | if ($type == 'object' or $type == 'array' or ! isset($this->table_columns[$column])) { |
||
1121 | return $value; |
||
1122 | } |
||
1123 | |||
1124 | // Load column data |
||
1125 | $column = $this->table_columns[$column]; |
||
1126 | |||
1127 | if ($value === null and ! empty($column['null'])) { |
||
1128 | return $value; |
||
1129 | } |
||
1130 | |||
1131 | if (! empty($column['binary']) and ! empty($column['exact']) and (int) $column['length'] === 1) { |
||
1132 | // Use boolean for BINARY(1) fields |
||
1133 | $column['type'] = 'boolean'; |
||
1134 | } |
||
1135 | |||
1136 | switch ($column['type']) { |
||
1137 | case 'int': |
||
1138 | if ($value === '' and ! empty($column['null'])) { |
||
1139 | // Forms will only submit strings, so empty integer values must be null |
||
1140 | $value = null; |
||
1141 | } elseif ((float) $value > PHP_INT_MAX) { |
||
1142 | // This number cannot be represented by a PHP integer, so we convert it to a string |
||
1143 | $value = (string) $value; |
||
1144 | } else { |
||
1145 | $value = (int) $value; |
||
1146 | } |
||
1147 | break; |
||
1148 | case 'float': |
||
1149 | $value = (float) $value; |
||
1150 | break; |
||
1151 | case 'boolean': |
||
1152 | $value = (bool) $value; |
||
1153 | break; |
||
1154 | case 'string': |
||
1155 | $value = (string) $value; |
||
1156 | break; |
||
1157 | } |
||
1158 | |||
1159 | return $value; |
||
1160 | } |
||
1161 | |||
1162 | /** |
||
1163 | * Loads a database result, either as a new object for this model, or as |
||
1164 | * an iterator for multiple rows. |
||
1165 | * |
||
1166 | * @chainable |
||
1167 | * @param boolean return an iterator or load a single row |
||
1168 | * @return ORM for single rows |
||
1169 | * @return ORM_Iterator for multiple rows |
||
0 ignored issues
–
show
|
|||
1170 | */ |
||
1171 | protected function load_result($array = false) |
||
1172 | { |
||
1173 | if ($array === false) { |
||
1174 | // Only fetch 1 record |
||
1175 | $this->db->limit(1); |
||
0 ignored issues
–
show
|
|||
1176 | } |
||
1177 | |||
1178 | if (! isset($this->db_applied['select'])) { |
||
1179 | // Select all columns by default |
||
1180 | $this->db->select($this->table_name.'.*'); |
||
0 ignored issues
–
show
|
|||
1181 | } |
||
1182 | |||
1183 | if (! empty($this->load_with)) { |
||
1184 | foreach ($this->load_with as $alias => $object) { |
||
1185 | // Join each object into the results |
||
1186 | if (is_string($alias)) { |
||
1187 | // Use alias |
||
1188 | $this->with($alias); |
||
1189 | } else { |
||
1190 | // Use object |
||
1191 | $this->with($object); |
||
1192 | } |
||
1193 | } |
||
1194 | } |
||
1195 | |||
1196 | if (! isset($this->db_applied['orderby']) and ! empty($this->sorting)) { |
||
1197 | $sorting = array(); |
||
1198 | foreach ($this->sorting as $column => $direction) { |
||
1199 | if (strpos($column, '.') === false) { |
||
1200 | // Keeps sorting working properly when using JOINs on |
||
1201 | // tables with columns of the same name |
||
1202 | $column = $this->table_name.'.'.$column; |
||
1203 | } |
||
1204 | |||
1205 | $sorting[$column] = $direction; |
||
1206 | } |
||
1207 | |||
1208 | // Apply the user-defined sorting |
||
1209 | $this->db->orderby($sorting); |
||
0 ignored issues
–
show
|
|||
1210 | } |
||
1211 | |||
1212 | // Load the result |
||
1213 | $result = $this->db->get($this->table_name); |
||
0 ignored issues
–
show
|
|||
1214 | |||
1215 | if ($array === true) { |
||
1216 | // Return an iterated result |
||
1217 | return new ORM_Iterator($this, $result); |
||
1218 | } |
||
1219 | |||
1220 | if ($result->count() === 1) { |
||
1221 | // Load object values |
||
1222 | $this->load_values($result->result(false)->current()); |
||
1223 | } else { |
||
1224 | // Clear the object, nothing was found |
||
1225 | $this->clear(); |
||
1226 | } |
||
1227 | |||
1228 | return $this; |
||
1229 | } |
||
1230 | |||
1231 | /** |
||
1232 | * Return an array of all the primary keys of the related table. |
||
1233 | * |
||
1234 | * @param string table name |
||
1235 | * @param object ORM model to find relations of |
||
1236 | * @return array |
||
1237 | */ |
||
1238 | protected function load_relations($table, ORM $model) |
||
1239 | { |
||
1240 | // Save the current query chain (otherwise the next call will clash) |
||
1241 | $this->db->push(); |
||
0 ignored issues
–
show
|
|||
1242 | |||
1243 | $query = $this->db |
||
0 ignored issues
–
show
|
|||
1244 | ->select($model->foreign_key(null).' AS id') |
||
1245 | ->from($table) |
||
1246 | ->where($this->foreign_key(null, $table), $this->object[$this->primary_key]) |
||
1247 | ->get() |
||
1248 | ->result(true); |
||
1249 | |||
1250 | $this->db->pop(); |
||
0 ignored issues
–
show
|
|||
1251 | |||
1252 | $relations = array(); |
||
1253 | foreach ($query as $row) { |
||
1254 | $relations[] = $row->id; |
||
1255 | } |
||
1256 | |||
1257 | return $relations; |
||
1258 | } |
||
1259 | |||
1260 | /** |
||
1261 | * Returns whether or not primary key is empty |
||
1262 | * |
||
1263 | * @return bool |
||
1264 | */ |
||
1265 | protected function empty_primary_key() |
||
1266 | { |
||
1267 | return (empty($this->object[$this->primary_key]) and $this->object[$this->primary_key] !== '0'); |
||
1268 | } |
||
1269 | } // End ORM |
||
1270 |
Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.