2015-05-25 45 views
7

Symfony命令教條:生成:crud生成的控制器<表單及其視圖。但是,索引不包含「多對一」的其他表引用字段。Symfony crud生成的索引視圖,其中沒有引用字段

實體模型:

<?php 

namespace Acme\Bundle\AdminBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 

/** 
* Albums 
* 
* @ORM\Table(name="albums", indexes={@ORM\Index(name="IDX_F4E2474F3D8E604F", columns={"parent"})}) 
* @ORM\Entity 
*/ 
class Albums 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer", nullable=false) 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="SEQUENCE") 
    * @ORM\SequenceGenerator(sequenceName="albums_id_seq", allocationSize=1, initialValue=1) 
    */ 
    private $id; 

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

    /** 
    * @var integer 
    * 
    * @ORM\Column(name="sort", type="integer", nullable=false) 
    */ 
    private $sort; 

    /** 
    * @var \ParentAlbums 
    * 
    * @ORM\ManyToOne(targetEntity="ParentAlbums") 
    * @ORM\JoinColumns({ 
    * @ORM\JoinColumn(name="parent", referencedColumnName="id") 
    * }) 
    */ 
    private $parent; 



    /** 
    * Get id 
    * 
    * @return integer 
    */ 
    public function getId() 
    { 
     return $this->id; 
    } 

    /** 
    * Set name 
    * 
    * @param string $name 
    * @return Albums 
    */ 
    public function setName($name) 
    { 
     $this->name = $name; 

     return $this; 
    } 

    /** 
    * Get name 
    * 
    * @return string 
    */ 
    public function getName() 
    { 
     return $this->name; 
    } 

    /** 
    * Set sort 
    * 
    * @param integer $sort 
    * @return Albums 
    */ 
    public function setSort($sort) 
    { 
     $this->sort = $sort; 

     return $this; 
    } 

    /** 
    * Get sort 
    * 
    * @return integer 
    */ 
    public function getSort() 
    { 
     return $this->sort; 
    } 

    /** 
    * Set parent 
    * 
    * @param \Acme\Bundle\AdminBundle\Entity\ParentAlbums $parent 
    * @return Albums 
    */ 
    public function setParent(\Acme\Bundle\AdminBundle\Entity\ParentAlbums $parent = null) 
    { 
     $this->parent = $parent; 

     return $this; 
    } 

    /** 
    * Get parent 
    * 
    * @return \Acme\Bundle\AdminBundle\Entity\ParentAlbums 
    */ 
    public function getParent() 
    { 
     return $this->parent; 
    } 
} 

Index.html.twig - 表頭部分:

<thead> 
     <tr> 
      <th>Id</th> 
      <th>Name</th> 
      <th>Sort</th> 
      <th>{{ 'views.index.actions'|trans({}, 'JordiLlonchCrudGeneratorBundle') }}</th> 
     </tr> 
    </thead> 

enter image description here

+0

它必須包含3個字段:name,sort,parent。父字段未生成。 –

+0

symfony crud generateor命令:php app/console doctrine:generate:crud --entity = AdminBundle:相冊--route-prefix = admin/albums --with-write --format = annotation --no-interaction --overwrite –

回答

7

這是DoctrineCrudGenerator的正常行爲,由於發電機僅使用Doctrine\ORM\Mapping\ClassMetadataInfo::$fieldMappings陣列生成表,但ParentAlbum,多對一協會位於Doctrine\ORM\Mapping\ClassMetadataInfo::$associationMappings陣列中。所以它永遠不會被認爲是殘酷的一代。

爲了展示一個可能的解決方案,我用的symfony-演示應用程序的註釋實體:

<?php 

/* 
* This file is part of the Symfony package. 
* 
* (c) Fabien Potencier <[email protected]> 
* 
* For the full copyright and license information, please view the LICENSE 
* file that was distributed with this source code. 
*/ 

namespace AppBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use Symfony\Component\Validator\Constraints as Assert; 

/** 
* @ORM\Entity 
* 
* Defines the properties of the Comment entity to represent the blog comments. 
* See http://symfony.com/doc/current/book/doctrine.html#creating-an-entity-class 
* 
* Tip: if you have an existing database, you can generate these entity class automatically. 
* See http://symfony.com/doc/current/cookbook/doctrine/reverse_engineering.html 
* 
* @author Ryan Weaver <[email protected]> 
* @author Javier Eguiluz <[email protected]> 
*/ 
class Comment 
{ 
    /** 
    * @ORM\Id 
    * @ORM\GeneratedValue 
    * @ORM\Column(type="integer") 
    */ 
    private $id; 

