Php 具有多重关系的Slug

Php 具有多重关系的Slug,php,symfony,doctrine-orm,doctrine-extensions,stofdoctrineextensions,Php,Symfony,Doctrine Orm,Doctrine Extensions,Stofdoctrineextensions,我有三个实体,比如A,B和CA与B和C有两种多通关系。我想为a生成一个slug,由字段a.a、B.B和C.C组成。 目前,我可以使用a.a和B.B生成一个slug,使用以下代码: A类: <?php use Doctrine\ORM\Mapping as ORM; use Gedmo\Mapping\Annotation as Gedmo; /** * @ORM\Entity( * repositoryClass="AppBundle\Repository\AReposit

我有三个实体,比如
A
B
C
A
B
C
有两种多通关系。我想为
a
生成一个slug,由字段
a.a
B.B
C.C
组成。 目前,我可以使用
a.a
B.B
生成一个slug,使用以下代码:

A类:

<?php

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;

/**
 * @ORM\Entity(
 *     repositoryClass="AppBundle\Repository\ARepository"
 * )
 */
class A
{
    /**
     * @var integer
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue
     */
    private $id;

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

    /**
     * @var B
     * @ORM\ManyToOne(targetEntity="B")
     */
    private $b;

    /**
     * @var C
     * @ORM\ManyToOne(targetEntity="C")
     */
    private $c;

    /**
     * @var string
     * @ORM\Column(type="string", unique=true)
     * @Gedmo\Slug(handlers={
     *      @Gedmo\SlugHandler(class="Gedmo\Sluggable\Handler\RelativeSlugHandler", options={
     *          @Gedmo\SlugHandlerOption(name="relationField", value="name"),
     *          @Gedmo\SlugHandlerOption(name="relationSlugField", value="alias"),
     *          @Gedmo\SlugHandlerOption(name="separator", value="-")
     *      })
     * }, separator="-", updatable=true, fields={"name"})
     */
    private $slug;

    // ...

}

我已经用这个类解决了:

<?php

namespace App\Handler;

use Gedmo\Sluggable\Mapping\Event\SluggableAdapter;
use Gedmo\Tool\Wrapper\AbstractWrapper;

class SecondaryRelativeGedmoSlugHandler extends \Gedmo\Sluggable\Handler\RelativeSlugHandler
{

    /**
     * Used options
     *
     * @var array
     */
    private $usedOptions;

    /**
     * Callable of original transliterator
     * which is used by sluggable
     *
     * @var callable
     */
    private $originalTransliterator;

