Doctrine 可以定义 MySQL 的 Generated 列吗?

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)

dnl*_*tsn 5

首先,我想为这个答案这么晚道歉,但我能够通过 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 查询。

我真的希望这对您有所帮助,因为它对我的用例有帮助 - 有任何问题,请随时提出 :)