protected function _inspectComparisonExpression(Comparison $expression, $bundle, Query $query)
    {
        $field = $expression->getField();
        $column = is_string($field) ? $this->_toolbox->columnName($field) : '';

        if (empty($column) ||
            in_array($column, (array)$this->_table->schema()->columns()) || // ignore real columns
            !in_array($column, $this->_toolbox->getAttributeNames()) ||
            !$this->_toolbox->isSearchable($column) // ignore no searchable virtual columns
        ) {
            // nothing to alter
            return $expression;
        }

        $attr = $this->_toolbox->attributes($bundle)[$column];
        $value = $expression->getValue();
        $type = $this->_toolbox->getType($column);
        $conjunction = $expression->getOperator();
        $conditions = [
            'EavValues.eav_attribute_id' => $attr['id'],
            "EavValues.value_{$type} {$conjunction}" => $value,
        ];

        // subquery scope
        $subQuery = TableRegistry::get('Eav.EavValues')
            ->find()
            ->select('EavValues.entity_id')
            ->where($conditions)
            ->order(['EavValues.id' => 'DESC']);

        // some variables
        $pk = $this->_tablePrimaryKey();
        $driverClass = $this->_toolbox->driver($query);

        switch ($driverClass) {
            case 'sqlite':
                $concat = implode(' || ', $pk);
                $field = "({$concat} || '')";
                break;
            case 'sqlserver':
                $pk = array_map(function ($keyPart) {
                    return "CAST({$keyPart} AS VARCHAR)";
                }, $pk);
                $concat = implode(' + ', $pk);
                $field = "({$concat} + '')";
                break;
            case 'mysql':
            case 'postgres':
            default:
                $concat = implode(', ', $pk);
                $field = "CONCAT({$concat}, '')";
                break;
        }

        // compile query, faster than raw subquery in most cases
        $ids = $subQuery->all()->extract('entity_id')->toArray();
        $ids = empty($ids) ? ['-1'] : $ids;
        $expression->setField($field);
        $expression->setValue($ids);
        $expression->setOperator('IN');

        $class = new \ReflectionClass($expression);
        $property = $class->getProperty('_type');
        $property->setAccessible(true);
        $property->setValue($expression, 'string');

        $property = $class->getProperty('_isMultiple');
        $property->setAccessible(true);
        $property->setValue($expression, true);

        return $expression;
    }
protected function _inspectComparisonExpression(Comparison $expression, $bundle, Query $query)
    {
        $field = $expression->getField();
        $column = is_string($field) ? $this->_toolbox->columnName($field) : '';

        if (empty($column) ||
            in_array($column, (array)$this->_table->schema()->columns()) || // ignore real columns
            !in_array($column, $this->_toolbox->getAttributeNames()) ||
            !$this->_toolbox->isSearchable($column) // ignore no searchable virtual columns
        ) {
            // nothing to alter
            return $expression;
        }

        $attr = $this->_toolbox->attributes($bundle)[$column];
        $value = $expression->getValue();
        $type = $this->_toolbox->getType($column);
        $conjunction = $expression->getOperator();
        $conditions = [
            'EavValues.eav_attribute_id' => $attr['id'],
            "EavValues.value_{$type} {$conjunction}" => $value,
        ];

        // subquery scope
        $subQuery = TableRegistry::get('Eav.EavValues')
            ->find()
            ->select('EavValues.entity_id')
            ->where($conditions)
            ->order(['EavValues.id' => 'DESC']);

        // some variables
        $pk = $this->_tablePrimaryKey();
        $driverClass = $this->_toolbox->driver($query);

        switch ($driverClass) {
            case 'sqlite':
                $concat = implode(' || ', $pk);
                $field = "({$concat} || '')";
                break;
            case 'sqlserver':
                $pk = array_map(function ($keyPart) {
                    return "CAST({$keyPart} AS VARCHAR)";
                }, $pk);
                $concat = implode(' + ', $pk);
                $field = "({$concat} + '')";
                break;
            case 'mysql':
            case 'postgres':
            default:
                $concat = implode(', ', $pk);
                $field = "CONCAT({$concat}, '')";
                break;
        }

        // compile query, faster than raw subquery in most cases
        $ids = $subQuery->all()->extract('entity_id')->toArray();
        $ids = empty($ids) ? ['-1'] : $ids;
        $expression->setField($field);
        $expression->setValue($ids);
        $expression->setOperator('IN');

        $class = new \ReflectionClass($expression);
        $property = $class->getProperty('_type');
        $property->setAccessible(true);
        $property->setValue($expression, 'string');

        $property = $class->getProperty('_isMultiple');
        $property->setAccessible(true);
        $property->setValue($expression, true);

        return $expression;
    }