    /**
     * {@inheritDoc}
     */
    public function onChangeDecision(SluggableAdapter $ea, array &$config, $object, &$slug, &$needToChangeSlug)
    {
        $this->om = $ea->getObjectManager();
        $isInsert = $this->om->getUnitOfWork()->isScheduledForInsert($object);
        $this->usedOptions = $config['handlers'][get_called_class()];
        if (!isset($this->usedOptions['separator'])) {
            $this->usedOptions['separator'] = self::SEPARATOR;
        }
        if (!$isInsert && !$needToChangeSlug) {
            $changeSet = $ea->getObjectChangeSet($this->om->getUnitOfWork(), $object);
            if (isset($changeSet[$this->usedOptions['relationField']])) {
                $needToChangeSlug = true;
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    public function postSlugBuild(SluggableAdapter $ea, array &$config, $object, &$slug)
    {
        $this->originalTransliterator = $this->sluggable->getTransliterator();
        $this->sluggable->setTransliterator(array($this, 'transliterate'));
    }

    /**
     * Transliterates the slug and prefixes the slug
     * by relative one
     *
     * @param string $text
     * @param string $separator
     * @param object $object
     *
     * @return string
     */
    public function transliterate($text, $separator, $object)
    {
        // MIO
        $result = call_user_func_array(
            $this->originalTransliterator,
            array($text, $separator, $object)
        );
        $tokens = explode('/', $result);
        if(count($tokens) > 1) {
            $result = $tokens[count($tokens) - 1];
        }
        $wrapped = AbstractWrapper::wrap($object, $this->om);
        $relation = $wrapped->getPropertyValue($this->usedOptions['relationField']);
        if ($relation) {
            $wrappedRelation = AbstractWrapper::wrap($relation, $this->om);
            $slug = $wrappedRelation->getPropertyValue($this->usedOptions['relationSlugField']);

            if (isset($this->usedOptions['urilize']) && $this->usedOptions['urilize']) {
                $slug = call_user_func_array(
                    $this->originalTransliterator,
                    array($slug, $separator, $object)
                );
            }

            $result = $slug.$this->usedOptions['separator'].$result;
        }

        return $result;
    }
}
<?php

namespace App\Handler;

use Gedmo\Sluggable\Mapping\Event\SluggableAdapter;
use Gedmo\Tool\Wrapper\AbstractWrapper;

class SecondaryRelativeGedmoSlugHandler extends \Gedmo\Sluggable\Handler\RelativeSlugHandler
{

    /**
     * Used options
     *
     * @var array
     */
    private $usedOptions;

    /**
     * Callable of original transliterator
     * which is used by sluggable
     *
     * @var callable
     */
    private $originalTransliterator;

    /**
     * {@inheritDoc}
     */
    public function onChangeDecision(SluggableAdapter $ea, array &$config, $object, &$slug, &$needToChangeSlug)
    {
        $this->om = $ea->getObjectManager();
        $isInsert = $this->om->getUnitOfWork()->isScheduledForInsert($object);
        $this->usedOptions = $config['handlers'][get_called_class()];
        if (!isset($this->usedOptions['separator'])) {
            $this->usedOptions['separator'] = self::SEPARATOR;
        }
        if (!$isInsert && !$needToChangeSlug) {
            $changeSet = $ea->getObjectChangeSet($this->om->getUnitOfWork(), $object);
            if (isset($changeSet[$this->usedOptions['relationField']])) {
                $needToChangeSlug = true;
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    public function postSlugBuild(SluggableAdapter $ea, array &$config, $object, &$slug)
    {
        $this->originalTransliterator = $this->sluggable->getTransliterator();
        $this->sluggable->setTransliterator(array($this, 'transliterate'));
    }

    /**
     * Transliterates the slug and prefixes the slug
     * by relative one
     *
     * @param string $text
     * @param string $separator
     * @param object $object
     *
     * @return string
     */
    public function transliterate($text, $separator, $object)
    {
        // MIO
        $result = call_user_func_array(
            $this->originalTransliterator,
            array($text, $separator, $object)
        );
        $tokens = explode('/', $result);
        if(count($tokens) > 1) {
            $result = $tokens[count($tokens) - 1];
        }
        $wrapped = AbstractWrapper::wrap($object, $this->om);
        $relation = $wrapped->getPropertyValue($this->usedOptions['relationField']);
        if ($relation) {
            $wrappedRelation = AbstractWrapper::wrap($relation, $this->om);
            $slug = $wrappedRelation->getPropertyValue($this->usedOptions['relationSlugField']);

            if (isset($this->usedOptions['urilize']) && $this->usedOptions['urilize']) {
                $slug = call_user_func_array(
                    $this->originalTransliterator,
                    array($slug, $separator, $object)
                );
            }

            $result = $slug.$this->usedOptions['separator'].$result;
        }

        return $result;
    }
}
/**
 * @Gedmo\Slug(handlers={
 *      @Gedmo\SlugHandler(class="Gedmo\Sluggable\Handler\RelativeSlugHandler", value="shop", options={
 *          @Gedmo\SlugHandlerOption(name="relationField", value="shop"),
 *          @Gedmo\SlugHandlerOption(name="relationSlugField", value="name"),
 *          @Gedmo\SlugHandlerOption(name="separator", value="/"),
 *          @Gedmo\SlugHandlerOption(name="urilize", value=true)
 *      }),
 *     @Gedmo\SlugHandler(class="App\Handler\SecondaryRelativeGedmoSlugHandler", value="category", options={
 *          @Gedmo\SlugHandlerOption(name="relationField", value="category"),
 *          @Gedmo\SlugHandlerOption(name="relationSlugField", value="name"),
 *          @Gedmo\SlugHandlerOption(name="separator", value="/"),
 *          @Gedmo\SlugHandlerOption(name="urilize", value=true)
 *      })
 * },fields={"name"}, unique=true, updatable=true)
 * @ORM\Column(type="string", length=255, unique=true)
 */
private $slug;