我确实使用了 symfony2.1,并且我有一种形式,我确实通过另一种形式进行了扩展,主要部分(来自第一个实体 [ ToolCategory
])确实有效,但附加的部分没有(ToolDocument
)。这是代码:
工具类别
namespace Einder\Has\ToolsBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Einder\DoctrineBundle\Entity\ActiveInterface;
/**
* Einder\Has\ToolsBundle\Entity\ToolCategory
*
* @ORM\Table(name="tool_category")
* @ORM\Entity(repositoryClass="Einder\Has\ToolsBundle\Repository\ToolCategoryRepository")
* @ORM\HasLifecycleCallbacks
*/
class ToolCategory implements ActiveInterface
{
/**
* @var integer $id
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string $name
*
* @ORM\Column(name="name", type="string", length=255)
* @Assert\NotBlank()
*/
private $name;
/**
* @var text $target
*
* @ORM\Column(name="target", type="text")
* @Assert\NotBlank()
*/
private $target;
/**
* @var text $activity
*
* @ORM\Column(name="activity", type="text")
* @Assert\NotBlank()
*/
private $activity;
/**
* @var boolean $active
*
* @ORM\Column(name="active", type="boolean", nullable=true)
*/
private $active = true;
/**
* @ORM\OneToMany(targetEntity="ToolDocument", mappedBy="toolCategory", cascade={"persist", "remove"})
*/
private $documents;
/**
* @var boolean $createAnother
*
* @Assert\Type(type="boolean")
*/
private $createAnother = false;
/**
* @var datetime $createdAt
*
* @ORM\Column(name="created_at", type="datetime")
*/
private $createdAt;
/**
* @var datetime $updatedAt
*
* @ORM\Column(name="updated_at", type="datetime")
*/
private $updatedAt;
/**
* Constructor
*/
public function __construct()
{
$this->documents = new ArrayCollection();
}
/**
* __toString
*/
public function __toString()
{
return $this->name;
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set target
*
* @param text $target
*/
public function setTarget($target)
{
$this->target = $target;
}
/**
* Get target
*
* @return text
*/
public function getTarget()
{
return $this->target;
}
/**
* Set activity
*
* @param text $activity
*/
public function setActivity($activity)
{
$this->activity = $activity;
}
/**
* Get activity
*
* @return text
*/
public function getActivity()
{
return $this->activity;
}
/**
* Set active
*
* @param boolean $active
*/
public function setActive($active = true)
{
$this->active = $active;
}
/**
* Get active
*
* @return boolean
*/
public function getActive()
{
return $this->active;
}
/**
* Add documents
*
* @param Einder\Has\ToolsBundle\Entity\ToolDocument $documents
*/
public function addToolDocument(\Einder\Has\ToolsBundle\Entity\ToolDocument $documents)
{
$this->documents[] = $documents;
}
/**
* Get documents
*
* @return Doctrine\Common\Collections\Collection
*/
public function getDocuments()
{
return $this->documents;
}
/**
* Set createAnother
*
* @param boolean $createAnother
*/
public function setCreateAnother($createAnother)
{
$this->createAnother = $createAnother;
}
/**
* Get createAnother
*
* @return boolean
*/
public function getCreateAnother()
{
return $this->createAnother;
}
/**
* Set createdAt
*
* @ORM\PrePersist
*/
public function setCreatedAt()
{
$this->createdAt = new \DateTime();
}
/**
* Get createdAt
*
* @return datetime
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* Set updatedAt
*
* @ORM\PrePersist
* @ORM\PreUpdate
*/
public function setUpdatedAt()
{
$this->updatedAt = new \DateTime();
}
/**
* Get updatedAt
*
* @return datetime
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}
public function setDocuments($documents) {
$this->documents = $documents;
foreach ($documents as $document) {
$document->setToolCategory($this);
}
}
}
工具文档
namespace Einder\Has\ToolsBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Einder\DoctrineBundle\Entity\EntityInterface;
/**
* Einder\Has\ToolsBundle\Entity\ToolDocument
*
* @ORM\Table(name="tool_document")
* @ORM\Entity(repositoryClass="Einder\Has\ToolsBundle\Repository\ToolDocumentRepository")
* @ORM\HasLifecycleCallbacks
*/
class ToolDocument implements EntityInterface
{
/**
* @var integer $id
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @Assert\File(maxSize="6000000")
*/
public $file;
/**
* @ORM\Column(type="string", length=255)
* @Assert\NotBlank()
* @Assert\NotNull()
* @Assert\MinLength(10)
*/
private $name;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $path;
/**
* @var boolean $active
*
* @ORM\Column(name="active", type="boolean", nullable=true)
*/
private $active = true;
/**
* @var boolean $deleted
*
* @ORM\Column(name="deleted", type="boolean", nullable=true)
*/
private $deleted = false;
/**
* @var datetime $deletedAt
*
* @ORM\Column(name="deleted_at", type="boolean", nullable=true)
*/
private $deletedAt;
/**
* @ORM\ManyToOne(targetEntity="ToolCategory", inversedBy="documents")
* @ORM\JoinColumn(name="tool_category_id", referencedColumnName="id")
*/
private $toolCategory;
/**
* @var datetime $createdAt
*
* @ORM\Column(name="created_at", type="datetime")
*/
private $createdAt;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
public function __toString()
{
return $this->name;
}
public function getAbsolutePath()
{
return null === $this->path ? null : $this->getUploadRootDir().'/'.$this->path;
}
public function getWebPath()
{
return null === $this->path ? null : $this->getUploadDir().'/'.$this->path;
}
protected function getUploadRootDir()
{
// the absolute directory path where uploaded documents should be saved
return __DIR__.'/../../../../../web/'.$this->getUploadDir();
}
protected function getUploadDir()
{
// get rid of the __DIR__ so it doesn't screw when displaying uploaded doc/image in the view.
return '/uploads/tools';
}
/**
* @ORM\PrePersist()
* @ORM\PreUpdate()
*/
public function preUpload()
{
if (null !== $this->file) {
// do whatever you want to generate a unique name
$this->setPath(uniqid() . '.' . pathinfo($this->file->getClientOriginalName(), PATHINFO_EXTENSION));
}
}
/**
* @ORM\PostPersist()
* @ORM\PostUpdate()
*/
public function upload()
{
if (null === $this->file) {
return;
}
// you must throw an exception here if the file cannot be moved
// so that the entity is not persisted to the database
// which the UploadedFile move() method does automatically
$this->file->move($this->getUploadRootDir(), $this->path);
unset($this->file);
}
/**
* @ORM\PostRemove()
*/
public function removeUpload()
{
if ($file = $this->getAbsolutePath()) {
unlink($file);
}
}
/**
* Set name
*
* @param string $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set path
*
* @param string $path
*/
public function setPath($path)
{
$this->path = $path;
}
/**
* Get path
*
* @return string
*/
public function getPath()
{
return $this->path;
}
/**
* Set active
*
* @param boolean $active
*/
public function setActive($active = true)
{
$this->active = $active;
}
/**
* Get active
*
* @return boolean
*/
public function getActive()
{
return $this->active;
}
/**
* Set deleted
*
* @param boolean $deleted
*/
public function setDeleted($deleted = false)
{
$this->deleted = $deleted;
}
/**
* Get deleted
*
* @return boolean
*/
public function getDeleted()
{
return $this->deleted;
}
/**
* Get deletedAt
*
* @return datetime
*/
public function getDeletedAt()
{
return $this->deletedAt;
}
/**
* Set deletedAt
*
* @param boolean $deletedAt
*/
public function setDeletedAt(\DateTime $deletedAt = null)
{
$this->deletedAt = $deletedAt;
}
/**
* Set toolCategory
*
* @param Einder\Has\ToolsBundle\Entity\ToolCategory $toolCategory
*/
public function setToolCategory($toolCategory)
{
$this->toolCategory = $toolCategory;
}
/**
* Get toolCategory
*
* @return Einder\Has\ToolsBundle\Entity\ToolCategory
*/
public function getToolCategory()
{
return $this->toolCategory;
}
/**
* Set createdAt
*
* @ORM\PrePersist
*/
public function setCreatedAt()
{
$this->createdAt = new \DateTime();
}
/**
* Get createdAt
*
* @return datetime
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* Set updatedAt
*
* @ORM\PrePersist
* @ORM\PreUpdate
*/
public function setUpdatedAt()
{
$this->updatedAt = new \DateTime();
}
/**
* Get updatedAt
*
* @return datetime
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}
}
工具类别类型
namespace Einder\Has\ToolsBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Einder\Has\ToolsBundle\Form\Type\ToolDocumentType;
class ToolCategoryType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('name', null, array('label' => 'tool.category.form.labels.name'))
->add('target', null, array('label' => 'tool.category.form.labels.target'))
->add('activity', null, array('label' => 'tool.category.form.labels.activity'))
->add('createAnother', null, array('label' => 'tool.category.form.labels.create_another'))
->add('documents', 'collection', array(
'by_reference' => false,
'type' => new ToolDocumentType(),
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
'error_bubbling' => true
));
}
public function getDefaultOptions()
{
return array(
'data_class' => 'Einder\Has\ToolsBundle\Entity\ToolCategory'
);
}
public function getName()
{
return 'tool_category';
}
}
工具文档类型
namespace Einder\Has\ToolsBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
class ToolDocumentType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('name', null, array('label' => 'tool.document.form.labels.name'))
->add('file', null, array('label' => 'tool.document.form.labels.file'));
}
public function getDefaultOptions()
{
return array(
'data_class' => 'Einder\Has\ToolsBundle\Entity\ToolDocument',
'cascade_validation' => true,
);
}
public function getName()
{
return 'tool_document';
}
}
{{ form_errors(form) }} <form method="post" {{ form_enctype(form) }} novalidate> <table class="table table-striped"> <tbody> <tr> <td>{{ form_label(form.name) }}</td> <td>{{ form_widget(form.name) }} {{ form_errors(form.name) }}</td> </tr> <tr> <td>{{ form_label(form.target) }}</td> <td>{{ form_widget(form.target) }} {{ form_errors(form.target) }}</td> </tr> <tr> <td>{{ form_label(form.activity) }}</td> <td>{{ form_widget(form.activity) }} {{ form_errors(form.activity) }}</td> </tr> <tr id="tool_category_documents" data-prototype="{{ _self.widget_prototype(form.documents, 'Remove tag')|escape }}"> <td>{{ form_label(form.documents) }}</td> <td id="widget-collection-holder"> {% for row in form.documents %} {{ _self.widget_prototype(row) }} {% endfor %} </td> </tr> <tr> <td><a class="jslink_add">{{ 'Add'|trans }}</a></td> <td></td> </tr> </tbody> <tfoot> <tr> <td>{{ form_label(form.createAnother) }} {{ form_widget(form.createAnother) }} {{ form_errors(form.createAnother) }}</td> <td> <input type="submit" value="{{ 'admin.tools.categories.category.form.save'|trans }}" class="btn btn-success" /> <a href="{{ path('admin_tools_index')}}" class="btn btn-danger">{{ 'global.action.cancel'}}</a> </td> </tr> <tr> <td>{{ form_rest(form) }}</td> <td></td> </tr> </tfoot> </table> </form> {% block javascripts %} <script type="text/javascript"> function add() { var collectionHolder = $('#tool_category_documents'); var prototype = collectionHolder.attr('data-prototype'); console.log(collectionHolder); form = prototype.replace(/__name__/g, $('#widget-collection-holder').children().length); console.log($(form)); collectionHolder.find('#widget-collection-holder').append(form); } function remove(object) { $(object).parent().remove(); } $('a.jslink_add').live('click', function(event){ event.preventDefault(); add(); }); $('a.jslink_remove').live('click', function(event){ event.preventDefault(); remove(this); }); </script> {% endblock %} {% macro widget_prototype(widget) %} {% if widget.get('prototype') %} {% set form = widget.get('prototype') %} {% set name = widget.get('prototype').get('name') %} {% else %} {% set form = widget %} {% set name = widget.get('full_name') %} {% endif %} <div class="widget-holder">{{ form_errors(form) }} {{ form_widget(form.name) }} {{ form_widget(form.file)}} <a href="#" class="jslink_remove">{{ 'Remove'|trans }}</a></div> {% endmacro %}
感谢您的任何回答!