2013-10-14 2 views
1

В настоящее время я работаю над проектом с Zend Framework 2 и Doctrine.zend framework 2 стратегия гидратации доктрины - метод гидратов никогда не назывался

Я реализую Zend \ Form и используя DoctrineORMModule \ Stdlib \ Hydrator \ DoctrineEntity для извлечения и гидратации данных из/в базу данных.

Во многих учебных пособиях, которые я прочитал, идеально подходит для реализации Zend \ Stdlib \ Hydrator \ Strategy \ StrategyInterface, когда вам нужно преобразовать определенное значение перед увлажнением объекта (в моем примере строка значения времени даты, которая является проблемой при использовании Доктрины). Однако, несмотря на все мои усилия по его реализации, кажется, что метод extract() в моей стратегии гидратации называется никогда, а не методом hydrate(). КОГДА-ЛИБО!

Чтобы предоставить пример кода, это то, что я делаю - я сократил некоторые аспекты кода для краткости;

// Service 

public function getProposerForm() { 

    // get required classes from service manager 

    $proposerEntity = $this->getServiceManager()->get('tourers_entity_proposer'); 

    $entityManager = $this->getServiceManager()->get('Doctrine\ORM\EntityManager'); 

    $formManager = $this->getServiceManager()->get('FormElementManager'); 
    $proposerFieldset = $formManager->get('tourers_form_proposer_fieldset'); 
    $proposerForm = $formManager->get('tourers_form_proposal'); 


    $proposerFieldset->setUseAsBaseFieldset(true); 
    $proposerForm->add($proposerFieldset); 

    $proposerForm->get('submit')->setValue('Continue'); 
    $proposerForm->bind($proposerEntity); 

    return $proposerForm; 
} 

.

// Controller 

public function proposerAction() {  

    // grab the form from the form service 

    $formService = $this->getServiceLocator()->get('tourers_service_forms'); 

    $form = $formService->getProposerForm(); 

    if (true === $this->getRequest()->isPost()) { 

     $form->setData($this->getRequest()->getPost()); 

     if (true === $form->isValid()) { 

      $proposerEntity = $form->getData(); 

      $encryptedPolicyId = $formService->saveProposerForm($proposerEntity, $policyId); 

      return $this->redirect()->toRoute('tourers/proposal/caravan',array('policyid' => $encryptedPolicyId)); 


     } else { 
      $errors = $form->getMessages(); 
      var_dump($errors); 
     } 
    } 

    // view 

    return new ViewModel(array(
     'form'  => $form 
     ,'policyid' => $policyId 
     ) 
    ); 

} 

.

// Form 

class ProposerFieldset extends Fieldset implements InputFilterProviderInterface, ObjectManagerAwareInterface 
{ 

/** 
* @var Doctrine\ORM\EntityManager 
*/ 
private $objectManager; 

/** 
* @return Zend\Form\Fieldset 
*/ 

public function init() 
{ 
    // set name 

    parent::__construct('Proposer'); 

    // set the hydrator to the domain object 

    $hydrator = new DoctrineEntity($this->objectManager,true); 
    $hydrator->addStrategy('proposerDateOfBirth',new DateStrategy); 

    $this->setHydrator($hydrator); 

    // other form elements below here including proposerDateOfBirth 

    $minDate = date('dd\/mm\/yyyy',strtotime('-100 years')); 
    $maxDate = date('dd\/mm\/yyyy',strtotime('-16 years')); 

    $this->add(array(
     'name' => 'proposerDateOfBirth' 
     ,'type' => 'Zend\Form\Element\Date' 
     ,'attributes' => array(
      'class' => 'form-control' 
      ,'id' => 'proposerDateOfBirth' 
      ,'placeholder' => 'dd/mm/yyyy' 
      ,'min' => $minDate 
      ,'max' => $maxDate 
      ,'data-date-format' => 'dd/mm/yyyy' 

     ), 
     'options' => array(
      'label' => 'Date of Birth', 
     ) 
    )); 
} 
} 

.

// Hydrator Strategy 

namespace Tourers\Hydrator\Strategy; 

use Zend\Stdlib\Hydrator\Strategy\StrategyInterface; 

class DateStrategy implements StrategyInterface { 

/** 
* (non-PHPdoc) 
* @see Zend\Stdlib\Hydrator\Strategy.StrategyInterface::extract() 
*/ 
public function extract($value) { 
    var_dump($value . ' extracted'); // GETS CALLED 
    return $value; 

} 

/** 
* (non-PHPdoc) 
* @see Zend\Stdlib\Hydrator\Strategy.StrategyInterface::hydrate() 
*/ 
public function hydrate($value) { 
    var_dump($value . ' hydrated'); // NEVER CALLED 
    return $value; 
} 
} 

