0

我确实使用了 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 %}

感谢您的任何回答!

4

1 回答 1

1

你应该要么

  • 对(首选解决方案)施加@Assert\Valid约束ToolCategory::$documents,或
  • 设置为父窗体(即cascade_validation),而不是子true窗体ToolCategoryType
于 2012-05-29T18:56:47.303 回答