public function setInformation(array $info) { parent::setInformation($info); $this->cm->attribute = isset($info['key_from']) ? $info['key_from'] : 'id'; $this->cm->column = $this->cm->t->columnRealName($this->cm->attribute); $this->lm->attribute = isset($info['key_to']) ? $info['key_to'] : call_user_func(Cfg::get('buildForeignKey'), $this->cm->t->modelBaseName); $this->lm->column = $this->lm->t->columnRealName($this->lm->attribute); }
/** * @covers SimpleAR\Database\Builder\WhereBuilder::getQueryOptionRelationSeparator * @covers WhereBuilder::setQueryOptionRelationSeparator */ public function testQueryOptionRelationSeparator() { $b = new WhereBuilder(); $this->assertEquals(Cfg::get('queryOptionRelationSeparator'), $b->getQueryOptionRelationSeparator()); $b->setQueryOptionRelationSeparator('#'); $this->assertEquals('#', $b->getQueryOptionRelationSeparator()); Cfg::set('queryOptionRelationSeparator', '@'); $b = new WhereBuilder(); $this->assertEquals('@', $b->getQueryOptionRelationSeparator()); // Reset the default config option. Cfg::set('queryOptionRelationSeparator', '/'); }
public function setInformation(array $info) { parent::setInformation($info); $this->cm->attribute = isset($info['key_from']) ? $info['key_from'] : 'id'; $this->cm->column = (array) $this->cm->t->columnRealName($this->cm->attribute); $this->lm->attribute = isset($info['key_to']) ? $info['key_to'] : 'id'; $this->lm->column = (array) $this->lm->t->columnRealName($this->lm->attribute); $this->jm = new \StdClass(); if (isset($info['join_model'])) { $this->jm->class = $s = $info['join_model'] . Cfg::get('modelClassSuffix'); $this->jm->t = $s::table(); $this->jm->table = $this->jm->t->name; $this->jm->from = (array) $this->jm->t->columnRealName(isset($info['join_from']) ? $info['join_from'] : call_user_func(Cfg::get('buildForeignKey'), $this->cm->t->modelBaseName)); $this->jm->to = (array) $this->jm->t->columnRealName(isset($info['join_to']) ? $info['join_to'] : call_user_func(Cfg::get('buildForeignKey'), $this->lm->t->modelBaseName)); } else { $this->jm->class = null; $this->jm->table = isset($info['join_table']) ? $info['join_table'] : $this->cm->table . '_' . $this->lm->table; $this->jm->from = (array) (isset($info['join_from']) ? $info['join_from'] : decamelize($this->cm->t->modelBaseName) . '_id'); $this->jm->to = (array) (isset($info['join_to']) ? $info['join_to'] : decamelize($this->lm->t->modelBaseName) . '_id'); } }
/** * Get the separation character of relation names in options. * * If the separator is not set yet, it fetches it from Config and cache it * in current builder instance. * * @return string The separator. * * @see Config::$_queryOptionRelationSeparator */ public function getQueryOptionRelationSeparator() { // Not here? Fetch it. if (!$this->_queryOptionRelationSeparator) { $sep = Cfg::get('queryOptionRelationSeparator'); $this->setQueryOptionRelationSeparator($sep); } return $this->_queryOptionRelationSeparator; }
public function setInformation(array $info) { $this->lm = new \StdClass(); $this->lm->class = $s = $info['model'] . Cfg::get('modelClassSuffix'); $this->lm->t = $s::table(); $this->lm->table = $this->lm->t->name; //$this->lm->pk = $this->lm->t->primaryKey; foreach (array('filter', 'conditions', 'order') as $item) { if (isset($info[$item])) { $this->{$item} = $info[$item]; } } if (!empty($info['scope'])) { $this->setScope($info['scope']); } }
/** * Updates a instance. * * @throws Exception if a database error occurs. * @return $this * * @see SimpleAR\Model::_onBeforeUpdate() * @see SimpleAR\Model::_onAfterUpdate() */ private function _update() { $this->_onBeforeUpdate(); $table = static::table(); $columns = array_diff_key($table->columns, $table->deprecated); // Keys will be attribute names; Values will be attributes values. $fields = array(); // Will contains LM to save in cascade. $linkedModels = array(); // Avoid retrieving config option several times. $dateTimeFormat = Cfg::get('databaseDateTimeFormat'); foreach ($this->_attributes as $key => $value) { // Handles actual columns. if (isset($columns[$key])) { // Transform DateTime object into a database-formatted string. if ($value instanceof \DateTime) { $value = $value->format($dateTimeFormat); } $fields[$key] = $value; continue; } // Handle linked models. // $value can be: // - a Model instance not saved yet (BelongsTo or HasOne relations); // - a Model instance ID (BelongsTo or HasOne relations) (Not // implemented). // // - a Model instance array (HasMany or ManyMany relations); // - a Model instance ID array (HasMany or ManyMany relations). if (isset(static::$_relations[$key])) { $relation = static::relation($key); // If it is linked by a BelongsTo instance, update local field. if ($relation instanceof Relation\BelongsTo) { if ($value) { // Save in cascade. $value->save(); // We use array_merge() and array_combine() in order to handle composed keys. $fields = array_merge($fields, array_combine((array) $relation->cm->attribute, (array) $value->id)); } } else { $linkedModels[] = array('relation' => static::relation($key), 'object' => $value); } } } try { $pk = self::table()->getPrimaryKey(); $query = self::query()->update()->set($fields)->where($pk, array($this->id()))->run(); // I know code seems (is) redundant, but I am convinced that it is // better this way. Treatment of linked model can be different // during insert than during update. See ManyMany treatment for // example: we delete before inserting. foreach ($linkedModels as $a) { // Avoid multiple array accesses. $relation = $a['relation']; $object = $a['object']; // Ignore if not Model instance. if ($relation instanceof Relation\HasOne) { if ($object instanceof Model) { $attrs = array_combine((array) $relation->lm->attribute, $this->id()); $object->set($attrs); $object->save(); } } elseif ($relation instanceof Relation\HasMany) { // Ignore if not Model instance. // Array cast allows user not to bother to necessarily set an array. foreach ((array) $object as $o) { if ($o instanceof Model) { $attrs = array_combine((array) $relation->lm->attribute, $this->id()); $o->set($attrs); $o->save(); } } } else { // We want to: // - save linked model instances if not done yet; // - consider integers as linked model instance IDs; // - save instances on cascade. // - link these instances with current model via the // relation join table. To do this: // 1) Delete all rows of join table that concerns // current model; // 2) Insert new rows. // Remove all rows from join table. (Easier this way.) self::query()->delete($relation->jm->table)->where((array) $relation->jm->from, $this->id())->run(); $values = array(); // Array cast allows user not to bother to necessarily set an array. foreach ((array) $object as $m) { if ($m instanceof Model) { $m->save(); $values[] = array($this->id(), $m->id()); } else { $values[] = array($this->id(), $m); } } // Run insert query only if there are values to insert. It // would throw a PDO Exception otherwise. if ($values) { $fields = array($relation->jm->from, $relation->jm->to); $query = self::query()->insert($relation->jm->table)->fields($fields)->values($values)->run(); } } } } catch (DatabaseEx $ex) { throw $ex; } catch (Exception $ex) { throw new Exception('Update failed for ' . get_class($this) . ' with ID: ' . var_export($this->id(), true) . '.', 0, $ex); } $this->_onAfterUpdate(); return $this; }