如何根据ACL过滤表单中的实体

时间:2014-01-09 15:30:02

标签: symfony sonata-admin

这是我想要完成的事情:

我有一个简单的应用程序来管理产品和类别实体。这些的CRUD由SonataAdmin管理。

我的Product实体与Category实体(多对一关联)相关联。我想要的是,当Sonata的CRUD显示创建产品的表单时,在类别选择中,它仅列出用户拥有EDIT访问控制条目的类别。

以下是一些代码来说明这一点:

Product实体

<?php

namespace Acme\DemoBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Product
 *
 * @ORM\Table()
 * @ORM\Entity
 * @ORM\HasLifecycleCallbacks()
 */
class Product
{

    /**
     * @var integer id
     *
     * @ORM\Id
     * @ORM\Column(name="id", type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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

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

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

    /**
     * @ORM\ManyToOne(targetEntity="Category", inversedBy="products")
     * @ORM\JoinColumn(name="category_id", referencedColumnName="id")
     */
    protected $category;

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

    /*Getters and setters
    ...
    */
}

Category实体

<?php

namespace Acme\DemoBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * Category
 *
 * @ORM\Table()
 * @ORM\Entity
 */
class Category
{
    /**
     * @var integer
     *
     * @ORM\Id
     * @ORM\Column(name="id", type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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

    /**
     * @ORM\OneToMany(targetEntity="Product", mappedBy="category")
     */
    protected $products;

    public function __construct()
    {
        $this->products = new ArrayCollection();
    }

    /*Getters and setters
    ...
    */
}

Sonata CRUD的ProductAdmin

<?php

namespace Acme\DemoBundle\Admin;

use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
use Symfony\Component\Security\Acl\Permission\MaskBuilder;

use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;

class ProductAdmin extends Admin
{

    // Fields to be shown on create/edit forms
    protected function configureFormFields(FormMapper $formMapper)
    {
        $formMapper
            ->add('name', 'text', array('label' => 'Product name'))

            // HOWTO FILTER THESE ???
            ->add('category', 'entity', array('class' => 'Acme\DemoBundle\Entity\Category'))

            ->add('price')
            ->add('description')
        ;
    }

    /* More here, but kept short for the example
    ...
    */

}

我想要的是在ProductAdmin::configureFormFields呼叫中->add('category', 'entity', array('class' => 'Acme\DemoBundle\Entity\Category'))检查ACL的方法

任何帮助非常感谢。 FL。

2 个答案:

答案 0 :(得分:1)

解决方案是使用字段的query_builder选项过滤您的实体列表(doc is here),但我不确定如何在ACL上创建查询构建器过滤。

我看到的另一个(更好的?)解决方案是:

  1. 将您的表单声明为服务(doc
  2. 注入安全上下文作为依赖性以及您需要的任何其他依赖性
  3. 使用注入服务
  4. 请求表单中的Category列表
  5. 使用实体字段的choices选项设置表单类别,将其Category列表作为数组(doc
  6. 应该有用......

答案 1 :(得分:0)

我写这个答案只是为了让F.L. comment maphe answer站起来,因为这是他自己的问题的解决方案,对我有很大的帮助。

Symfony食谱的答案记录在案: http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html

该文档描述了如何解决需要动态表单的许多常见问题。我在这里引用文件的介绍:

  

通常情况下,无法静态创建表单。在这个条目中,你会   了解如何根据三种常见用例自定义表单:

     
      
  1. 根据基础数据自定义表单

         

    示例:您有一个“产品”表单,需要修改/添加/删除a   字段基于正在编辑的基础产品的数据。

  2.   
  3. 如何根据用户数据动态生成表单

         

    示例:您创建了“朋友消息”表单,需要构建一个   下拉列表,仅包含与当前朋友相关的用户   经过身份验证的用户。

  4.   
  5. 提交表单的动态生成

         

    示例:在注册表单上,您有一个“国家/地区”字段和一个   “state”字段,应该根据in中的值动态填充   “国家”字段。

  6.