2016-05-06 1 views
1

Doctrine2エンティティを更新していくつかのフィールドを除外する必要がある状況です。ZF2 Doctrine2の更新からエンティティフィールドを除外

ZF2では、Zend \ Formと検証フィルタを使用して更新を処理するアクションがあります。特にDishエンティティは、と呼ばれ、が必要なブロブ列を持っています。です。更新中は、新しいファイルが提供されている場合にのみ、写真を置き換えたいと思います。

エンティティのソースコードと、料理を更新するコントローラアクションがあります。

料理\エンティティ\ Dish.php

<?php 
namespace Dishes\Entity; 

use Doctrine\ORM\Mapping as ORM; 

/** @ORM\Entity **/ 
class Dish 
{ 
    /** 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    * @ORM\Column(type="integer") 
    **/ 
    protected $id; 

    /** 
    * @ORM\Column(type="string") 
    */ 
    protected $name; 

    /** 
    * @ORM\Column(type="text") 
    */ 
    protected $description; 

    /** 
    * @ORM\Column(type="integer") 
    */ 
    protected $time; 

    /** 
    * @ORM\Column(type="integer") 
    */ 
    protected $complexity; 

    /** 
    * @ORM\Column(type="blob") 
    */ 
    protected $photo; 

    /** 
    * Magic getter to expose protected properties. 
    * 
    * @param string $property 
    * @return mixed 
    */ 
    public function __get($property) 
    { 
    return $this->$property; 
    } 

    /** 
    * Magic setter to save protected properties. 
    * 
    * @param string $property 
    * @param mixed $value 
    */ 
    public function __set($property, $value) 
    { 
    $this->$property = $value; 
    } 
} 

料理\コントローラ\ AdminController.php

public function editDishAction() 
{ 
    //Params from url 
    $id = (int) $this->params()->fromRoute('id', 0); 

    $objectManager = $this->objectManager; 

    $hydrator = new DoctrineObject($objectManager, false); 
    $form = new DishForm(); 

    $existingDish = $objectManager->find('Dishes\Entity\Dish', $id); 

    if ($existingDish === NULL) 
    $this->notFoundAction(); 

    $request = $this->getRequest(); 

    if ($request->isPost()) 
    { 
    $filter = new DishFilter(); 
    $filter->get('photo')->setRequired(false); 

    $form->setHydrator($hydrator) 
     ->setObject($existingDish) 
     ->setInputFilter($filter); 

    $post = array_merge_recursive(
     $request->getPost()->toArray(), 
     $request->getFiles()->toArray() 
    ); 

    //Backup photo stream 
    $imageData = $existingDish->photo; 

    $form->setData($post); 
    if ($form->isValid()) 
    { 
     //If user upload a new image read it. 
     if(!empty($existingDish->photo['tmp_name'])) 
     $imageData = file_get_contents($existingDish->photo['tmp_name']); 

     $existingDish->photo = $imageData; 

     $objectManager->flush(); 

     $this->redirect()->toRoute('zfcadmin/dishes'); 
    } 
    } 
    else 
    { 
    $data = $hydrator->extract($existingDish); 
    unset($data['photo']); 
    $form->setData($data); 
    } 

    return new ViewModel(array('form' => $form)); 
} 

は、実際に私はNULL$dish->photoプロパティを設定するが、これは違反しますDB NOT NULLという制約があります。

実行時に特定のエンティティフィールドを更新から除外するようにDoctrineに指示するにはどうすればよいですか?

答えて

0

あなたの注釈内の任意のnullableフラグを設定していないので、Doctrineはデフォルトでfalseに、データベースレベルのすべての列のnullableプロパティをマップ:

/** 
* @ORM\Column(type="blob") 
*/ 
protected $photo; 

このことは、「写真が必要とされ、あなたは挿入できませんまたは列の写真列をヌル値で更新します。 "

あなたは、データベース内null値を持つようにしたい場合は、以下のアノテーションを使用します。

/** 
* @ORM\Column(type="blob", nullable=true) 
*/ 
protected $photo; 

、それだセッターnullデフォルト引数値を忘れないでくださいで:については

public function setPhoto($photo = null) 
{ 
    $this->photo = $photo; 
} 

を質問;アクション内のすべての編集操作で新しいDishオブジェクトを設定しているようです:

$form->setHydrator($hydrator) 
    ->setObject(new Dish) 
    ->setInputFilter($filter); 

これは、新しいDishオブジェクトを作成するときは正しいです。編集するとき、あなたはすでに設定する必要がフォームにディッシュインスタンスを持続:

// I'm just writing to explain the flow. 
// Accessing the object repository in action level is not a good practice. 
// Use a DishService for example. 

$id   = 32; // Grab it from route or elsewhere 
$repo   = $entityManager->getRepository('Dishes\Entity\Dish'); 
$existingDish = $repo->findOne((int) $id); 

$form->setHydrator($hydrator) 
    ->setObject($existingDish) 
    ->setInputFilter($filter); 

私は、これは既存のディッシュの編集アクションであると仮定しています。

したがって、フォームを介して既に入力されたDishインスタンスを与えるため、ハイドレーターは次の呼び出しで変更フィールドと変更されないフィールドの両方を正しく処理します。

私もInputFilterManagerからDishFilterをフェッチする代わりの行動レベルで手動で作成することはお勧め:

// $filter = new DishFilter(); 
$filter = $serviceLocator->get('InputFilterManager')->get(DishFilter::class); 
// Exclude the photo on validation: 
$filter->setValidationGroup('name', 'description', 'time', 'complexity'); 

はそれがお役に立てば幸いです。

+0

ありがとうございました。 私のコードを実際の解決策に編集します。特に、写真の検証を無効にすることはありません。 Zend \ファイルが提供されていない場合は、空の配列に写真のプロパティを設定します。したがって、新しい画像がない場合は、doctrineによって提供されたストリームをバックアップして復元します。 – DocLM

関連する問題