    /** 
    * @ORM\ManyToOne(targetEntity="Post", inversedBy="comments") 
    * @ORM\JoinColumn(nullable=false) 
    */ 
    private $post; 

    /** 
    * @ORM\Column(type="text") 
    * @Assert\NotBlank(message="Please don't leave your comment blank!") 
    * @Assert\Length(
    *  min = "5", 
    *  minMessage = "Comment is too short ({{ limit }} characters minimum)", 
    *  max = "10000", 
    *  maxMessage = "Comment is too long ({{ limit }} characters maximum)" 
    *) 
    */ 
    private $content; 

    /** 
    * @ORM\Column(type="string") 
    * @Assert\Email() 
    */ 
    private $authorEmail; 

    /** 
    * @ORM\Column(type="datetime") 
    * @Assert\DateTime() 
    */ 
    private $publishedAt; 

    public function __construct() 
    { 
     $this->publishedAt = new \DateTime(); 
    } 

    /** 
    * @Assert\True(message = "The content of this comment is considered spam.") 
    */ 
    public function isLegitComment() 
    { 
     $containsInvalidCharacters = false !== strpos($this->content, '@'); 

     return !$containsInvalidCharacters; 
    } 

    public function getId() 
    { 
     return $this->id; 
    } 

    public function getContent() 
    { 
     return $this->content; 
    } 

    public function setContent($content) 
    { 
     $this->content = $content; 
    } 

    public function getAuthorEmail() 
    { 
     return $this->authorEmail; 
    } 

    public function setAuthorEmail($authorEmail) 
    { 
     $this->authorEmail = $authorEmail; 
    } 

    public function getPublishedAt() 
    { 
     return $this->publishedAt; 
    } 

    public function setPublishedAt($publishedAt) 
    { 
     $this->publishedAt = $publishedAt; 
    } 

    public function getPost() 
    { 
     return $this->post; 
    } 

    public function setPost(Post $post = null) 
    { 
     $this->post = $post; 
    } 
} 

有喜歡的ID,內容,AUTHOREMAIL和publishedAt和一個多對一關聯早報「正常」列實體。對於這個實體產生以下元數據:

Doctrine\ORM\Mapping\ClassMetadata {#437 
    +name: "AppBundle\Entity\Comment" 
    +namespace: "AppBundle\Entity" 
    +rootEntityName: "AppBundle\Entity\Comment" 
    +customGeneratorDefinition: null 
    +customRepositoryClassName: null 
    +isMappedSuperclass: false 
    +isEmbeddedClass: false 
    +parentClasses: [] 
    +subClasses: [] 
    +embeddedClasses: [] 
    +namedQueries: [] 
    +namedNativeQueries: [] 
    +sqlResultSetMappings: [] 
    +identifier: array:1 [ 
    0 => "id" 
    ] 
    +inheritanceType: 1 
    +generatorType: 4 
    +fieldMappings: array:4 [ 
    "id" => array:9 [ 
     "fieldName" => "id" 
     "type" => "integer" 
     "scale" => 0 
     "length" => null 
     "unique" => false 
     "nullable" => false 
     "precision" => 0 
     "id" => true 
     "columnName" => "id" 
    ] 
    "content" => array:8 [ 
     "fieldName" => "content" 
     "type" => "text" 
     "scale" => 0 
     "length" => null 
     "unique" => false 
     "nullable" => false 
     "precision" => 0 
     "columnName" => "content" 
    ] 
    "authorEmail" => array:8 [ 
     "fieldName" => "authorEmail" 
     "type" => "string" 
     "scale" => 0 
     "length" => null 
     "unique" => false 
     "nullable" => false 
     "precision" => 0 
     "columnName" => "authorEmail" 
    ] 
    "publishedAt" => array:8 [ 
     "fieldName" => "publishedAt" 
     "type" => "datetime" 
     "scale" => 0 
     "length" => null 
     "unique" => false 
     "nullable" => false 
     "precision" => 0 
     "columnName" => "publishedAt" 
    ] 
    ] 
    +fieldNames: array:4 [ 
    "id" => "id" 
    "content" => "content" 
    "authorEmail" => "authorEmail" 
    "publishedAt" => "publishedAt" 
    ] 
    +columnNames: array:4 [ 
    "id" => "id" 
    "content" => "content" 
    "authorEmail" => "authorEmail" 
    "publishedAt" => "publishedAt" 
    ] 
    +discriminatorValue: null 
    +discriminatorMap: [] 
    +discriminatorColumn: null 
    +table: array:1 [ 
    "name" => "Comment" 
    ] 
    +lifecycleCallbacks: [] 
    +entityListeners: [] 
    +associationMappings: array:1 [ 
    "post" => array:19 [ 
     "fieldName" => "post" 
     "joinColumns" => array:1 [ 
     0 => array:6 [ 
      "name" => "post_id" 
      "unique" => false 
      "nullable" => false 
      "onDelete" => null 
      "columnDefinition" => null 
      "referencedColumnName" => "id" 
     ] 
     ] 
     "cascade" => [] 
     "inversedBy" => "comments" 
     "targetEntity" => "AppBundle\Entity\Post" 
     "fetch" => 2 
     "type" => 2 
     "mappedBy" => null 
     "isOwningSide" => true 
     "sourceEntity" => "AppBundle\Entity\Comment" 
     "isCascadeRemove" => false 
     "isCascadePersist" => false 
     "isCascadeRefresh" => false 
     "isCascadeMerge" => false 
     "isCascadeDetach" => false 
     "sourceToTargetKeyColumns" => array:1 [ 
     "post_id" => "id" 
     ] 
     "joinColumnFieldNames" => array:1 [ 
     "post_id" => "post_id" 
     ] 
     "targetToSourceKeyColumns" => array:1 [ 
     "id" => "post_id" 
     ] 
     "orphanRemoval" => false 
    ] 
    ] 
    +isIdentifierComposite: false 
    +containsForeignIdentifier: false 
    +idGenerator: Doctrine\ORM\Id\IdentityGenerator {#439 
    -sequenceName: null 
    } 
    +sequenceGeneratorDefinition: null 
    +tableGeneratorDefinition: null 
    +changeTrackingPolicy: 1 
    +isVersioned: null 
    +versionField: null 
    +cache: null 
    +reflClass: null 
    +isReadOnly: false 
    #namingStrategy: Doctrine\ORM\Mapping\DefaultNamingStrategy {#407} 
    +reflFields: array:5 [ 
    "id" => null 
    "content" => null 
    "authorEmail" => null 
    "publishedAt" => null 
    "post" => null 
    ] 
    -instantiator: Doctrine\Instantiator\Instantiator {#438} 
} 

你可以看到,正常的域位於fieldMappings陣列中,而該協會所居住的associationMappings陣列英寸 運行的註釋實體渣滓發生器產生的表僅適用於「正常」列不交的關聯關係:

<thead> 
    <tr> 
     <th>Id</th> 
     <th>Content</th> 
     <th>Authoremail</th> 
     <th>Publishedat</th> 
     <th>Actions</th> 
    </tr> 
</thead> 

現在,要改變這種行爲,你只需要「合併」中的associationMappings陣列現場監視數組在crud世代。 你可以在Sensio\Bundle\GeneratorBundle\Generator\DoctrineCrudGenerator中做到這一點。對於生產,您必須覆蓋 Sensio\Bundle\GeneratorBundle\Generator\DoctrineCrudGeneratorSensio\Bundle\GeneratorBundle\Command\GenerateDoctrineCrudCommand 並在您自己的類中進行更改。但正如概念證明我會做快速,真正骯髒的黑客,一個直接添加 以下更改DoctrineCrudGenerator:

/** 
* Generates a CRUD controller. 
* 
* @author Fabien Potencier <[email protected]> 
*/ 
class DoctrineCrudGenerator extends Generator 
{ 

    // ... 

    /** 
    * Generates the index.html.twig template in the final bundle. 
    * 
    * @param string $dir The path to the folder that hosts templates in the bundle 
    */ 
    protected function generateIndexView($dir) 
    { 
     $this->renderFile(
      'crud/views/index.html.twig.twig', 
      $dir . '/index.html.twig', 
      array(
       'bundle' => $this->bundle->getName(), 
       'entity' => $this->entity, 
       'identifier' => $this->metadata->identifier[0], 

       // Use the function instead of the "raw" fieldMappings array 
       // 'fields' => $this->metadata->fieldMappings, 
       'fields' => $this->processFieldMappings(), 

       'actions' => $this->actions, 
       'record_actions' => $this->getRecordActions(), 
       'route_prefix' => $this->routePrefix, 
       'route_name_prefix' => $this->routeNamePrefix, 
      ) 
     ); 
    } 

    // ... 
    /** 
    * Add the associations to the array 
    * 
    * @return array 
    */ 
    protected function processFieldMappings() 
    { 

     /** @var \Doctrine\ORM\Mapping\ClassMetadata $metadata */ 
     $metadata = $this->metadata; 

     $fields = $metadata->fieldMappings; 
     $associationMappings = $metadata->associationMappings; 

     foreach ($associationMappings as $k => $a) { 
      // Add the field only if it is a ToOne association and if the targetEntity implements the __toString method 
      if ($a['type'] & ClassMetadataInfo::TO_ONE && method_exists($a['targetEntity'], '__toString')) { 
       $fields[$k] = array(
        "fieldName" => $a["fieldName"], 
        "type" => "text", 
        "scale" => 0, 
        "length" => null, 
        "unique" => false, 
        "nullable" => false, 
        "precision" => 0, 
        "columnName" => $k 
       ); 
      } 
     } 

     return $fields; 
    } 
} 

更改後,如果您添加了__toString向早報實體,發電機產生以下代碼:

<table class="records_list"> 
    <thead> 
     <tr> 
      <th>Id</th> 
      <th>Content</th> 
      <th>Authoremail</th> 
      <th>Publishedat</th> 
      <th>Post</th> 
      <th>Actions</th> 
     </tr> 
    </thead> 
    <tbody> 
    {% for entity in entities %} 
     <tr> 
      <td><a href="{{ path('comment_show', { 'id': entity.id }) }}">{{ entity.id }}</a></td> 
      <td>{{ entity.content }}</td> 
      <td>{{ entity.authorEmail }}</td> 
      <td>{% if entity.publishedAt %}{{ entity.publishedAt|date('Y-m-d H:i:s') }}{% endif %}</td> 
      <td>{{ entity.post }}</td> 
      <td> 
      <ul> 
       <li> 
        <a href="{{ path('comment_show', { 'id': entity.id }) }}">show</a> 
       </li> 
       <li> 
        <a href="{{ path('comment_edit', { 'id': entity.id }) }}">edit</a> 
       </li> 
      </ul> 
      </td> 
     </tr> 
    {% endfor %} 
    </tbody> 
</table> 

您可以看到,現在可以識別該後期關聯。如果你想開始寫你自己的發電機,你可以用它作爲入口點。但您必須調查,如何處理ToMany關聯以及如何處理 表單等中的關聯。

+0

其實,我用另一種方法'fields'=> array_merge($ this-> metadata-> fieldMappings,$ this-> metadata-> associationMappings)解決了這個問題, –

+0

當然可以。但是,如果您想將'array_merge'用於ToMany關聯,而無需自定義模板,則會遇到問題。我也不會聲稱我的方法是唯一的方法。它是由你決定 ;) – skroczek

-1

的CRUD命令可幫助您快速生成多個文件,但它並不是一切。 $ parent是指向另一個實體的指針。 crud方法無法知道你想從這個實體顯示什麼。試想一下,ParentAlbums有一個屬性'$ name'。您可以顯示通過改變index.html.twig一點很簡單:

<thead> 
    <tr> 
     <th>Id</th> 
     <th>Name</th> 
     <th>Parent</th> 
     <th>Sort</th> 
     <th>{{ 'views.index.actions'|trans({}, 'JordiLlonchCrudGeneratorBundle') }}</th> 
    </tr> 
</thead> 
    <tbody> 
    {% for entity in entities %} 
     <tr> 
      <td>{{ entity.id }}</td> 
      <td>{{ entity.name }}</td> 
      <td>{{ entity.parent.name }}</td> 
      <td>{{ entity.sort }}</td> 
      <td> 
      <ul> 
        // actions here 
      </ul> 
      </td> 
     </tr> 
    {% endfor %} 
    </tbody> 
+0

不需要編寫entity.parent.name,entity.parent足夠簡單。 –

相關問題