簡體   English   中英

批量導入時,如何填寫ManyToOne關系的字段?

[英]When batch importing, how do I fill in the field of a ManyToOne relationship?

我正在嘗試導入一批記錄(票據),但我與客戶之間存在多對一關系。 如何填寫該關系的“數據庫”列?

我在實體中使用了fromArray的函數,我在該實體中傳遞了字段列表和一條記錄的值(數據源是CSV)。 然后在該函數內部,我只需將每個列值分配給相應的屬性。 但是,屬性Customer是一個對象,因此我需要傳遞一個我沒有的對象。

我已經考慮過將實體管理器注入到我的實體中,但這被認為是一種糟糕的做法,所以我有點受阻。

我還嘗試添加一個額外的屬性customerId希望它會強制寫入值,但它似乎堅持使用關系值而不是屬性值。

這是我的代碼:

class Bill

    /**
     * @var string
     *
     * @ORM\Column(name="docId", type="string", length=25, nullable=false)
     * @ORM\Id
     */
    private $id;

    /**
     * @var float|null
     *
     * @ORM\Column(name="amount", type="float", precision=10, scale=0, nullable=true)
     */
    private $amount;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Customer", inversedBy="bills")
     * @ORM\JoinColumn(name="customerId", referencedColumnName="customerId", nullable=false)
     */
    private $customer;

    public function getCustomer(): ?Customer
    {
        return $this->customer;
    }

    public function setCustomer( $customer): self
    {
        $this->customer = $customer;

        return $this;
    }

    //this is where we import
    public static function fromCSVRecord($header, $line)
    {
        $object = new self;
        foreach($header as $key => $field){
            try{
                switch($field){
                    case 'customerId':
                        //get the customer here from EM but we don't have EM
                        $customer = $em->getRepository(Customer::class)->find($line[$key]);
                        $object->setCustomer($customer);
                        break;
                    default:
                        $object->$field = $line[$key];
                        break;
                }
            }catch(\Exception $e){
                dd($line[$key]);
            }

        }

        return $object;
    }
}

我希望有一種簡單的方法可以使用ORM導入記錄值,而不必將實體管理器注入到實體類中。

您的問題是您試圖將此責任歸於錯誤的班級。 您正確理解的是,您需要在實體內部需要實體管理器的巨大代碼氣味使您無法理解,因為那是執行該操作的錯誤位置。

將其移至存儲庫。 無論如何,這是一個更合乎邏輯的地方,並且您已經有了可用的實體管理器。

class BillRepository extends ServiceEntityRepository
{
  //..

  public function addFromCSVRecord($header, $line) {

    $em   = $this->getEntityManager();
    $bill = new Bill();

    foreach ($header as $key => $field) {
         try {
              switch ($field) {
                 case 'customerId':
                     $customer = $em->getRepository(Customer::class)->find($line[$key]);
                      // alternatively, if you are certain of the incoming data and you do not want to hit the DB...
                      // $customer = $this->getEntityManager()->getReference(Customer:class, $line[$key]);
                      $bill->setCustomer($customer);
                      break;
                 default:
                      $bill->$field = $line[$key];
                      break;
                 }
             } catch (\Exception $e) { dd($line[$key]); }
        }
        // return $object;
        $em->persist($bill);
        $em->flush();
    }
} 

我不了解您在方法中發現的大部分邏輯,因為我不知道具體細節。 盡管更改了實際持久存儲數據的return值,但是對addFromCsvRecord()的一次調用將創建新的對象並將其持久存儲在數據庫中。

請注意,在我的答案中,我向您展示了如何使用EntityManager::getReference()為客戶生成對象引用。 如果您可以信任輸入文件,則將稍快一些,因為您無需單擊該對象的數據庫。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM