【问题标题】:ManyToOne association for zfcuser doctrine entity with bjyauthorize与 bjyauthorize 的 zfcuser 学说实体的 ManyToOne 关联
【发布时间】:2015-05-18 22:31:40
【问题描述】:

我在我的 zf2 项目中使用 zfcuser 学说模块和 bjyauthorize,它工作得很好。现在我想从我的用户实体中获取连接的国家实体

在 User.php 中:

/**
 * An example of how to implement a role aware user entity.
 *
 * @ORM\Entity
 * @ORM\Table(name="users", indexes={
 *      @ORM\Index(name="fk_User_Country1_idx", columns={"Country_id"}), 
 * }, uniqueConstraints={@ORM\UniqueConstraint(name="email_UNIQUE", columns={"email"})})
 * @ORM\HasLifecycleCallbacks()
 */
class User implements UserInterface, ProviderInterface
{

...

/**
 * @var ersEntity\Country
 * @ORM\ManyToOne(targetEntity="Country", inversedBy="users")
 * @ORM\JoinColumn(name="Country_id", referencedColumnName="id")
 */
protected $country;

在 Country.php 中

/**
 * Entity\Country
 *
 * @ORM\Entity()
 * @ORM\Table(name="Country")
 * @ORM\HasLifecycleCallbacks()
 */
class Country implements InputFilterAwareInterface
{

...

/**
 * @ORM\OneToMany(targetEntity="User", mappedBy="country")
 * @ORM\JoinColumn(name="id", referencedColumnName="Country_id")
 */
protected $users;

我的一个控制器中的一个简单的 testAction 失败了:

$user = $em->getRepository("ersEntity\Entity\User")
    ->findOneBy(array('id' => 1));
error_log($user->getFirstname().' '.$user->getSurname());
error_log('country: '.$user->getCountry()->getName());

导致:

[Tue May 19 00:02:44 2015] [error] [client 185.17.207.16] Andi N.
[Tue May 19 00:02:44 2015] [error] [client 185.17.207.16] PHP Fatal error:  Call to a member function getName() on a non-object in /home/ers/www/ers/module/Admin/src/Admin/Controller/TestController.php on line 172

我想知道为什么不能从 User 实体中获取 Country 实体。对于同一项目中的其他实体,这可以正常工作。

谁能告诉我需要做什么才能让 Country 实体脱离这个 zfcuser-bjyauthorize-doctrine 用户实体?

有关更多代码信息,整个项目可在开发分支的https://github.com/inbaz/ers 获得。

编辑:

对于未设置国家/地区的用户,肯定会出现错误。有必要检查一个国家是否存在是对的。但是这个用户有一个国家集。我通过 phpmyadmin 进行了检查。无法通过 getCountry() 方法获取该国家/地区实体。

这可能是导致将条令实体反序列化和序列化到会话中的原因。我检查了doctrine documentation,了解如何将实体保存到会话中。但我想将所有子实体保留在会话中,所以在我的情况下,我在会话中有一个订单实体,其中包含多个包实体。每个包裹实体都有一个用户和多个项目实体。从会话中获取订单实体时,我希望能够访问所有这些元素。

我什至尝试对会话中的每个用户进行合并,例如:

foreach($participants as $participant) {
    $participant = $em->merge($participant);
}

但这不会改变任何事情。甚至整个订单的合并都不成功。

您对如何从会话中恢复具有完整学说功能的学说实体有任何想法吗?

【问题讨论】:

    标签: php doctrine-orm zend-framework2 zfcuser bjyauthorize


    【解决方案1】:

    在我看来一切都很好。起初我认为您的实体定义中缺少您的getCountry 方法,但我看到了it is there

    我的猜测是 id 为 1 的用户没有设置国家/地区。转到您的表(phpmyadmin 或其他)并检查 Country_id 列的值。 如果您希望每个用户都有一个国家/地区,您可以根据the Doctrine2 @JoinColumn specs 在连接列定义中添加 nullable=false 来确保数据完整性。

    否则(如果$country 允许为null),您可能应该在拉动getName() 之前先检查国家是否是一个对象:

    $countryName = null;
    $country = $user->getCountry();
    if(is_object($country)){
        $countryName = $country->getName();
    }
    /** @var null|string $countryName */
    $countryName  //... use your country name which is null or string
    

    还有一点,我强烈建议tablecolumn 名称只使用小写 字符串。使用大写字母可能会给您带来麻烦。

    编辑

    我仔细看了看,现在发现您的映射是错误的。你use doctrine to validate your schema了吗?在关系的反面(在 Country.php 中)有一个@ORM\JoinColumn。反面不需要这个@ORM\JoinColumn 声明。您应该删除此行。拥有方是用户,所以连接列定义应该只在那里声明。

    应该是这样的:

    Country.php:

    /**
     * @var Collection
     * @ORM\OneToMany(targetEntity="User", mappedBy="country")
     */
    protected $users;
    

    用户.php:

    /**
     * @var Country
     * @ORM\ManyToOne(targetEntity="Country", inversedBy="users")
     * @ORM\JoinColumn(name="Country_id", referencedColumnName="id")
     */
    protected $country;
    

    【讨论】:

    • 用户可以选择国家,但不需要。所以国家可以为空。我在 Country.php 中删除 JoinColumn 前后验证了我的方案。两者都可以: [映射] 正常 - 映射文件是正确的。 [数据库] OK - 数据库架构与映射文件同步。教义本身无法在这里找到错误。这可能是将用户实体反序列化和序列化到会话中的问题吗?反序列化后,无法再获取 Country 实体。
    • 是的,在会话中存储实体时,您应该关注certain the documentation。我建议只在会话中存储 id,并在需要时再次解析对象。
    【解决方案2】:

    Doctrine 2: Can entities be saved into sessions?

    这是我的问题的答案。

    如果延迟加载的实体在序列化时未加载,则在反序列化后将无法加载。因此,您必须确保实体在序列化之前已完全加载。

    如果无法创建一个新的学说实体并获取反序列化实体的数组副本并将此数据填充到新实体中,那么问题仍然存在。

    【讨论】:

    • 我建议不要将序列化实体存储在会话存储中。更好的是只存储user_id 并从数据库中解析实体。您可以创建一个ObjectManagerAware 的存储并实现getUser 方法,以便您可以执行$sessionService->getUser()。您从会话存储中获取 user_id 并使用 ObjectManager 的实例在此 getUser 方法中解析您的 User 实体。像这样,您始终拥有一个带有最新数据的 User 实例。
    猜你喜欢
    • 1970-01-01
    • 2016-09-21
    • 1970-01-01
    • 2014-09-27
    • 2018-07-19
    • 1970-01-01
    • 1970-01-01
    • 2015-06-18
    • 1970-01-01
    相关资源
    最近更新 更多