예제 #1
0
 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')));
 }
예제 #2
0
 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);
 }
예제 #3
0
 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);
 }
예제 #4
0
 /**
  * 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);
 }