CakePHP 2.X: 复合(连接多个数据库列)虚拟字段作为显示字段
CakePHP 2.X: compound (concatenate several db columns) virtualfield as displayfield
我已经回答了我自己的问题,但我不介意接受任何其他确实比我的方法更好的答案(请提及它如何更好)。请投稿。
我曾遇到过这样一种情况,在我的 User Model
中,我将 first_name, middle_name, last_name
作为 3 个单独的字段,并且只有 first_name
针对 empty/NULL
进行了验证,即其他 2可以是 empty/NULL/whitespace(不想用不合理的验证来惹恼用户,我个人认识一些人 have/use 因为一些疯狂的原因不姓氏)。
有了这样的结构,displayfield
是所有这 3 列的复合,记住其他 2 可能是“”/NULL/white-space(因为它们都是VARCHAR 列)。此外,我的数据库 table 有像 created_by
、modified_by
、approved_by
、assigned_to
这样的列...(这个模型还有很多其他别名,但所有其中在 "CakePHP convention").
之后关系密切
我读了official documentation and several posts here on SO like this one。但其中 none 为这种情况提供了解决方案或示例。也许,我的数据库结构太不传统了,或者我会说 "unorthodox" ;)(好吧,官方文档确实回答了多个模型别名,我错过了好几次,这促使我 post 这个问题并在此处回答。
那么,问题是如何正确处理这样的模型关系和结构?
TL; DR; - 跳转到最终解决方案最后
我将分两部分回答我自己的问题 -
- 如何解决虚拟字段中的多个模型别名
- 如何正确连接字段以获得所需的字段"full name"
1。 模型别名
CakePHP 的官方文档 2.X 有一节关于 Virtual fields and model aliases。
When you are using virtualFields and models with aliases that are not
the same as their name, you can run into problems as virtualFields do
not update to reflect the bound alias. If you are using virtualFields
in models that have more than one alias it is best to define the
virtualFields in your model’s constructor
所以 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');
,您都会得到一个包含 id
和 full_name
用户的数组。
希望这对某人有帮助,或者至少可以作为我自己的日记:)
我已经回答了我自己的问题,但我不介意接受任何其他确实比我的方法更好的答案(请提及它如何更好)。请投稿。
我曾遇到过这样一种情况,在我的 User Model
中,我将 first_name, middle_name, last_name
作为 3 个单独的字段,并且只有 first_name
针对 empty/NULL
进行了验证,即其他 2可以是 empty/NULL/whitespace(不想用不合理的验证来惹恼用户,我个人认识一些人 have/use 因为一些疯狂的原因不姓氏)。
有了这样的结构,displayfield
是所有这 3 列的复合,记住其他 2 可能是“”/NULL/white-space(因为它们都是VARCHAR 列)。此外,我的数据库 table 有像 created_by
、modified_by
、approved_by
、assigned_to
这样的列...(这个模型还有很多其他别名,但所有其中在 "CakePHP convention").
我读了official documentation and several posts here on SO like this one。但其中 none 为这种情况提供了解决方案或示例。也许,我的数据库结构太不传统了,或者我会说 "unorthodox" ;)(好吧,官方文档确实回答了多个模型别名,我错过了好几次,这促使我 post 这个问题并在此处回答。
那么,问题是如何正确处理这样的模型关系和结构?
TL; DR; - 跳转到最终解决方案最后
我将分两部分回答我自己的问题 -
- 如何解决虚拟字段中的多个模型别名
- 如何正确连接字段以获得所需的字段"full name"
1。 模型别名
CakePHP 的官方文档 2.X 有一节关于 Virtual fields and model aliases。
When you are using virtualFields and models with aliases that are not the same as their name, you can run into problems as virtualFields do not update to reflect the bound alias. If you are using virtualFields in models that have more than one alias it is best to define the virtualFields in your model’s constructor
所以 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');
,您都会得到一个包含 id
和 full_name
用户的数组。
希望这对某人有帮助,或者至少可以作为我自己的日记:)