CakePHP 2.X:复合(连接几个db列)virtualfield为displayfield

时间:2016-02-24 06:10:16

标签: cakephp cakephp-2.0

我已经回答了我自己的问题,但我不介意接受任何其他比我的方法更好的答案(提一下它是如何更好的)。请贡献。

我遇到的情况是User Model,我有first_name, middle_name, last_name个3个单独的字段,只有first_nameempty/NULL验证,即其他2个可以空/ NULL /空格(不想用不合理的验证来惹恼用户,我个人知道那些因某些疯狂的原因而没有使用姓氏的人。)

有了这样的结构,可以合理地期望displayfield作为所有这3列的复合,记住其他2可能是"" / NULL / white-space (因为它们都是VARCHAR列)。此外,我的数据库表格包含created_bymodified_byapproved_byassigned_to等列...(此模型的其他别名很多,但所有这些都很相关遵循" CakePHP惯例")。

我在SO official documentation上阅读了like this one和几个帖子。但是他们都没有为这种情况提供解决方案或样本。也许,我的数据库结构太不寻常了,或者我说'非正统'" ;)(好吧,官方文档确实回答了多个模型别名,我错过了几次,这促使我发布这个问题并在此处回答它。)

那么,问题是如何正确地解决这种模型关系和结构?

1 个答案:

答案 0 :(得分:0)

<强> TL; DR; - 最后跳转到最终解决方案

我将分两部分回答我自己的问题 -

  1. 如何在虚拟字段中处理多个模型别名
  2. 如何正确连接字段以获得所需&#34;全名&#34;
  3. 1。 模型别名

    CakePHP 2.X的官方文档有一个关于Virtual fields and model aliases的部分。

      

    当您使用虚拟字段和具有非别名的模型时   与其名称相同,您可以像virtualFields那样遇到问题   不更新以反映绑定别名。如果您使用的是virtualFields   在具有多个别名的模型中,最好定义   模型构造函数中的virtualFields

    所以User.PHP中的类似内容应允许virtualFields适用于您为模型提供的任何别名:

    public function __construct($id = false, $table = null, $ds = null) {
        parent::__construct($id, $table, $ds);
        $this->virtualFields['name'] = sprintf(
            'CONCAT(%s.first_name, " ", %s.middle_name, " ", %s.last_name)', $this->alias, $this->alias, $this->alias
        );
    }
    

    2。 清空中间名和姓氏

    这可以通过模型构造函数中的一些额外SQL语法来解答,为简单起见,我使用CASE ... WHEN ... THEN ... ELSE ... END,可以用更好的SQL代替(如果可能)。但是这个也不会失败(并且也不错)。

    CONCAT(%s.first_name, CASE WHEN %s.middle_name = "" THEN " " ELSE CONCAT(" ", %s.middle_name, " ") END, %s.last_name)
    

    最终解决方案

    在模型构造函数中:

    public function __construct($id = false, $table = null, $ds = null) {
        parent::__construct($id, $table, $ds);
        $this->virtualFields['full_name'] = sprintf(
            'CONCAT(%s.first_name, CASE WHEN %s.middle_name = "" THEN " " ELSE CONCAT(" ", %s.middle_name, " ") END, %s.last_name)', $this->alias, $this->alias, $this->alias, $this->alias
        );
    }
    

    最后,通常是public $displayField = 'full_name';

    现在,无论您在控制器中执行$this->RelatedModel->UserAlias->find('list');,您都会得到一个包含用户idfull_name的数组。

    希望这可以帮助某人,或者至少为我自己担任期刊:)