Ben*_*ndy 6 php mysql symfony doctrine-orm
在 Symfony 实体中使用mySQL 生成的列是否正确(如果正确的话)?
例如,GENERATED ALWAYS在下面的例子中:
CREATE TABLE contacts (
id INT AUTO_INCREMENT PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
fullname varchar(101) GENERATED ALWAYS AS (concat(first_name,' ',last_name)),
email VARCHAR(100) NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
我知道这可以在实体中完成,__construct()但由 Doctrine/mySQL 处理是否更正确?就像是:
/**
* @ORM\Column(type="text")
* @ORM\Generated(concat(first_name,' ',last_name))
*/
private $fullname;
Run Code Online (Sandbox Code Playgroud)
首先,我想为这个答案这么晚道歉,但我能够通过 DQL 为基本的 SELECT 和 JOIN 查询创建一个解决方法。由于修改了结果实体,我没有使用 UPDATE 查询对此进行测试。
正如上面的用户 dbu 所指出的,您需要首先遵循本指南:https ://www.liip.ch/en/blog/doctrine-and-generated-columns
这可以防止学说在运行模式构建器时尝试修改生成的列。当实体更新发生时,这没有学说忽略该列。
您需要确保创建添加生成列的迁移。我是这样实现的:
/**
* Adds a generated column for fullname to the contacts table
*
* @param Schema $schema
*/
public function up(Schema $schema)
{
$this->addSql('
ALTER TABLE
contacts
ADD COLUMN
fullname varchar(101) GENERATED ALWAYS AS (concat(first_name,' ',last_name));
');
}
Run Code Online (Sandbox Code Playgroud)
有了上述基础工作,您应该能够让学说使用模式构建器正常生成数据库模式,并且在通过迁移添加时不会干扰生成的列。
现在下一个问题是确保您的数据可以被添加到您的联系人实体中,而不会在 UPDATE 和 INSERT 查询期间尝试修改数据库上的结果。
诀窍是创建另一个实体来扩展您当前的联系人实体,并且仅用于 SELECT 和 JOIN 查询。
<?php
namespace Embark\ApiBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Generated values from the contacts table
*
* @ORM\Table(name="contacts")
* @ORM\MappedSuperclass
*/
class ContactGenerated extends Contact
{
/**
*
* @ORM\Column(name="fullname", type="string", nullable=true)
*/
private $fullname;
}
Run Code Online (Sandbox Code Playgroud)
@MappedSuperClass 注释可防止学说模式构建器尝试创建具有相同名称的表。
然后您可以使用 DQL 来获取数据:
$queryBuilder->select('contact')
->from(ContactGenerated::class, 'contact');
Run Code Online (Sandbox Code Playgroud)
这将返回一组 ContactGenerated 实体。如果您尝试保留它们,您会遇到问题,您应该真正将它们视为只读。
我将让您自行决定如何将这些转换为标准 Contact 类,该类删除不存在的“全名”属性,这将允许您从选择中执行 UPDATE 查询。
我真的希望这对您有所帮助,因为它对我的用例有帮助 - 有任何问题,请随时提出 :)