예제 #1
0
 function exclude()
 {
     foreach (func_get_args() as $Q) {
         $this->constraints[] = $Q instanceof Util\Q ? $Q->negate() : Util\Q::not($Q);
     }
     return $this;
 }
예제 #2
0
 /**
  * compileQ
  *
  * Build a constraint represented in an arbitrarily nested Q instance.
  * The placement of the compiled constraint is also considered and
  * represented in the resulting CompiledExpression instance.
  *
  * Parameters:
  * $Q - (Util\Q) constraint represented in a Q instance
  * $model - (string) root model class for all the field references in
  *      the Util\Q instance
  * $slot - (int) slot for inputs to be placed. Useful to differenciate
  *      inputs placed in the joins and where clauses for SQL backends
  *      which do not support named parameters.
  *
  * Returns:
  * (CompiledExpression) object containing the compiled expression (with
  * AND, OR, and NOT operators added). Furthermore, the $type attribute
  * of the CompiledExpression will allow the compiler to place the
  * constraint properly in the WHERE or HAVING clause appropriately.
  */
 function compileQ(Util\Q $Q, $model, $slot = false)
 {
     $filter = array();
     $type = CompiledExpression::TYPE_WHERE;
     foreach ($Q->constraints as $field => $value) {
         // Handle nested constraints
         if ($value instanceof Util\Q) {
             $filter[] = $T = $this->compileQ($value, $model, $slot);
             // Bubble up HAVING constraints
             if ($T instanceof CompiledExpression && $T->type == CompiledExpression::TYPE_HAVING) {
                 $type = $T->type;
             }
         } elseif ($value instanceof Model\ModelBase) {
             $criteria = array();
             foreach ($value->pk as $f => $v) {
                 $f = $field . '__' . $f;
                 $criteria[$f] = $v;
             }
             $filter[] = $this->compileQ(new Util\Q($criteria), $model, $slot);
         } else {
             list($field, $op) = $this->getField($field, $model);
             if ($field instanceof Util\Aggregate) {
                 // This constraint has to go in the HAVING clause
                 $field = $field->toSql($this, $model);
                 $type = CompiledExpression::TYPE_HAVING;
             }
             if ($value === null) {
                 $filter[] = sprintf('%s IS NULL', $field);
             } elseif ($value instanceof Util\Field) {
                 $filter[] = sprintf($op, $field, $value->toSql($this, $model));
             } elseif (is_callable($op)) {
                 $filter[] = call_user_func($op, $field, $value, $model);
             } else {
                 $filter[] = sprintf($op, $field, $this->input($value, $slot));
             }
         }
     }
     $glue = $Q->isOred() ? ' OR ' : ' AND ';
     $clause = implode($glue, $filter);
     if (count($filter) > 1) {
         $clause = '(' . $clause . ')';
     }
     if ($Q->isNegated()) {
         $clause = 'NOT ' . $clause;
     }
     return new CompiledExpression($clause, $type);
 }