Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/242.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php Zend3表单筛选器-ParamConverter无法生成有效表单_Php_Zend Framework_Zend Form_Zend Framework3 - Fatal编程技术网

Php Zend3表单筛选器-ParamConverter无法生成有效表单

Php Zend3表单筛选器-ParamConverter无法生成有效表单,php,zend-framework,zend-form,zend-framework3,Php,Zend Framework,Zend Form,Zend Framework3,我真的对我的表单过滤器感到困惑 我的测试项目包含两个模型 class Category extends AbstractEntity { use Nameable; // just property name and getter and setter /** * @var boolean * @ORM\Column(name="issue", type="boolean") */ private $issue; /**

我真的对我的表单过滤器感到困惑

我的测试项目包含两个模型

class Category extends AbstractEntity 
{
    use Nameable; // just property name and getter and setter

    /**
     * @var boolean
     * @ORM\Column(name="issue", type="boolean")
     */
    private $issue;

    /**
     * @var Collection|ArrayCollection|Entry[]
     *
     * @ORM\OneToMany(targetEntity="CashJournal\Model\Entry", mappedBy="category", fetch="EAGER", orphanRemoval=true, cascade={"persist", "remove"})
     */
    private $entries;
}
条目

class Entry extends AbstractEntity
{
    use Nameable;

    /**
     * @var null|float
     *
     * @ORM\Column(name="amount", type="decimal")
     */
    private $amount;

    /**
     * @var null|Category
     *
     * @ORM\ManyToOne(targetEntity="CashJournal\Model\Category", inversedBy="entries", fetch="EAGER")
     * @ORM\JoinColumn(name="category_id", referencedColumnName="id", nullable=false)
     */
    protected $category;

    /**
     * @var null|DateTime
     *
     * @ORM\Column(name="date_of_entry", type="datetime")
     */
    private $dateOfEntry;
}
如果有人需要抽象实体

abstract class AbstractEntity implements EntityInterface
{
    /**
     * @var int
     * @ORM\Id
     * @ORM\Column(name="id", type="integer")
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    protected $id;
}
每个类别都可以有许多条目。我正在使用
原则
来处理这种关系。这个很好用

我有一个基于此字段集的表单:

$this->add([
    'name' => 'id',
    'type' => Hidden::class
]);

$this->add([
    'name' => 'name',
    'type' => Text::class,
    'options' => [
        'label' => 'Name'
    ]
]);

$this->add([
    'name' => 'amount',
    'type' => Number::class,
    'options' => [
        'label' => 'Summe'
    ]
]);

$this->add([
    'name' => 'date_of_entry',
    'type' => Date::class,
    'options' => [
        'label' => 'Datum'
    ]
]);

$this->add([
    'name' => 'category',
    'type' => ObjectSelect::class,
    'options' => [
        'target_class' => Category::class,
    ]
]);
因此,我的表单会显示一个包含我的类别的下拉列表。是的,很好

要为我的条目实体加载类别,我使用过滤器

$this->add([
    'name' => 'category',
    'required' => true,
    'filters' => [
        [
            'name' => Callback::class,
            'options' => [
                'callback' => [$this, 'loadCategory']
            ]
        ]
    ]
]);
以及回调:

public function loadCategory(string $categoryId)
{
    return $this->mapper->find($categoryId);
}
映射器将精细加载类别。伟大的但该表格无效,因为:

无法将CashJournal\Model\Category类的对象转换为int

好的,我正在删除过滤器,但是现在它无法将属性设置为Entry实体,因为setter需要一个
类别
。表单错误显示:

输入不是有效的步骤

在Symfony中,我可以创建一个
ParamConverter
,它将
category\u id
转换为有效的
category
实体

问题 如何使用过滤器作为参数

更新 此外,当我将category_id转换为int时,我将从表单中获得错误

更新2 我将字段集更改为:

class EntryFieldSet extends Fieldset implements ObjectManagerAwareInterface
{
    use ObjectManagerTrait;

    /**
     * {@inheritDoc}
     */
    public function init()
    {
        $this->add([
            'name' => 'id',
            'type' => Hidden::class
        ]);

        $this->add([
            'name' => 'name',
            'type' => Text::class,
            'options' => [
                'label' => 'Name'
            ]
        ]);

        $this->add([
            'name' => 'amount',
            'type' => Number::class,
            'options' => [
                'label' => 'Summe'
            ]
        ]);

        $this->add([
            'name' => 'date_of_entry',
            'type' => Date::class,
            'options' => [
                'label' => 'Datum'
            ]
        ]);

        $this->add([
            'name' => 'category',
            'required' => false,
            'type' => ObjectSelect::class,
            'options' => [
                'target_class' => Category::class,
                'object_manager' => $this->getObjectManager(),
                'property'       => 'id',
                'display_empty_item' => true,
                'empty_item_label'   => '---',
                'label_generator' => function ($targetEntity) {
                    return $targetEntity->getName();
                },
            ]
        ]);

        parent::init();
    }
} 
但此操作将退出,并显示错误消息:

Entry::setDateOfEntry()必须是DateTime的实例,字符串为


您是否查看了
ObjectSelect
的文档?您似乎缺少几个选项,即要使用哪个属性(EntityManager)和标识属性(id)

例如:

$this->add([
    'type'    => ObjectSelect::class,
    'name'    => 'category',                           // Name of property, 'category' in your question
    'options' => [
        'object_manager' => $this->getObjectManager(), // Make sure you provided the EntityManager to this Fieldset/Form
        'target_class'   => Category::class,           // Entity to target
        'property'       => 'id',                      // Identifying property
    ],
]);
要验证所选元素,请添加InputFilter:

$this->add([
    'name'     => 'category',
    'required' => true,
]);
InputFilter不需要更多。一个类别已经存在,并且之前已经验证过。所以,您应该能够选择它

如果您有特殊要求,您只需要额外的过滤器/验证器,例如:“一个类别只能在条目中使用一次”,这样您就需要使用
NoObjectExists
验证器。但这里的情况似乎并非如此


根据评论和过去的问题进行更新

我认为你把你要做的事情复杂化了。似乎您只想在客户端加载表单之前填充表单。在收到(来自客户机的)帖子时,您希望将收到的数据放入表单中,验证并存储它。对吗

基于此,请为我的一个项目中的用户找到一个完整的控制器。希望对您有所帮助。提供它是因为更新正在偏离您原来的问题,这可能会帮助您解决问题

我已经删除了一些额外的检查和错误抛出,但在其他方面是完全正常的

(请注意,我使用的是我自己的抽象控制器,请确保将其替换为您自己的和/或重新创建并匹配要求)

我还在这段代码中添加了其他注释来帮助您

<?php

namespace User\Controller\User;

use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\ORM\ORMException;
use Exception;
use Keet\Mvc\Controller\AbstractDoctrineActionController;
use User\Entity\User;
use User\Form\UserForm;
use Zend\Http\Request;
use Zend\Http\Response;

class EditController extends AbstractDoctrineActionController
{
    /**
     * @var UserForm
     */
    protected $userEditForm; // Provide this

    public function __construct(ObjectManager $objectManager, UserForm $userEditForm)
    {
        parent::__construct($objectManager); // Require this in this class or your own abstract class

        $this->setUserEditForm($userEditForm);
    }

    /**
     * @return array|Response
     * @throws ORMException|Exception
     */
    public function editAction()
    {
        $id = $this->params()->fromRoute('id', null);
        // check if id set -> else error/redirect

        /** @var User $entity */
        $entity = $this->getObjectManager()->getRepository(User::class)->find($id);
        // check if entity -> else error/redirect


        /** @var UserForm $form */
        $form = $this->getUserEditForm();  // GET THE FORM
        $form->bind($entity);              // Bind the Entity (object) on the Form

        // Only go into the belof if() on POST, else return Form. Above the data is set on the Form, so good to go (pre-filled with existing data)

        /** @var Request $request */
        $request = $this->getRequest();
        if ($request->isPost()) {
            $form->setData($request->getPost());       // Set received POST data on Form

            if ($form->isValid()) {                    // Validates Form. This also updates the Entity (object) with the received POST data
                /** @var User $user */
                $user = $form->getObject();            // Gets updated Entity (User object)

                $this->getObjectManager()->persist($user); // Persist it

                try {
                    $this->getObjectManager()->flush();    // Store in DB
                } catch (Exception $e) {

                    throw new Exception('Could not save. Error was thrown, details: ', $e->getMessage());
                }

                return $this->redirectToRoute('users/view', ['id' => $user->getId()]);
            }
        }

        // Returns the Form with bound Entity (object). 
        // Print magically in view with `<?= $this->form($form) ?>` (prints whole Form!!!)

        return [
            'form' => $form,
        ];
    }

    /**
     * @return UserForm
     */
    public function getUserEditForm() : UserForm
    {
        return $this->userEditForm;
    }

    /**
     * @param UserForm $userEditForm
     *
     * @return EditController
     */
    public function setUserEditForm(UserForm $userEditForm) : EditController
    {
        $this->userEditForm = $userEditForm;

        return $this;
    }
}
`(打印整个表单!!!)
返回[
'form'=>$form,
];
}
/**
*@returnuserform
*/
公共函数getUserEditForm():UserForm
{
返回$this->userEditForm;
}
/**
*@param UserForm$userEditForm
*
*@return-EditController
*/
公共函数setUserEditForm(UserForm$userEditForm):EditController
{
$this->userEditForm=$userEditForm;
退还$this;
}
}

希望这对……有帮助。

hi@rkeet,谢谢你的大力帮助。是的,我阅读了文档,并以这种方式构建,但随后我得到消息
Entry::setDateOfEntry()必须是DateTime的实例,字符串给定
,因此我决定将参数转换为对象。我更新了我的问题,并添加了带有changesUpdate2的字段集,这与另一个问题有关。接收到的值应为实例
日期
,但您向其传递一个
字符串
。你说你在使用条令,为什么要手动执行所有这些操作?你可能没有在你的字段集上设置正确的值。因此,EntryFieldset应该具有DoctrineObject或set。然后,当您设置客户端的POST数据(
$form->setDate(getRequest()->getPost())
)时,会将id(
34
)匹配到正确的类别。很高兴我能提供帮助;-)记住,一旦你掌握了窍门,它通常会变成像这样的小事;-)如果您必须根据post数据等手动分配完整实体对象上的值,那么通常会忘记或稍微偏离;-)德国劳埃德船级社