【问题标题】:Symfony | Doctrine Help Needed - Inserting in Multiple TablesSymfony |需要教义帮助 - 在多个表中插入
【发布时间】:2014-01-18 10:43:43
【问题描述】:

我有 3 张桌子:

  1. 产品 - 产品 ID、产品名称、价格、类型、创建时间
  2. 网关 - gateway_id、gateway_name、create_time
  3. mapping_product_gateways - mapping_id、gateway_id、product_id

products 和 gateways 表没有任何共同之处。没有外键等。但是当我创建产品时,我将网关选择字段显示为多选字段,其中填充了网关表中的数据。一旦我点击提交按钮插入产品记录,此时所有选定网关的 ID 都将插入到 mapping_product_gateways 表中,具有相同的 product_id 和选定网关 ID。

所以插入后的记录可能如下所示:

产品表记录:

1,产品 1,10 美元,数字,2013 年 10 月 10 日

2,产品 2,13 美元,订阅,2013 年 1 月 1 日

网关表记录:

1,贝宝,2014 年 3 月 1 日

2,信用卡,01/01/2014

3, 2Checkout, 02/01/2014

因此,mapping_product_gateways 记录可能如下所示:

mapping_id、gateway_id、product_id

1、2、1

2、3、1

3、1、2

3、2、2

这意味着产品 ID 1 具有与之关联的网关 2 和 3,而产品 ID 2 具有与之关联的网关 1 和 2。

由于映射和产品表之间没有直接关系,如何在存储库类中建立查询来进行记录的搜索、插入、更新?或者我是否需要创建一个类型的关系 n 实体?

我完全糊涂了..对不起,我对 symfony 很陌生。

谢谢

【问题讨论】:

    标签: symfony doctrine-orm


    【解决方案1】:

    这个问题不是一个 symfony 问题,而是一个教义问题。 首先,您不应该问自己“数据库会是什么样子?”。更好的问题是:“产品和网关是如何关联的?”

    据我了解您的帖子: - 许多产品可以有许多网关。

    所以我们谈论的是多对多关联。这就是为什么您需要(“数据库将是什么样子?”)关联两个表的第三个表的原因。 但是我们需要回答第二个问题(“产品和网关是如何关联的?”) 答:它们通过多对多关联关联。

    这在教义上是如何实现的?

    /**
    * @ORM\Entity()
    */
    class Product{
        /*
        * @ORM\ManyToMany(targetEntity="Gateway", inversedBy="products")
        */
        private $gateways;
        //adder + setter + getter
    }
    
    /**
    * @ORM\Entity()
    */
    class Gateway{
        /*
        * @ORM\ManyToMany(targetEntity="Product", mappedBy="gateways")
        */
        private $products;
        //adder + setter + getter
    }
    

    要更新架构,请在您的 cmd(应用根目录)中执行 php app/console dictionary:schema:update --force

    这就是方法,教义解决问题。不错,不是吗?

    您的第二个问题是:我如何对实体进行 CRUD?

    假设您在控制器中编码。您的数据库没有产品,但有 5 个网关(ID 1-5)

    class someController extends Controller {
        public function doSomeCrud(){
            $em = $this -> get('doctrine.orm.entity_manager');
            $product = new Product();
            $someGateway = $em -> find('NAMESPACE\Gateway',3);
            $anotherGateway = $em -> find('NAMESPACE\Gateway',5);
            $product -> addGateway($someGateway) -> addGateway($anotherGateway);
            $em -> persist($product);
            $em -> flush();
        }
    }
    

    调用该方法后,您的数据库将如下所示:

    产品:1

    网关:1;2;3;4;5

    Product_Gateway:(1,1,3);(2,1,5)

    您可以通过

    获取一个产品的所有网关
    $product -> getGateways();
    

    并通过以下方式更新产品:

    $product -> getGateways() -> first() -> setName('new name');
    $em -> flush();
    

    实体管理器识别出网关 3 的名称已更改,并设置了 UPDATE Gateway set name='new name' WHERE id = 3

    【讨论】:

    【解决方案2】:

    您仍然缺少的是 setter 和 getter(例如 product -> gateways):

    public function addGateway(GatewayInterface $gateway){
        $this -> gateways -> add($gateway);
        return $this;
    }
    
    public function setGateways(Collection $gateway){
        $this -> gateways = $gateways;
        return $this;
    }
    
    public function getGateways(){
        return $this -> gateways;
    }
    

    您需要先创建 GatewayInterface 才能使其工作。 并且您需要相同的设置器/获取器用于网关 -> 产品

    索引操作(创建产品)必须如下所示:

    public function indexAction()
    {
        $em = $this->getDoctrine()->getManager();
        $product = new ShopProducts();
        $em -> persist($product);
        $gateway = new GlobalGateways();
        $em -> persist($gateway);
        $product -> addGateway($gateway);
        $em -> flush();
    }
    

    注意:您应该始终以单数命名您的课程。所以如果名字是“Product”和“GlobalGateway”会更好

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-09
      • 2021-12-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多