Exemple #1
0
 /**
  * Fetch a single result of this query. Builds a Model object if the $parse_objects flag is set. This will
  * also attach any joined or with objects to their associated targets.
  *
  * @param bool $parse_objects If true the array is filled with Model objects, otherwise the result is an array
  *                            of associative arrays.
  * @param bool $debug Used to print the query to STDOUT before being executed
  *
  * @return Model|array|null
  */
 public function fetchRow($parse_objects = true, $debug = false)
 {
     $object_instances = array();
     if (!$this->_executed) {
         $this->execute($debug);
     }
     for (;;) {
         if ($this->_last_row === false) {
             $this->_last_row = $this->_statement->fetch();
         }
         //if still false, return null (no rows left in set)
         if ($this->_last_row === false) {
             break;
         }
         //if not bothering to parse object
         if (!$parse_objects) {
             $output = array();
             // if it's a manual select (fields were manually specified) then just put the
             // requested fields into the output directly, keyed by their aliases.
             if ($this->manual_select) {
                 if (isset($this->fields[0])) {
                     throw new Exception('An associative array must be passed in to \\Wave\\DB\\Query::from() when not parsing objects');
                 }
                 foreach ($this->fields as $alias => $field) {
                     if (isset($this->_last_row[$alias])) {
                         $key = $this->manual_select ? $alias : $field;
                         $output[$key] = $this->_last_row[$alias];
                     }
                 }
             } else {
                 foreach ($this->class_aliases[$this->from_alias]['columns'] as $column => $column_alias) {
                     $output[$column] = $this->_last_row[$column_alias];
                 }
                 foreach ($this->class_aliases as $alias => $class_details) {
                     if ($alias === $this->from_alias) {
                         continue;
                     }
                     foreach ($class_details['columns'] as $column => $column_alias) {
                         $output[$alias][$column] = $this->_last_row[$column_alias];
                     }
                 }
             }
             $this->_last_row = false;
             return $output;
         }
         //if there's no instance of the main class, create a new one.
         if (!isset($object_instances[$this->from_alias])) {
             $object_instances[$this->from_alias] = $this->buildClassInstance($this->from_alias);
         }
         if ($object_instances[$this->from_alias] === null) {
             trigger_error('Insufficient data in SELECT to build object instance.');
             return null;
         }
         //if there are joins, check that the current row still has the same $from_instance, if it doesn't, break.
         //otherwise build the related objects and put them on it.
         if (isset($this->joins[0])) {
             //if the from instance is different, break and leave it for the next call to fetchRow().
             foreach ($object_instances[$this->from_alias]->_getIdentifyingData() as $property => $value) {
                 $class = $this->class_aliases[$this->from_alias]['class'];
                 $alias = $this->class_aliases[$this->from_alias]['columns'][$property];
                 $cast_value = $this->database->valueFromSQL($this->_last_row[$alias], $class::_getField($property));
                 if ($cast_value !== $value) {
                     return isset($object_instances[$this->from_alias]) ? $object_instances[$this->from_alias] : null;
                 }
                 // break 2;
             }
             //otherwise build the child rows
             foreach ($this->joins as $join) {
                 $object_instances[$join['table_alias']] = $this->buildClassInstance($join['table_alias']);
             }
             //then check non-null child rows and add them to their parent rows
             foreach ($this->joins as $join) {
                 if ($object_instances[$join['table_alias']] === null) {
                     continue;
                 }
                 //find if is a join or a with
                 if (isset($this->with[$join['table_alias']])) {
                     switch ($this->with[$join['table_alias']]['relation_type']) {
                         case Wave\DB\Relation::ONE_TO_ONE:
                         case Wave\DB\Relation::MANY_TO_ONE:
                             $object_instances[$join['target_alias']]->{'set' . $this->with[$join['table_alias']]['relation_name']}($object_instances[$join['table_alias']], false);
                             break;
                         case Wave\DB\Relation::ONE_TO_MANY:
                         case Wave\DB\Relation::MANY_TO_MANY:
                             $object_instances[$join['target_alias']]->{'add' . $this->with[$join['table_alias']]['relation_name']}($object_instances[$join['table_alias']], false);
                             break;
                     }
                 } else {
                     $object_instances[$join['target_alias']]->addJoinedObject($object_instances[$join['table_alias']], $join['table_alias'], $this->unaliasClass($join['table_alias']));
                 }
             }
             //set the _last_row to false as it has been processed and this will force the next call to get another one.
             $this->_last_row = false;
         } else {
             //if no joins, just break from loop and return the $from_instance.
             break;
         }
     }
     // reset the last row pointer since we've finished with this row now.
     $this->_last_row = false;
     return isset($object_instances[$this->from_alias]) ? $object_instances[$this->from_alias] : null;
 }