【问题标题】:Getter for a object from the JSON-Field来自 JSON 字段的对象的 Getter
【发布时间】:2018-12-07 11:33:00
【问题描述】:

我有 2 个实体:

class Opponent
{
  ...
  ...
  ...
}

class Process 
{

    /**
     * @var array
     * 
     * @ORM\Column(name="answers_in_related_questionnaires", type="json", nullable=true)
     */
    private $answersInRelatedQuestionnaires = [];

    .
    .        
    . 

}

我在该领域的答案中包含对象对手的其他问题

"opponent": {
 "id":1088,
 "name":"Inora Life Versicherung"
}

我想在实体进程中编写一个 getter,它不仅从对手那里获取值 id 和 name,而且还获取整个实体 Opponent。像这样的:

private function getOpponent() : Opponent
{
    $id = $this->answersInRelatedQuestionnaires['opponent']['id'];
    return $entityManager->getRepository(Opponent::class)->find($id)
}

我已阅读,在实体中使用实体管理器不是一个好主意。我的问题有哪些解决方案?我可以在 Process 实体中使用 Process 存储库吗?

【问题讨论】:

  • 实体之间有关系吗?也许您应该发布您的实体结构以及您想要实现的目标。
  • 是的,关系很多
  • 整个结构非常复杂。我想实现,用一种方法 $process->getOpponent(); 获取整个 Opponent 对象
  • 因为我们看不到实体结构,我认为实现这一目标的最佳方法是使用学说关联/关系 -> symfony.com/doc/current/doctrine/associations.html
  • 与 JSON 字段的关联/关系?恐怕,这是不可能的。

标签: php json symfony orm doctrine


【解决方案1】:

您不应该在实体中注入实体管理器,这是一种非常糟糕的做法,并且违反了类之间的关注点分离。但如果你真的想要,你确实可以在你的实体中注入实体管理器。

良好做法:

创建一个Model/Process 类并在其中包含与您的模型相关的任何功能。教义实体不是模型类。在Model/Process 中,您可以注入实体管理器和您需要的任何其他服务。

编辑:通过创建一个Model/Process 类,我的意思是在您的/src 文件夹中的Model 目录中创建一个名为Process 的类。你的班级路径将是:/src/Model/Process。当然,目录或类的名称可以是任何名称,但这是一个典型的约定。您的 Model 类应该负责您的所有业务逻辑,例如模型的验证等。这确实会使您的代码结构更加复杂,但从长远来看对于大型项目来说将是一种享受。您还需要Model/ProcessManager 以在不同情况下(例如,从数据库加载时、用户表单等)正确填充 Process 模型。当然,最终这一切都是复杂性和可持续性之间的权衡问题。

可以在 here 找到一个关于 Symfony 模型的有趣方法,主要适用于大型项目。

替代方案:

如果您仅在加载实体后访问 opponent 属性,您可以使用 Doctrine PostLoad LifecycleCallback 正确设置 opponent 属性。这不是一个坏习惯:

use Doctrine\Common\Persistence\Event\LifecycleEventArgs;

/**
 * @ORM\Entity()
 * @ORM\HasLifecycleCallbacks()
 */
class Product
{
    // ...
    private $opponentObject;

    /**
     * @ORM\PostLoad
     */
     public function onPostLoad(LifecycleEventArgs $args){
         $em = $args->getEntityManager();

         $id = $this->answersInRelatedQuestionnaires['opponent']['id'];
         $this->opponentObject = $em->getRepository(Opponent::class)->find($id);

     }

     public function getOpponent() {
         return $this->opponent;

     }
} 

最后,如果您真的想将实体管理器注入到您的实体中,您可以通过自动装配通过依赖注入来实现:

use Doctrine\ORM\EntityManagerInterface;

class Process
{
    private $em;

    public function __contruct(EntityManagerInterface $em)
    {
        $this->em = $em;
    }
    ....
}

【讨论】:

  • 不,我不想注入实体管理器。我知道,这是一个非常糟糕的做法。我发现 onPostLoad 的解决方案很有趣。但是你对模型/流程是什么意思?我不明白。能详细解释一下吗?
  • 使用 onPostLoad 的解决方案有效,如果我使用 $this->getDoctrine()->getRepository(Process::class)->find(2000000);但是不起作用,如果我使用查询生成器 $qb = $this->createQueryBuilder('p') ->select('p') ->where('p.id = :processId') -> 获取数据setParameter('processId', 2000000);
  • 编辑了我的答案以更好地解释模型/流程建议。这是一个更复杂的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-08
  • 1970-01-01
  • 1970-01-01
  • 2018-07-10
  • 2019-03-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多