public function assertConditions($expectedSql, $values, $underscoredString, $map = null) { $cond = SQLBuilder::createConditionsFromUnderscoredString($this->table->conn, $underscoredString, $values, $map); $this->assertSqlHas($expectedSql, array_shift($cond)); if ($values) { $this->assertEquals(array_values(array_filter($values, function ($s) { return $s !== null; })), array_values($cond)); } else { $this->assertEquals(array(), $cond); } }
protected function createConditionsFromKeys(Model $model, $condition_keys = [], $value_keys = []) { $condition_string = \implode('_and_', $condition_keys); $condition_values = \array_values($model->getValuesFor($value_keys)); // return null if all the foreign key values are null so that we don't try to do a query like "id is null" if (all(null, $condition_values)) { return null; } $conditions = SQLBuilder::createConditionsFromUnderscoredString(Table::load(\get_class($model))->conn, $condition_string, $condition_values); # DO NOT CHANGE THE NEXT TWO LINES. add_condition operates on a reference and will screw options array up if (isset($this->options['conditions'])) { $options_conditions = $this->options['conditions']; } else { $options_conditions = []; } return Utils::addCondition($options_conditions, $conditions); }
/** * Enables the use of dynamic finders. * * Dynamic finders are just an easy way to do queries quickly without having to * specify an options array with conditions in it. * * <code> * SomeModel::find_by_first_name('Tito'); * SomeModel::find_by_first_name_and_last_name('Tito','the Grief'); * SomeModel::find_by_first_name_or_last_name('Tito','the Grief'); * SomeModel::find_all_by_last_name('Smith'); * SomeModel::count_by_name('Bob') * SomeModel::count_by_name_or_state('Bob','VA') * SomeModel::count_by_name_and_state('Bob','VA') * </code> * * You can also create the model if the find call returned no results: * * <code> * Person::find_or_create_by_name('Tito'); * * # would be the equivalent of * if (!Person::find_by_name('Tito')) * Person::create(array('Tito')); * </code> * * Some other examples of find_or_create_by: * * <code> * Person::find_or_create_by_name_and_id('Tito',1); * Person::find_or_create_by_name_and_id(array('name' => 'Tito', 'id' => 1)); * </code> * * @param string $method Name of method * @param mixed $args Method args * @return \Activerecord\Model * @throws {@link Activerecord} if invalid query * @see find */ public static function __callStatic($method, $args) { $options = static::extractAndValidateOptions($args); $create = false; if (\substr($method, 0, 17) == 'find_or_create_by') { $attributes = \substr($method, 17); // can't take any finders with OR in it when doing a find_or_create_by if (\strpos($attributes, '_or_') !== false) { throw new ExceptionActiverecord("Cannot use OR'd attributes in find_or_create_by"); } $create = true; $method = 'find_by' . \substr($method, 17); } if (\substr($method, 0, 7) === 'find_by') { $attributes = \substr($method, 8); $options['conditions'] = SQLBuilder::createConditionsFromUnderscoredString(static::connection(), $attributes, $args, static::$alias_attribute); if (!($ret = static::find('first', $options)) && $create) { return static::create(SQLBuilder::createHashFromUnderscoredString($attributes, $args, static::$alias_attribute)); } return $ret; } elseif (\substr($method, 0, 11) === 'find_all_by') { $options['conditions'] = SQLBuilder::createConditionsFromUnderscoredString(static::connection(), \substr($method, 12), $args, static::$alias_attribute); return static::find('all', $options); } elseif (\substr($method, 0, 8) === 'count_by') { $options['conditions'] = SQLBuilder::createConditionsFromUnderscoredString(static::connection(), \substr($method, 9), $args, static::$alias_attribute); return static::count($options); } throw new ExceptionActiverecord("Call to undefined method: {$method}"); }