如何在Doctrine中的json_array中自定义键和值?

时间:2016-09-25 19:27:19

标签: php doctrine-orm doctrine symfony

我在我的实体中使用 json_array 来存储公交城市(Symfony 3.1项目)。我的实体摘录如下:

class Travel {

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

    /* OTHER VARIABLES HERE */

    /**
    * @var integer
    * @ORM\Column(name="transit_cities", type="json_array", nullable=true)
    */
    protected $transitCities;

    /* OTHER VARIABLES HERE */    

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

    /* GETTERS AND SETTERS HERE */    

}

在我的表单中,我使用的是ChoiceType :: class,其allow_add设置为 true 。用户可以选择添加新值并删除现有值:

$builder->add('transitCities', CollectionType::class, array(
                'entry_type'    => null,
                'prototype'     => true,
                'allow_add'     => true,
                'allow_delete'  => true,
                'delete_empty'  => true,
                'error_bubbling'=> false,
                'entry_options' => array(
                    'attr'      => array('class' => 'transit-cities')
                ),
            ))

使用默认的成功表单提交,这非常有效(没有在控制器内部设置任何特殊内容)。持久化数据具有以下结构:

[
    0 => "City 1",
    1 => "City 2",
    // and so on
]

其中密钥(本例中为0和1)由Doctrine自动生成。但我想使用自己的密钥而不是默认的索引号,最好还添加其他相关信息,如下所示:

[
    {'123' => 'City 1', 'dateTime' => 'Travel-date 1', 'opt'=> 1},
    {'45' => 'City 2', 'dateTime' => 'Travel-date 2', 'opt'=> 2},
    // and so on
]

123和45可以是city-id的FK,而dateTime和opt可以是每行的其他相关信息。

==== 已添加详细信息 ===

这是我的城市实体:

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Cities
 *
 * @ORM\Table(name="city")
 * @ORM\Entity
 * @ORM\Entity(repositoryClass="AppBundle\Repository\CityRepository")
 */
class City
{
    /**
     * @var string
     * @ORM\Column(name="name", type="string", length=70, nullable=false)
     */
    private $name;

    /**
     * @var string
     *
     * @ORM\Column(name="country", type="string", length=32, nullable=false)
     */
    private $country;

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


    /* CONST */
    public function __toString() {
        return $this->name;
    }

    /* OTHER PARAMETERS HERE */


    /* GETTERS AND SETTERS */    
    /**
     * Set name
     *
     * @param string $name
     *
     * @return City
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }


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


}

我想将cityId用于json_key。例如,如果用户选择了城市"伦敦"与相应的cityId如100和再次city" Amsterdam"使用cityId 115,然后json_array中的键对应该是:

  

{' 100' => '伦敦',' dateTime' => ' 2000-01-01',' opt' => 1}

     

{' 115' => '阿姆斯特丹',' dateTime' => ' 2000-01-02',' opt' => 4}

其中, dateTime 由用户使用js-date-picker选取,而 opt 仅取代任意值,例如。 Transit-Cities可以由用户根据自己的选择添加和删除(已经运行)。

如何实现这一目标?请建议。

2 个答案:

答案 0 :(得分:3)

您可以创建custom mapping type以方便您的自定义json数组。

来自文档:

<?php
namespace My\Project\Types;

use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform;

/**
 * My custom json city type.
 */
class JsonCityType extends Type
{
    const MYTYPE = 'json_city_type';

    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
    {
        // Get json array type
        return $platform->getJsonTypeDeclarationSQL('json_array');
    }

    public function convertToPHPValue($value, AbstractPlatform $platform)
    {
        // This is executed when the value is read from the database. Make your conversions here, optionally using the $platform.
    }

    public function convertToDatabaseValue($value, AbstractPlatform $platform)
    {
        // This is executed when the value is written to the database. Make your conversions here, optionally using the $platform.
    }

    public function getName()
    {
        return self::MYTYPE; // modify to match your constant name
    }
}

像这样使用:

/**
* @var integer
* @ORM\Column(name="transit_cities", type="json_city_type", nullable=true)
*/
protected $transitCities; // ;

您需要在doctrine config中注册自定义类型:

'doctrine' => array(
    'configuration' => array(
        'orm_default' => array(
            'types' => array(
                'json_city_type' => My\Project\Types\JsonCityType::class
            )
        )
    )
)

我保留了自定义convertToPHPValueconvertToDatabaseValue中的键和值的逻辑,因为我不知道从哪里获取数据。

答案 1 :(得分:0)

我尝试使用数据类型json_array做了几件事但没有按预期工作。因此,为了简化操作,我切换到simple_array数据类型并添加了3个新属性;即cityIddateTimeopt。所以我的新实体类看起来如下所示:

class Travel {

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

    /* OTHER PROPERTIES HERE */

    /**
     * @var integer
     *
     * @ORM\Column(name="transit_cities", type="simple_array", nullable=true)
     */
    protected $transitCities;

    /**
     * @var integer
     *
     * @ORM\Column(name="date_time", type="simple_array", nullable=true)
     */
    protected $dateTime;


    /**
     * @var integer
     *
     * @ORM\Column(name="opt", type="simple_array", nullable=true)
     */
    protected $opt;


    /* OTHER PROPERTIES + GETTERS AND SETTERS HERE */    

}

虽然我在将来的任何时候都错过了向json_array添加新属性的灵活性;尽管如此,现在好处是使用WHERE XX IN array()子句搜索更简单。