public function test_where_operators() { $numbers = new Collection(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); $this->assertCount(1, $numbers->where('2')); $this->assertCount(2, $numbers->where('<= 2')); $this->assertCount(5, $numbers->where('> 5')); $vehicles = new Collection(array(array('name' => 'car', 'wheels' => 4), array('name' => 'trike', 'wheels' => 3), array('name' => 'bike', 'wheels' => 2))); $this->assertCount(1, $vehicles->where(array('wheels >' => 3))); $this->assertCount(2, $vehicles->where(array('name LIKE' => '%ke'))); }
public function where($conditions) { if ($this->valueField === null && $this->data instanceof Collection) { // The valueField is not set, pass the conditions to the original collection. return new self($this->data->where($conditions), null, $this->keyField); } return parent::where($conditions); }
public function where($conditions) { if ($this->isConverted) { return parent::where($conditions); } if ($this->data instanceof Collection && is_array($conditions)) { $logicalOperator = \Sledgehammer\extract_logical_operator($conditions); $convertedConditions = []; if ($logicalOperator === false) { if (count($conditions) > 1) { notice('Conditions with multiple conditions require a logical operator.', "Example: array('AND', 'x' => 1, 'y' => 5)"); } $minimum = 0; } else { $minimum = 1; $convertedConditions[0] = $logicalOperator; } foreach ($conditions as $path => $value) { if (preg_match('/^(.*) (' . \Sledgehammer\COMPARE_OPERATORS . ')$/', $path, $match)) { $column = $match[1]; $columnOperator = ' ' . $match[2]; } else { $column = $path; $columnOperator = ''; } if (($path !== 0 || $logicalOperator === false) && isset($this->options['mapping'][$column])) { $convertCondition = true; if (isset($this->options['writeFilters'][$column])) { if (in_array($columnOperator, array('', '==', '!='))) { $value = filter($value, $this->options['writeFilters'][$column]); } else { $convertCondition = false; // operation can't work reliably with filters } } if ($convertCondition) { $convertedConditions[$this->options['mapping'][$column] . $columnOperator] = $value; unset($conditions[$path]); } } } if (count($convertedConditions) > $minimum) { // There are conditions the low-level collection can handle? $collection = new self($this->data->where($convertedConditions), $this->model, $this->repository, $this->options); if (count($conditions) === $minimum) { return $collection; } return $collection->where($conditions); // Apply the remaining conditions } elseif (count($conditions) === $minimum) { // An empty array was given as $conditions? return new self(clone $this->data, $this->model, $this->repository, $this->options); } } return parent::where($conditions); }
/** * Return a subsection of the collection based on the conditions. * * Convert the $conditions to SQL object when appropriate. * * auto converts * ['x_id' => null] to "x_id IS NULL" * ['x_id !=' => null] to "x_id IS NOT NULL" * 'hits' => 0] to "hits = '0'" (Because in mysql '' = 0 evaluates to true, '' = '0' to false) * * @param array $conditions * * @return Collection */ public function where($conditions) { if ($this->data !== null || is_string($this->sql) || is_object($conditions) && is_callable($conditions) || $this->sql->limit !== false || $this->sql->offset != 0) { return parent::where($conditions); } $db = Connection::instance($this->dbLink); $sql = $this->sql; $logicalOperator = \Sledgehammer\extract_logical_operator($conditions); if ($logicalOperator === false) { if (count($conditions) > 1) { \Sledgehammer\notice('Conditions with multiple conditions require a logical operator.', "Example: array('AND', 'x' => 1, 'y' => 5)"); } $logicalOperator = 'AND'; } else { unset($conditions[0]); } if ($logicalOperator === 'AND') { $method = 'andWhere'; } elseif ($logicalOperator === 'OR') { $method = 'orWhere'; } else { throw new Exception('Unsupported logical operator "' . $logicalOperator . '", expecting "AND" or "OR"'); } // The result are rows(fetch_assoc arrays), all conditions must be columnnames (or invalid) foreach ($conditions as $path => $value) { if (preg_match('/^(.*) (' . \Sledgehammer\COMPARE_OPERATORS . ')$/', $path, $matches)) { $column = $this->convertPathToColumn($matches[1]); $operator = $matches[2]; } else { $column = $this->convertPathToColumn($path); $operator = '=='; } if ($column === false) { // Converting to path failed? \Sledgehammer\array_key_unshift($conditions, 0, $logicalOperator); return parent::where($conditions); } if ($value === null) { switch ($operator) { case '==': $operator = 'IS'; $expectation = 'NULL'; break; case '!=': $operator = 'IS NOT '; $expectation = 'NULL'; break; case '>': case '<': case '>=': case '<=': $expectation = "''"; break; default: \Sledgehammer\warning('Unknown behavior for NULL values with operator "' . $operator . '"'); $expectation = $db->quote($expectation); break; } $sql = $sql->{$method}($column . ' ' . $operator . ' ' . $expectation); } else { if ($operator === '!=') { $sql = $sql->{$method}('(' . $column . ' != ' . $db->quote($value, PDO::PARAM_STR) . ' OR ' . $column . ' IS NULL)'); } elseif ($operator === 'IN') { if ((is_array($value) || $value instanceof Traversable) === false) { \Sledgehammer\notice('Operator IN expects an array or Traversable', $value); $value = explode(',', $value); } $quoted = []; foreach ($value as $val) { $quoted[] = $this->quote($db, $column, $val); } $sql = $sql->{$method}($column . ' ' . $operator . ' (' . implode(', ', $quoted) . ')'); } else { if ($operator === '==') { $operator = '='; } $sql = $sql->{$method}($column . ' ' . $operator . ' ' . $this->quote($db, $column, $value)); } } } return new self($sql, $this->dbLink); }