2016-02-28 2 views
2

У меня есть эта Alias сущность:Могу ли я использовать prePersist/preUpdate в контроллере Sonata Admin для сохранения более чем одного объекта?

use Gedmo\Timestampable\Traits\TimestampableEntity; 

class Alias 
{ 
    use IdentifierAutogeneratedTrait; 
    use TimestampableEntity; 
    use ActiveTrait; 

    /** 
    * @var string 
    * @ORM\Column(type="string", length=150) 
    */ 
    private $name; 

    /** 
    * Command associated to the alias. 
    * 
    * @var Command[] 
    * @ORM\ManyToMany(targetEntity="Command", mappedBy="aliases", cascade={"persist"}) 
    */ 
    private $commands; 

    ... 
} 

И у меня есть этот контроллер администратора:

class AliasAdmin extends Admin 
{ 
    protected function configureFormFields(FormMapper $formMapper) 
    { 
     $formMapper 
      ->add('name', null, array('required' => true)) 
      ->add('active', null, array('required' => false)); 
    } 

    ... 

    public function prePersist($alias) 
    { 
     // remove extra white spaces 
     $noWhiteSpaces = str_replace(' ', '', $alias->getName()); 
     // split into several names 
     $aliasArr = explode(',', $noWhiteSpaces); 
    } 

    public function preUpdate($alias) 
    { 
     ... 
    } 
} 

Когда я добавляю новый Alias на вид - то есть сама форма - я могу написать одно значение в поле ввода name, например: value1 или я могу написать несколько значений, разделенных запятой: value1, value2, value3, value4. Если у меня есть только одно значение в поле name, когда я отправляю форму, тогда проблем не будет, но если у меня есть более одной запятой, разделенной как второй пример, тогда я должен проверить их на методе prePersist/preUpdate, чтобы разделить их и создать один Alias за name, как я могу это сделать? Если вы посмотрите на метод prePersist, вы увидите, что я говорю о том, как создать новый псевдоним для имени в новом $aliasArr, любую помощь?

Обновление: Временная проверка Не обрабатывается, почему?

После того как вы попробовали решение от @ m-khalid-junaid, я заканчиваю ошибку ниже из-за ограничения NOT NULL, но я не знаю почему. Посмотрите на код:

class AliasAdminController extends Controller 
{ 
    /** 
    * {@inheritdoc} 
    */ 
    public function createAction(Request $request = null) 
    { 
     // the key used to lookup the template 
     $templateKey = 'edit'; 

     if (false === $this->admin->isGranted('CREATE')) { 
      throw new AccessDeniedException(); 
     } 

     $object = $this->admin->getNewInstance(); 
     $this->admin->setSubject($object); 

     /** @var $form \Symfony\Component\Form\Form */ 
     $form = $this->admin->getForm(); 
     $form->setData($object); 

     if ($this->getRestMethod() == 'POST') { 
      $form->submit($this->get('request')); 
      $isFormValid = $form->isValid(); 

      // persist if the form was valid and if in preview mode the preview was approved 
      if ($isFormValid && (!$this->isInPreviewMode() || $this->isPreviewApproved())) { 
       if (false === $this->admin->isGranted('CREATE', $object)) { 
        throw new AccessDeniedException(); 
       } 

       try { 
        $aliasArr = $this->toStrings($object->getName()); 

        if (count($aliasArr) > 1) { 
         $object->setName($aliasArr[0]); 
         $object = $this->admin->create($object); 
         unset($aliasArr[0]); 
         $entityManager = $this->getDoctrine()->getManager(); 

         foreach ($aliasArr as $alias) { 
          $newAlias = new Alias(); 
          $newAlias->setName($alias); 
          $entityManager->persist($newAlias); 
         } 

         $entityManager->flush(); 
        } else { 
         $object = $this->admin->create($object); 
        } 

        if ($this->isXmlHttpRequest()) { 
         return $this->renderJson(array(
          'result' => 'ok', 
          'objectId' => $this->admin->getNormalizedIdentifier($object), 
         )); 
        } 

        $this->addFlash(
         'sonata_flash_success', 
         $this->admin->trans(
          'flash_create_success', 
          array('%name%' => $this->escapeHtml($this->admin->toString($object))), 
          'SonataAdminBundle' 
         ) 
        ); 

        // redirect to edit mode 
        return $this->redirectTo($object); 
       } catch (ModelManagerException $e) { 
        $this->logModelManagerException($e); 
        $isFormValid = false; 
       } 
      } 

      // show an error message if the form failed validation 
      if (!$isFormValid) { 
       if (!$this->isXmlHttpRequest()) { 
        $this->addFlash(
         'sonata_flash_error', 
         $this->admin->trans(
          'flash_create_error', 
          array('%name%' => $this->escapeHtml($this->admin->toString($object))), 
          'SonataAdminBundle' 
         ) 
        ); 
       } 
      } elseif ($this->isPreviewRequested()) { 
       // pick the preview template if the form was valid and preview was requested 
       $templateKey = 'preview'; 
       $this->admin->getShow(); 
      } 
     } 

     $view = $form->createView(); 

     // set the theme for the current Admin Form 
     $this->get('twig')->getExtension('form')->renderer->setTheme($view, $this->admin->getFormTheme()); 

     return $this->render($this->admin->getTemplate($templateKey), array(
      'action' => 'create', 
      'form' => $view, 
      'object' => $object, 
     )); 
    } 