protected function _inspectComparisonExpression ( Comparison $ expression , $ bundle , Query $ query ) { $ field = $ expression -> getField ( ) ; $ column = is_string ( $ field ) ? $ this -> _toolbox -> columnName ( $ field ) : '' ; if ( empty ( $ column ) || in_array ( $ column , ( array ) $ this -> _table -> schema ( ) -> columns ( ) ) || // ignore real columns ! in_array ( $ column , $ this -> _toolbox -> getAttributeNames ( ) ) || ! $ this -> _toolbox -> isSearchable ( $ column ) // ignore no searchable virtual columns ) { // nothing to alter return $ expression ; } $ attr = $ this -> _toolbox -> attributes ( $ bundle ) [ $ column ] ; $ value = $ expression -> getValue ( ) ; $ type = $ this -> _toolbox -> getType ( $ column ) ; $ conjunction = $ expression -> getOperator ( ) ; $ conditions = [ 'EavValues.eav_attribute_id' => $ attr [ 'id' ] , "EavValues.value_{$type} {$conjunction}" => $ value , ] ; // subquery scope $ subQuery = TableRegistry :: get ( 'Eav.EavValues' ) -> find ( ) -> select ( 'EavValues.entity_id' ) -> where ( $ conditions ) -> order ( [ 'EavValues.id' => 'DESC' ] ) ; // some variables $ pk = $ this -> _tablePrimaryKey ( ) ; $ driverClass = $ this -> _toolbox -> driver ( $ query ) ; switch ( $ driverClass ) { case 'sqlite' : $ concat = implode ( ' || ' , $ pk ) ; $ field = "({$concat} || '')" ; break ; case 'sqlserver' : $ pk = array_map ( function ( $ keyPart ) { return "CAST({$keyPart} AS VARCHAR)" ; } , $ pk ) ; $ concat = implode ( ' + ' , $ pk ) ; $ field = "({$concat} + '')" ; break ; case 'mysql' : case 'postgres' : default : $ concat = implode ( ', ' , $ pk ) ; $ field = "CONCAT({$concat}, '')" ; break ; } // compile query, faster than raw subquery in most cases $ ids = $ subQuery -> all ( ) -> extract ( 'entity_id' ) -> toArray ( ) ; $ ids = empty ( $ ids ) ? [ '-1' ] : $ ids ; $ expression -> setField ( $ field ) ; $ expression -> setValue ( $ ids ) ; $ expression -> setOperator ( 'IN' ) ; $ class = new \ ReflectionClass ( $ expression ) ; $ property = $ class -> getProperty ( '_type' ) ; $ property -> setAccessible ( true ) ; $ property -> setValue ( $ expression , 'string' ) ; $ property = $ class -> getProperty ( '_isMultiple' ) ; $ property -> setAccessible ( true ) ; $ property -> setValue ( $ expression , true ) ; return $ expression ; }
Analyzes the given comparison expression and alters it according.

@param \Cake\Database\Expression\Comparison $expression Comparison expression
@param string $bundle Consider attributes only for a specific bundle
@param \Cake\ORM\Query $query The query instance this expression comes from
@return \Cake\Database\Expression\Comparison Scoped expression (or not)
Analyzes the given comparison expression and alters it according .