ответ

2

Я также обнаружил это поведение. До сих пор я все еще теряю, почему моя пользовательская стратегия не вызывалась.

В Стратегии применяются внутри hydrateValue() и EXTRACTVALUE() функций, поэтому его необходимой для этих функций можно назвать по гидрата() и экстракта() функции для того, чтобы стратегии или пользовательских стратегий.

Моя проблема была очевидна в hydrateByReference() функция внутри DoctrineModule \ Stdlib \ Hydrator \ DoctrineObject.

Кажется, что $ this-> hydrateValue (...) только называется полем имеет "ассоциации". Я еще не знаю, что такое «ассоциации», или что я делаю неправильно, чтобы они не существовали в моих данных.

Когда я сравнил его с extractByReference() функции, я заметил, что он всегда называет $ this-> EXTRACTVALUE() и не требует каких-либо "ассоциации".

В моем приложении я уже внедрил пользовательский класс Hydrator. Это означает, что когда я создаю форму, Гидратор и Стратегии автоматически применяются.

  • Внутри Init() функции моей формы, я назначить пользовательские увлажняющее.
  • Внутри моего пользовательского гидратора __construct(), я добавляю стратегии и пользовательские стратегии.


Так все, что мне нужно было сделать, чтобы переопределить hydrateByReference (...) в моей пользовательской увлажняющее, чтобы решить эту проблему. Пример приведен ниже.

ПРИМЕЧАНИЯ:

  1. Вы можете также необходимо переопределить hydrateByValue (...) если вы используете "по значению" гидратации.
  2. Мое решение может нарушить функциональность «ассоциаций».


Мой заказ Hydrator класс:

class maintenance 
     extends DoctrineHydrator 
{ 


    /** 
    * Constructor 
    * 
    * @param ObjectManager $objectManager The ObjectManager to use 
    */ 
    public function __construct($objectManager) 
    { 
     /* 
     * Just call the parent class. 
     */ 
     parent::__construct($objectManager, 
       'Maintenance\Entity\maintenance', // The FQCN of the hydrated/extracted object 
       false        // If set to true, hydrator will always use entity's public API 
      ); 


     /* 
     * Now set up our strategies, and attach them 
     * to the appropriate fields. 
     */ 
     $this->addStrategy('purchasedate', new TIGDateStrategy()); 
     $this->addStrategy('maintexpirydate', new TIGDateStrategy()); 

    } 

    /** 
    * SF Modification, to ensure we call this->hydrateValue on 
    * all values before doing anything else with the data. 
    * This way, we convert the data first, before trying to 
    * store it in a DoctrineEntity. 
    * 
    * Hydrate the object using a by-reference logic (this means that values are modified directly without 
    * using the public API, in this case setters, and hence override any logic that could be done in those 
    * setters) 
    * 
    * @param array $data 
    * @param object $object 
    * @return object 
    */ 
    protected function hydrateByReference(array $data, $object) 
    { 
     $object = $this->tryConvertArrayToObject($data, $object); 
     $metadata = $this->metadata; 
     $refl  = $metadata->getReflectionClass(); 

     foreach ($data as $field => $value) { 
      // Ignore unknown fields 
      if (!$refl->hasProperty($field)) { 
       continue; 
      } 

      // SF Mod 
      $value = $this->hydrateValue($field, $value); 
      // End SF Mod 

      $value  = $this->handleTypeConversions($value, $metadata->getTypeOfField($field)); 
      $reflProperty = $refl->getProperty($field); 
      $reflProperty->setAccessible(true); 

      if ($metadata->hasAssociation($field)) { 
       $target = $metadata->getAssociationTargetClass($field); 

       if ($metadata->isSingleValuedAssociation($field)) { 
        $value = $this->toOne($target, $this->hydrateValue($field, $value)); 
        $reflProperty->setValue($object, $value); 
       } elseif ($metadata->isCollectionValuedAssociation($field)) { 
        $this->toMany($object, $field, $target, $value); 
       } 
      } else { 
       $reflProperty->setValue($object, $value); 
      } 
     } 

     return $object; 
    } 

} 
+0

Спасибо Tigs, что точный ответ я искал! –

Смежные вопросы