    /** 
    * {@inheritdoc} 
    */ 
    public function editAction($id = null) 
    { 
     // the key used to lookup the template 
     $templateKey = 'edit'; 

     $id = $this->get('request')->get($this->admin->getIdParameter()); 
     $object = $this->admin->getObject($id); 

     if (!$object) { 
      throw new NotFoundHttpException(sprintf('unable to find the object with id : %s', $id)); 
     } 

     if (false === $this->admin->isGranted('EDIT', $object)) { 
      throw new AccessDeniedException(); 
     } 

     $this->admin->setSubject($object); 

     /** @var $form \Symfony\Component\Form\Form */ 
     $form = $this->admin->getForm(); 
     $form->setData($object); 

     if ($this->getRestMethod() == 'POST') { 
      $form->submit($this->get('request')); 

      $isFormValid = $form->isValid(); 

      // persist if the form was valid and if in preview mode the preview was approved 
      if ($isFormValid && (!$this->isInPreviewMode() || $this->isPreviewApproved())) { 
       try { 
        $aliasArr = $this->toStrings($object->getName()); 

        if (count($aliasArr) > 1) { 
         $object->setName($aliasArr[0]); 
         $object = $this->admin->update($object); 
         unset($aliasArr[0]); 
         $entityManager = $this->getDoctrine()->getManager(); 

         foreach ($aliasArr as $alias) { 
          $newAlias = new Alias(); 
          $newAlias->setName($alias); 
          $entityManager->persist($newAlias); 
         } 

         $entityManager->flush(); 
        } else { 
         $object = $this->admin->update($object); 
        } 

        if ($this->isXmlHttpRequest()) { 
         return $this->renderJson(array(
          'result' => 'ok', 
          'objectId' => $this->admin->getNormalizedIdentifier($object), 
         )); 
        } 

        $this->addFlash(
         'sonata_flash_success', 
         $this->admin->trans(
          'flash_edit_success', 
          array('%name%' => $this->escapeHtml($this->admin->toString($object))), 
          'SonataAdminBundle' 
         ) 
        ); 

        // redirect to edit mode 
        return $this->redirectTo($object); 
       } catch (ModelManagerException $e) { 
        $this->logModelManagerException($e); 

        $isFormValid = false; 
       } 
      } 

      // show an error message if the form failed validation 
      if (!$isFormValid) { 
       if (!$this->isXmlHttpRequest()) { 
        $this->addFlash(
         'sonata_flash_error', 
         $this->admin->trans(
          'flash_edit_error', 
          array('%name%' => $this->escapeHtml($this->admin->toString($object))), 
          'SonataAdminBundle' 
         ) 
        ); 
       } 
      } elseif ($this->isPreviewRequested()) { 
       // enable the preview template if the form was valid and preview was requested 
       $templateKey = 'preview'; 
       $this->admin->getShow(); 
      } 
     } 

     $view = $form->createView(); 

     // set the theme for the current Admin Form 
     $this->get('twig')->getExtension('form')->renderer->setTheme($view, $this->admin->getFormTheme()); 

     return $this->render($this->admin->getTemplate($templateKey), array(
      'action' => 'edit', 
      'form' => $view, 
      'object' => $object, 
     )); 
    } 

    private function logModelManagerException($e) 
    { 
     $context = array('exception' => $e); 
     if ($e->getPrevious()) { 
      $context['previous_exception_message'] = $e->getPrevious()->getMessage(); 
     } 
     $this->getLogger()->error($e->getMessage(), $context); 
    } 

    private function toStrings($string) 
    { 
     $noWhiteSpaces = str_replace(' ', '', $string); 
     return explode(',', $noWhiteSpaces); 
    } 
} 

И это ошибка:

