在Sonata Admin Bundle中使用标签

时间:2014-08-15 07:56:58

标签: symfony tags sonata-admin

我在SonataAdminBundle(问题,文章,新闻)中有几个实体,我想要连接标签。我通过与每个实体的Tag实体的多对多关系来实现它。但为此必须创建几个中间连接表,这是不方便的。

我找到了一个包FPNTagBundle,它允许使用额外的字段ResourceType指定连接表。这正是我需要的,我在另一个项目中做了同样的事情。

但是FPNTagBundle通过单独的TagManager建立通信,并且在SonataAdmin中不起作用。

你对我有什么建议?如何实现这个任务?

也许不用担心,并留下几个单独的交接表?但是,我仍然会有其他六个实体用于标记...而且我担心所有标记实体中的标记搜索都很难 - 它会在多个表中运行。

1 个答案:

答案 0 :(得分:2)

求解在Saving hooks

/**
 * @return FPN\TagBundle\Entity\TagManager
 */
protected function getTagManager() {
    return $this->getConfigurationPool()->getContainer()
        ->get('fpn_tag.tag_manager');
}

public function postPersist($object) {
    $this->getTagManager()->saveTagging($object);
}

public function postUpdate($object) {
    $this->getTagManager()->saveTagging($object);
}

public function preRemove($object) {
    $this->getTagManager()->deleteTagging($object);
    $this->getDoctrine()->getManager()->flush();
}

我的管理员课程:

protected function configureFormFields(FormMapper $formMapper)
{
    $tags = $this->hasSubject()
        ? $this->getTagManager()->loadTagging($this->getSubject())
        : array();

    $formMapper
        // other fields
        ->add('tags', 'entity', array('class'=>'AppBundle:Tag', 'choices' => $tags, 'multiple' => true, 'attr'=>array('style'=>'width: 100%;')))
    ;
}

SonataAdminBundle中有一个known bug - 当执行批量删除(在列表视图中)时,钩子preRemove / postRemove不会运行。我们需要扩展标准CRUD控制器:

namespace App\AppBundle\Controller;

use Sonata\AdminBundle\Controller\CRUDController as Controller;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Sonata\AdminBundle\Datagrid\ProxyQueryInterface;

class CRUDController extends Controller
{
    public function batchActionDelete(ProxyQueryInterface $query)
    {
        if (method_exists($this->admin, 'preRemove')) {
            foreach ($query->getQuery()->iterate() as $object) {                
                $this->admin->preRemove($object[0]);
            }
        }

        $response = parent::batchActionDelete($query);

        if (method_exists($this->admin, 'postRemove')) {
            foreach ($query->getQuery()->iterate() as $object) {                
                $this->admin->postRemove($object[0]);
            }
        }

        return $response;
    }

}