我有两个实体标记和用户。 标记可以分为以下四种类别之一:运动,食物,音乐,电影。 用户还有四个属性:运动,食物,音乐,电影其中包含与类别相关的标签数组( user.sport 可以包含 sport 类别中的标签等)。
让我们看一点代码更清楚。
AcmeBundle /实体/ Tag.php
namespace AcmeBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Table(name="tag")
* @ORM\Entity(repositoryClass="AcmeBundle\Repository\TagRepository")
*/
class Tag
{
/**
* @var int
*
* @ORM\Id
* @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="category", type="string", length=255)
*/
private $category;
/**
* @var string
*
* @ORM\Column(name="label", type="string", length=255)
*/
private $label;
}
AcmeBundle /实体/ user.php的
namespace AcmeBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Table(name="user")
* @ORM\Entity(repositoryClass="AcmeBundle\Repository\UserRepository")
*/
class User extends BaseUser
{
/**
* @var int
*
* @ORM\Id
* @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @var Tag[]
*
* @ORM\Column(name="sport", type="???")
*/
private $sport;
/**
* @var Tag[]
*
* @ORM\Column(name="food", type="???")
*/
private $food;
/**
* @var Tag[]
*
* @ORM\Column(name="music", type="???")
*/
private $music;
/**
* @var Tag[]
*
* @ORM\Column(name="movie", type="???")
*/
private $movie;
}
标签应该以这种形式存储在数据库中(数组以逗号作为分隔符进行内嵌)。
user_id | sport_tags | food_tags | music_tags | movie_tags
1 | 10,21,23 | 1,2,3 | 4,5 | 100
我想在持久用户期间自动保留标签。请看下面的例子。
$manager = $this->getDoctrine()->getManager();
$user = $manager->getRepository('AcmeBundle:User')->find(1);
$tag1 = $manager->getRepository('AcmeBundle:Tag')->find(10);
$tag2 = $manager->getRepository('AcmeBundle:Tag')->find(21);
$tag3 = $manager->getRepository('AcmeBundle:Tag')->find(23);
$tag4 = new Tag();
$tag4->setLabel('New tag');
$tag4->setCategory('sport');
$user->setSport(array(
$tag1,
$tag2,
$tag3,
$tag4,
));
$manager->persist($contact);
$manager->flush();
从数据库中获取用户后,标签的ID应自动转换为标签。从下面的示例转储应返回标记数组。
$manager = $this->getDoctrine()->getManager();
$user = $manager->getRepository('AcmeBundle:User')->find(1);
var_dump($user->getSport());
但我不确定如何实现这一点。我实现了新的Doctrine类型,它将标签数组转换为字符串(例如“10,21,23”),反之亦然。但是如何自动保留新标签?如果我试图在convertToDatabaseValue中保留标记,那么它不起作用(服务器关闭)。请参阅下面的我的TagType实现。
namespace AcmeBundle\Types;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\Type;
use Doctrine\ORM\EntityManager;
use AcmeBundle\Entity\Tag;
class TagType extends Type
{
/**
* @var EntityManager
*/
private $manager;
/**
* @return string
*/
public function getName()
{
return 'TagType';
}
/**
* @param EntityManager $manager
*/
public function setEntityManager(EntityManager $manager)
{
$this->manager = $manager;
}
/**
* @param array $fieldDeclaration
* @param AbstractPlatform $platform
* @return string
*/
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
if ($fieldDeclaration['notnull']) {
return 'LONGTEXT NOT NULL';
} else {
return 'LONGTEXT';
}
}
/**
* @param mixed $value
* @param AbstractPlatform $platform
* @return array
*/
public function convertToPHPValue($value, AbstractPlatform $platform)
{
if ($value === null) {
return array();
} else {
return array_filter(array_map(function ($id) {
return $this->manager->getRepository('AcmeBundle:Tag')->find($id);
}, explode(',', $value)));
}
}
/**
* @param mixed $value
* @param AbstractPlatform $platform
* @return string
*/
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
if ($value === null) {
return '';
} else {
return implode(',', array_filter(array_map(function (Tag $tag) {
try {
return $tag->getId();
} catch (\Exception $exception) {
return null;
}
}, $value)));
}
}
}