[2016-02-28 11:10:36] doctrine.DEBUG: "START TRANSACTION" [] [] 
[2016-02-28 11:10:36] doctrine.DEBUG: INSERT INTO cm_alias (name, created_at, updated_at, active) VALUES (?, ?, ?, ?) {"1":"alias1","2":null,"3":null,"4":true} [] 
[2016-02-28 11:10:36] doctrine.DEBUG: "ROLLBACK" [] [] 
[2016-02-28 11:10:36] app.ERROR: Failed to create object: PlatformAdminBundle\Entity\Alias {"exception":"[object] (Sonata\\AdminBundle\\Exception\\ModelManagerException(code: 0): Failed to create object: PlatformAdminBundle\\Entity\\Alias at /var/www/html/platform.sonata/vendor/sonata-project/doctrine-orm-admin-bundle/Model/ModelManager.php:142, Doctrine\\DBAL\\Exception\\NotNullConstraintViolationException(code: 0): An exception occurred while executing 'INSERT INTO cm_alias (name, created_at, updated_at, active) VALUES (?, ?, ?, ?)' with params [\"alias1\", null, null, 1]:\n\nSQLSTATE[23000]: Integrity constraint violation: 1048 Column 'created_at' cannot be null at /var/www/html/platform.sonata/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php:112, Doctrine\\DBAL\\Driver\\PDOException(code: 23000): SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'created_at' cannot be null at /var/www/html/platform.sonata/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php:93, PDOException(code: 23000): SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'created_at' cannot be null at /var/www/html/platform.sonata/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php:91)","previous_exception_message":"An exception occurred while executing 'INSERT INTO cm_alias (name, created_at, updated_at, active) VALUES (?, ?, ?, ?)' with params [\"alias1\", null, null, 1]:\n\nSQLSTATE[23000]: Integrity constraint violation: 1048 Column 'created_at' cannot be null"} [] 

Почему TimestampableEntity черта не обрабатывается новым контроллером администратора? Что мне здесь не хватает?

ответ

1

Если вы хотите добавить тот же объект с различными псевдонимами лучше, чтобы создать CRUDController контроллер для вашего класса администратора, Если у вас есть CRUDController вы можете переопределить createAction & editAction из базовый класс и реализовать свою логику здесь prePresist/preUpdate события для вашего текущего объекта, с которыми можно играть, чтобы создавать копии для вашего объекта с различной информацией, используя контроллер. Я упомянул только необходимый код ниже вы можете скопировать из CRUDController сонаты и реализовать ту же логику в editAction

public function createAction(Request $request = null) 
{ 
    // .. some code here copy from base class 
    try { 
     $noWhiteSpaces = str_replace(' ', '', $object->getName()); 
     // split into several names 
     $aliases = explode(',', $noWhiteSpaces); 
     if (count($aliases) > 1) { 
      $object->setName($aliases[0]); 
      $object = $this->admin->create($object); 
      unset($aliases[0]); 
      $DM = $this->getDoctrine()->getManager(); 
      foreach ($aliases as $alias) { 
       $newAlias = new Alias(); 
       $newAlias->setName($alias); 
       $DM->persist($newAlias); 
      } 
      $DM->flush(); 
     } else { 
      $object = $this->admin->create($object); 
     } 
    } catch (ModelManagerException $e) { 
     $this->handleModelManagerException($e); 

     $isFormValid = false; 
    } 
    // .. some code here copy from base class 
} 

Edit для created_at не нулевой ошибки

Вы должны определить функцию конструктора в ваш псевдоним лица и там инициализировать createdAt свойство с DateTime объекта

/** 
* Constructor 
*/ 
public function __construct() 
{ 
    $this->createdAt = new \DateTime('now'); 
} 
+0

Можете ли вы взглянуть на редактирование (обновление), которое я сделал для OP?Спасибо – ReynierPM

+0

@ReynierPM обновил мой ответ –

+0

Не работает такая же ошибка из-за NULL 'createdAt' – ReynierPM

0

Может быть что-то вроде этого:

public function prePersist($alias) 
{ 
    // remove extra white spaces 
    $noWhiteSpaces = str_replace(' ', '', $alias->getName()); 
    // split into several names 
    $aliasArr = explode(',', $noWhiteSpaces); 

    $currentAliasName = $aliasArr[0]; // Use the first name for the Alias created by your admin class. 
    $alias->setName($currentAliasName); 
    unset($aliasArr[0]); 

    $em = $this->getConfigurationPool()->getContainer()->getDoctrine()->getManager(); 

    foreach ($aliasArr as $aliasName) { 
     $newAlias = new Alias(); 
     $newAlias->setName($aliasName); 
     $newAlias->setActive(?); 

     $em->persist($newAlias); 
     $em->flush($newAlias); 
    } 
} 
+0

И мы должны сохраняться на 'методы prePersist/preUpdate'? Разве это не предназначено для внесения изменений в объекты, прежде чем они сохраняются, но не сохраняются, или я ошибаюсь? – ReynierPM

+0

Методы prePersist/preUpdate вызываются для внесения изменений только для текущего созданного/обновленного объекта. Но мы также можем использовать его для создания/обновления боковых объектов, таких как обработка загрузки файлов. Владельцу нужен пользовательский трюк для создания объектов в данный момент, поэтому он может отлично. Это немного грязно, потому что объекты имеют тот же тип тока, но это то, о чем он просит. – chalasr