我有
Contact Table : id, first_name, last_name, company_id
Company Table : id, name
我想在联系表中创建虚拟字段,因此它将显示为“contactInCompany”
"first_name last_name - Company.name" e.g: Andre Robin - Google
我怎样才能实现这一点,我尝试这种方式但它不起作用,它不接受另一个虚拟字段作为输入
public $virtualFields = array(
'companyName' => 'SELECT name FROM companies where id = Contact.company_id',
'customerWithCompany' => "CONCAT(Contact.first_name, ' ',
Contact.last_name, ' ', Contact.companyName, '')"
);
我也是这样尝试过的,但它不起作用
'customerWithCompany' => "CONCAT(Contact.first_name, ' ', Contact.last_name, '-',
SELECT name FROM companies where id = Contact.company_id)"
我经常需要这个,我会用这个来放入下拉选择框以选择联系人,所以我希望将联系人姓名与公司一起显示
答案 0 :(得分:8)
您不能对虚拟字段执行此操作,因为虚拟字段中的键只是别名
示例:
class Contact extends AppModel {
public $virtualFields = array(
'companyName' => 'SELECT name FROM companies where id = Contact.company_id',
'customerWithCompany' => "CONCAT(Contact.first_name, ' ',
Contact.last_name, ' ', Contact.companyName, '')"
);
public function getContacts() {
return $this->find('all', array(
'fields'=>array(
'Contact.id',
'Contact.first_name',
'Contact.companyName',
'Contact.customerWithCompany'
)
)
);
}
}
如果从ContactsController调用getContacts()方法
以上代码将形成此查询:
SELECT Contact.id, Contact.first_name,
(SELECT name FROM companies where id = Contact.company_id) AS Contact__companyName,
CONCAT(Contact.first_name, ' ', Contact.last_name, ' ', Contact.companyName, '') AS Contact__customerWithCompany
FROM contacts AS Contact;
此查询不会在mysql上执行,因为无法访问另一列的1列别名。
要实现这一点,你必须使用如下的子查询:Cake php将虚拟字段名称转换为Model__(在下面的例子中是Contact __)
SELECT
SubQuery.id,
SubQuery.first_name,
SubQuery.Contact____companyName,
CONCAT(SubQuery.first_name, ' ', SubQuery.last_name, ' ', SubQuery.Contact____companyName, '') AS Contact__customerWithCompany
FROM
(SELECT Contact.id, Contact.first_name, (SELECT name FROM companies where id = Contact.company_id) AS Contact__companyName
FROM contacts AS Contact) AS SubQuery;
如果你想在cake php中构建子查询,请使用 buildStatement DataSource方法
注意:使用联接是上述查询的另一个更好的解决方案,可以在不使用子查询的情况下获得相同的结果。
加入:
public function getContacts() {
$this->virtualFields['customerWithCompany'] = "CONCAT(Contact.first_name, ' ', Contact.last_name, ' ', Company.name)";
return $this->find('all', array(
'fields'=>array(
'Contact.id',
'Contact.first_name',
'Contact.last_name',
'Company.name',
'Contact.customerWithCompany'
),
'joins'=>array(
array(
'table'=>'companies',
'alias'=>'Company',
'type'=>'LEFT',
'conditions'=>array(
'Contact.company_id = Company.id'
)
)
)
)
);
}
答案 1 :(得分:2)
您不需要virtualField。使用JOIN LEFT进行此简单查询。
$users= $this->Contact->query('SELECT CONCAT(first_name," ",last_name," - ", companies.name) AS customerWithCompany FROM users
LEFT JOIN companies on contact.company_id = companies.id');
阅读数据:
$userList = array();
foreach ($users as $user) {
$userList[] = $user[0]['customerWithCompany'];
}
var_dump($userList);
输出:
array(
(int) 0 => 'Harts Jackson - Google'
(int) 1 => 'Emo Rock - Yahoo'
...
)
并且virtualFields的实现也有一些限制。首先,您不能在关联模型上对条件,顺序或字段数组使用virtualField。这样做通常会导致SQL错误,因为字段不会被ORM替换。这是因为很难估计可能找到相关模型的深度。
如果您没有关联的模型(我可以看到您已经拥有并希望分配条件),那么您必须在Contact模型中创建构造函数方法并在构造函数中设置virtualFiled。这是How to create $virtualFields
答案 2 :(得分:1)
在您的联系人模型中写下以下内容:
public $belongsTo = array(
'Company' => array(
'className' => 'Company',
'foreignKey' => 'company_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
在公司模型中写道:
public $hasMany = array(
'Contact' => array(
'className' => 'Contact',
'foreignKey' => 'company_id',
'dependent' => false,
),
}
现在,当您搜索任何联系人时,它也会包含相关公司的相关信息。打印阵列,您将看到公司索引。
PS:如果我的问题不正确,请告诉我确切的问题,我可以帮助你。
答案 3 :(得分:0)
在您的联系人模型中,请尝试以下操作:
public $belongsTo = array('Company');
public $actsAs = array('Containable');
public $virtualFields = array(
'customerWithCompany' => "CONCAT(Contact.first_name, ' ',
Contact.last_name, ' ', Company.name, '')"
);
并在您的控制器中执行以下操作:
$this->Contact->find(
'list',
array(
'fields' => array('Contact.id', 'Contact.customerWithCompany'),
'contain' => array('Company')
)
);
答案 4 :(得分:0)
我不确定,但尝试在各自的模型构造函数中设置虚拟字段。
答案 5 :(得分:0)
这不是主题,但这个带有相关模型的虚拟领域有效:
Orderitem hasMany Necessary
Necessary hasMany Recipe
Necessary hasMany Storage
'inrecipe' => 'SELECT COUNT(Necessary.id)
FROM necessaries AS Necessary
INNER JOIN recipes AS Recipe
ON Necessary.recipe_id = Recipe.id
WHERE Orderitem.id = Necessary.orderitem_id ',
这也有效
'instorage' => 'SELECT COUNT(Necessary.id)
FROM necessaries AS Necessary
INNER JOIN recipes AS Recipe
ON Recipe.id=Necessary.recipe_id
INNER JOIN storages AS Storage
ON Storage.id=Necessary.storage_id
AND Recipe.quantity = Storage.quantity
WHERE Orderitem.id = Necessary.orderitem_id ',
更复杂......
'resolution' => 'SELECT IF(
(SELECT COUNT(Necessary.id)
FROM necessaries AS Necessary
INNER JOIN recipes AS Recipe
ON Recipe.id=Necessary.recipe_id
INNER JOIN storages AS Storage
ON Storage.id=Necessary.storage_id AND Recipe.quantity=Storage.quantity
WHERE Orderitem.id = Necessary.orderitem_id )
=
(SELECT COUNT(Necessary.id)
FROM necessaries AS Necessary
INNER JOIN recipes AS Recipe
ON Necessary.recipe_id = Recipe.id
WHERE Orderitem.id = Necessary.orderitem_id )
,"YES", "NO") ',