symfony 3 学说不接受主键

Posted

技术标签:

【中文标题】symfony 3 学说不接受主键【英文标题】:symfony 3 doctrine does not accept primary key 【发布时间】:2017-05-15 21:06:58 【问题描述】:

我是 Symfony 的新手,正在尝试设置实体和关系。即使我似乎正确地注释了主键。

运行时

php bin/控制台原则:schema:validate

我收到如下错误:

引用的列名“brandId”必须是目标实体类“AppBundle\Entity\Brands”上的主键列。

实体看起来像(仅相关部分):

谢谢

品牌

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity
 * @ORM\Table(name="brands")
 */
class Brands

/**
 * @ORM\Id
 * @ORM\Column(type="smallint",length=3,unique=true,options="unsigned":true)
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $brandId;

/**
 * one brands has many models
 * @ORM\OneToMany(targetEntity="Models", mappedBy="brandId")
 * @ORM\JoinColumn(name="brandId", referencedColumnName="brandId")
 */
private $models;

public function __construct()

    $this->models = new ArrayCollection();

型号:

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;


/**
 * @ORM\Entity(repositoryClass="AppBundle\Repository\ModelsRepository")
 * @ORM\Table(name="models")
 */
class Models

/**
 * @ORM\Column(type="smallint",length=4,unique=true,options="unsigned":true)
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $modelId;

/**
 * @ORM\Column(type="string", length=25)
 */
private $model;

/**
 * Many models for one brand
 * @ORM\ManyToOne(targetEntity="Brands",inversedBy="models")
 * @ORM\JoinColumn(name="brandId", referencedColumnName="brandId")
 */
private $brandId;

【问题讨论】:

只需按照这里的示例:docs.doctrine-project.org/projects/doctrine-orm/en/latest/… 修复关系后,将 Model::brandId 更改为 Model::brand @Cerad。谢谢,但为什么我要包括 ::brand 这是品牌名称的字段(如福特、宝马等)?它当然不会推动(双关语)任何关系。 因为品牌是品牌对象。 brandId 只是唯一标识符。对于 Doctrine 2,请尝试根据对象而不是数据库列名来思考。 【参考方案1】:

一个有效且干净的实体映射应该是这样的:

品牌.php

/**
 * @ORM\Entity
 * @ORM\Table(name="brands")
 */
class Brand

    /**
     * @var integer
     *
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    protected $id;

    /**
     * one brands has many models
     *
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\Model", mappedBy="brand")
     */
    private $models;

    public function __construct()
    
        $this->models = new ArrayCollection();
    

模型.php

class Model

    /**
     * @var integer
     *
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=25)
     */
    private $name;

    /**
     * Many models for one brand
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Brand",inversedBy="models")
     */
    private $brand;

为了干净和易于使用:

$brand->getId(); //get id of brand
$brand->getModels(); //get array of Model object, ArrayCollection
$model->getBrand()->getId(); // Get id of related brand of some model 
$model->getBrand()->getName(); //get the name of other propery of related brand

【讨论】:

感谢@rafrsr 提供有关正确设置实体的所有好的指示。作为初学者,他们当然非常感激。尽管如此,这并没有解决我的问题,正如我上面所说,似乎有一些更改没有从缓存中清除并导致错误。我需要了解如何从头开始重新初始化所有实体。【参考方案2】:

在您的 Brands 模型中,不应存在此注释。

* @ORM\JoinColumn(name="brandId", referencedColumnName="brandId")

JoinColumn 仅适用于 ManyToOneOneToOne 字段。这是因为在一对多关系中,表中不会有包含关系拥有(“一”)方数据的连接列。

JoinColumn 用于在“多”端定义一个列,用于标识“一”端的哪个记录拥有它,因此将其包含在Models 模型中是可以的。

【讨论】:

这是一个开始。现在清理模型实体。 @Cerad 我知道命名有点不对劲,但该实体中的关系定义是否错误?我认为 JoinColumn 注释将转换为“在模型中创建一个brandId 列,该列引用品牌中的brandId 列”。我一定是错过了什么。 @Don'tPanic,正如你所说,它应该可以工作。我相信那是另一回事。我已经更改了一些字段名称,虽然我确实刷新了缓存,但似乎仍有一些东西挂在那里。我需要回去并找到一种从头开始重新初始化实体的方法。【参考方案3】:

已删除错误答案...

额外提示:实体类或更好的实例应该代表表的单个数据集。所以他们的名字应该是单数的;) 通过为主键列选择不带前缀的名称,您可以节省一些代码,因为 Doctrine 可以发挥它的魔力。 此外,如果您不为所有列添加前缀,则不应在其中一列中添加表名前缀。

【讨论】:

关闭但不完全。在 OneToMany 关系上有一个参考列是否有意义? docs.doctrine-project.org/projects/doctrine-orm/en/latest/… @funcOder。我很清楚该字段需要成为主键。如果你回到我的问题,问题是 Symfony 不接受指令。根据所谓的教义魔法,我有一些不那么讨人喜欢的替代形容词。 @func0der,对不起,为什么要加入brandId=modelId。这似乎没有意义。如果您要执行 mysql 查询,则类似于 INNER JOIN ON (brand.brandId = models.brandId) 是的,对不起。你说的对。反正。使用文档重新检查您的代码。我认为你正在使用'mappedBy' wronf。【参考方案4】:

这一切都成为了 Doctrine 命名策略的问题,我并不知道。见this article for details

该策略被设置为默认值,而我正在尝试使 mysql 的下划线命名策略适应 PHP 的驼峰命名策略。这导致 Symfony 找不到主节点,从而导致错误。

一旦我了解了这一点,并根据我在这篇文章中收到的宝贵意见,我将实体重构如下:

谢谢大家。

品牌

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity
 * @ORM\Table(name="brands")
 */
class Brands

/**
 * @var integer
 * 
 * @ORM\Id
 * @ORM\Column(type="smallint",length=3,unique=true,options="unsigned":true)
 * @ORM\GeneratedValue(strategy="AUTO")
 */
protected $id;

/**
 * one brands has many models
 * 
 * @ORM\OneToMany(targetEntity="Models", mappedBy="brandId")
 */
private $models;

public function __construct()

    $this->models = new ArrayCollection();


/**
 * @ORM\Column(type="string", length=25)
 */
private $brand;
.......

型号

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;


/**
 * @ORM\Entity(repositoryClass="AppBundle\Repository\ModelsRepository")
 * @ORM\Table(name="models")
 */
class Models

/**
 * @var integer
 *
 * @ORM\Id
 * @ORM\Column(type="smallint",length=4,unique=true,options="unsigned":true)
 * @ORM\GeneratedValue(strategy="AUTO")
 */
protected $id;

/**
 * @ORM\Column(type="string", length=25)
 */
private $model;

/**
 * Many models for one brand
 * @ORM\ManyToOne(targetEntity="Brands",inversedBy="models")
 * @ORM\JoinColumn(name="brand_id", referencedColumnName="id")
 */
private $brandId;

/**
 * Many models for one segment
 * @ORM\ManyToOne(targetEntity="Segments", inversedBy="models")
 * @ORM\JoinColumn(name="segment_id", referencedColumnName="id")
 */
private $segmentId;
.....
 

【讨论】:

以上是关于symfony 3 学说不接受主键的主要内容,如果未能解决你的问题,请参考以下文章

Symfony/学说

Symfony 4.3 学说迁移问题

如何防止不需要的学说在symfony 4中持续存在?

Symfony - 使用学说获取最后一个 ID

Symfony学说OneToAll关系

使用连接表返回结果的学说不起作用 Symfony2