【问题标题】:Working with Virtual Fields when using model alias使用模型别名时使用虚拟字段
【发布时间】:2013-08-14 00:38:27
【问题描述】:

我是 CakePHP 新手。我一直在寻找这个问题的答案。

我按照 RichardAtHome 的指示回答了关于 CakePHP 中的自动完成功能 (autoComplete CakePHP 2.0)。

我在我的 AppController 中设置了该功能。

这对真实字段非常有效,但在使用虚拟字段时会出现问题:

class Person extends AppModel {
    public $virtualFields = array(
        'name' => "CONCAT(Person.firstname, ' ', Person.lastname)"
    );
}

我收到此错误:Column not found: 1054 Unknown column 'Person.name' in 'where clause'

检查 SQL 查询时,我看到:

(CONCAT(`Person`.`firstname`, ' ', `Person`.`lastname`)) AS `Person__name`

只有当我使用$model = $this->{$this->modelClass}->alias; 时才会出现这个问题。在特定控制器(不是 AppController)中硬编码模型类可以正常工作。

我需要做什么才能让它工作?

更新:

在摆弄这个之后,我发现它根本与$model = $this->{$this->modelClass}->alias; 无关。

相反,我更改了find() 方法中的'conditions' 值,结果一切正常。我仍然不知道为什么,但现在它工作得很好。

不正确的代码:

$result = $this->$model->find('all', array(
    'conditions' => array(
        $model . '.' . $field . " LIKE '%" . $term . "%'"
    )
));

正确代码:

$result = $this->$model->find('all', array(
    'conditions' => array(
        $model . '.' . $field . " LIKE " => "%" . $term . "%"
    )
));

【问题讨论】:

  • 请显示实际触发错误的完整代码。您是否还确定 $model 实际上包含预期值?请提及您的确切 CakePHP 版本!

标签: cakephp autocomplete cakephp-2.0


【解决方案1】:

这是 CakePHP 核心的问题。您不能在属性声明中使用变量或其他属性。所以你必须重写构造函数并使用 $this->alias 设置你的虚拟字段。核心没有自动的方法在内部处理这个问题,所以你必须照顾它。

顺便说一句,该问题适用于所有模型属性。我们对模型的 $order 属性也有同样的问题。我将在此处粘贴代码,但您必须修改 aliasPrefixing() 方法以不只是通过字符串的开头。用正则表达式替换它,您应该可以将前缀替换方法应用于所有属性。

/**
 * Constructor
 *
 * @param integer|string|array $id Set this ID for this model on startup, can also be an array of options, see above.
 * @param string $table Name of database table to use.
 * @param string $ds DataSource connection name.
 */
   public function __construct($id = false, $table = null, $ds = null) {
        parent::__construct($id, $table, $ds);
       $this->prefixOrderProperty();
    }

/**
 * Prefixes the order property with the actual alias if its a string or array
 *
 * The core fails on using the proper prefix when building the query with two
 * different tables. Already reported this to the core team and might work on a
 * core patch to fix this in the DboSource. The core fix should be done in DboSource,
 * when reading the order property from the model.
 *
 * @return void
 */
    public function prefixOrderProperty() {
        if (is_string($this->order)) {
            $this->order = $this->aliasPrefixing($this->order);
        }
        if (is_array($this->order)) {
            foreach ($this->order as $key => $value) {
                $this->order[$key] = $this->aliasPrefixing($value);
            }
        }
    }

/**
 * Checks if a string of a field name contains a dot if not it will add it and add the alias prefix
 *
 * @param string
 * @return string
 */
    public function aliasPrefixing($string) {
        if (stripos($string, '.') === false) {
            return $this->alias . '.' . $string;
        }
        return $string;
    }

【讨论】:

  • 我认为您的阵列版本是错误的。应该是 $this->order[$this->aliasPrefixing($key)] = $value; 。至少对于我一直使用的:public $order = array('username' => 'ASC');
  • @burzum 我的理解可能有点慢,但这与所描述的问题有什么关系?我可能是错的,但我认为更多的是在条件中使用虚拟字段,至少从链接问题中的代码来看,问题可能是他需要使用 fragment => value 的单个 SQL 片段表示法,以便 CakePHP 生成正确的查询,该查询使用虚拟字段 SQL 片段而不是 WHERE 子句中的给定字段名(不确定这是 CakePHP 中的错误还是实际预期的行为)。
  • 这里还有第二个问题,因为您没有取消设置旧值(导致 SQL 异常)。完整的解决方案可以在这里找到:github.com/dereuromark/tools/blob/master/Model/MyModel.php#L59
猜你喜欢
  • 2010-10-10
  • 1970-01-01
  • 2012-04-29
  • 2019-02-21
  • 2019-01-25
  • 2021-07-05
  • 2018-10-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多