php - Symfony3 项目中的 POMM2,注册转换器时遇到问题

标签 php postgresql pomm

思路是这样的。在表“驱动程序”中,我有描述“驱动程序”的字段,但我需要存储另一组大约 100 个字段,我不需要将它们作为表列。所以我决定将它们存储在 Jsonb 字段中。我需要能够将这些字段作为模型字段使用,但它们需要自动保存在一个 jsonb 字段中。当我从一个表中选择时,我需要这个字段像表中的其他字段一样显示。

我查看了有关转换器的文档并找到了 PgJson 转换器。所以我认为这是处理这个问题的正确工具,但到目前为止我没有设法以正确的方式配置东西。

我尝试将字段“testinfo”注册为类型“extrainfo”,该类型在 SessionBuilder 中注册为转换器,但没有成功。不会调用 fromPg 和 toPG 方法。在这里,我展示了我的项目文件中的示例。

Composer .json

...
"require": {
    "php": ">=7.0.0",
    ...
    "pomm-project/pomm-bundle": "^2.3",
    "sensio/distribution-bundle": "^5.0.19",
    "sensio/framework-extra-bundle": "^3.0.2",
    ...
    "symfony/symfony": "3.3.6",
    ...
    "vibby/pomm-project-fos-user-bundle": "dev-master"
},
...

CREATE TABLE public.driver
(
  driver_id bigint NOT NULL DEFAULT nextval('driver_driver_id_seq'::regclass),
  account_id integer NOT NULL,
  infodata jsonb, -- large number of fields,...
  weight jsonb, -- weights for fields that are not in jsonb field
  ssn character varying,
  signature character varying
  -- ...
)

配置.yml

pomm:
configuration:
    driversdb:
        dsn: "pgsql://%db_user2%:%db_password2%@%db_host2%:%db_port2%/%db_name2%"
        #session_builder: "pomm.session_builder"
        pomm:default: true
        session_builder: 'AppBundle\Model\Driversdb\SessionBuilder'

服务.yml

...
drivertojson:
    class: AppBundle\Service\DriverToJson
    tags:
        - { name: pomm.model, converter: pomm.model }

AppBundle\Model\Driversdb\SessionBuilder:
    autowire: true
...

/src/AppBundle/Model/Driversdb/SessionBuilder.php

namespace AppBundle\Model\Driversdb;

use AppBundle\Service\DriverToJson;          //Exact Copy of Pomm PgJson converter.
use PommProject\Foundation\Converter\PgJson;
use PommProject\Foundation\Session\Session;
use PommProject\ModelManager\SessionBuilder as BaseSessionBuilder;

class SessionBuilder extends BaseSessionBuilder
{
    protected function postConfigure(Session $session) {
        parent::postConfigure($session);

        $session
            ->getPoolerForType('converter')
            ->getConverterHolder()
            ->registerConverter('extrainfo', new DriverToJson(), ['infodata', 'public.driver.infodata']) // register Jsonb converter
            ->addTypeToConverter('extrainfo', 'extrainfo', false) // convert a domain of point
        ;
    }
}

/src/AppBundle/Model/Driversdb/PublicSchema/Driver.php

namespace AppBundle\Model\Driversdb\PublicSchema;

use PommProject\ModelManager\Model\FlexibleEntity;

/**
 * Driver
 * Flexible entity for relation
 * public.driver
 * @see FlexibleEntity
*/
class Driver extends FlexibleEntity
{
    public $keyForId = 'driver_id';

    public function getId() {
        return $this->get($this->keyForId);
    }

    public function __toString() {
        return $this->getSsn();
    }

    private $driver_id;
    private $account_id;
    private $infodata;
    private $weight;
    private $ssn;
    private $signature;
    //...
    private $testinfo;

    public function getTestinfo() {
        if ($this->has('testinfo')) {
            return $this->get('testinfo');
        } else {
            return '';
        }
    }

    public function getDriverId() {
        if ($this->has('driver_id')) {
            return $this->get('driver_id');
        } else {
            return '';
        }
    }

    public function getAccountId() {
        if ($this->has('account_id')) {
            return $this->get('account_id');
        } else {
            return '';
        }
    }
//...

/src/Appbundle/Controller/DriverController.php

namespace AppBundle\Controller;

use AppBundle\Form\DriverFormType;
use AppBundle\Model\Driversdb\PublicSchema\Driver;
use AppBundle\Model\Driversdb\PublicSchema\DriverModel;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Form\Exception\InvalidArgumentException;
use Symfony\Component\HttpFoundation\Request;
use AppBundle\Service\DriverToJson;

class DriverController extends Controller
{
//...
/**
     * @Route("/driver", name="driver_create")
     * @Method ("POST")
     * @Template("@App/Driver/new.html.twig")
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\RedirectResponse
     * @throws \Exception
     */
    public function createAction(Request $request){
        $driver = new Driver();
        $form = $this->createForm(DriverFormType::class, $driver,[
            'action'=> $this->generateUrl('driver_create'),
            'method'=> 'POST'
        ]);

        $form->handleRequest($request);
        if($form->isValid()){
            $driver = $form->getData();
            try{
                /** @var DriverModel $driverModel */
                $driverModel = $this->get('pomm')['driversdb']->getModel(DriverModel::class);
                $driverModel->insertOne($driver);
                return $this->redirectToRoute('driver_list');
            }catch (\Exception $e){
                throw $e;
            }
        }
        throw new InvalidArgumentException('Invalid form data');
    }
//...
}

/src/AppBundle/Form/DriverFormType.php

namespace AppBundle\Form;

use AppBundle\Model\Driversdb\PublicSchema\Driver;
use AppBundle\Service\DriverToJson;
use PommProject\Foundation\Converter\ConverterPooler;
use PommProject\PommBundle\Request\ParamConverter\EntityParamConverter;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class DriverFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options){
        $builder
            ->add('testinfo', 'extrainfo', array('mapped'=>false))
            ->add('account_id', TextType::class)
            ->add('ssn', TextType::class,array(
                'attr'  => [
                    'class' => 'col-xs-12'
                ]
            ))
           // ... many other fields.
        ;
    }

    public function configureOptions(OptionsResolver $resolver) {
        $resolver->setDefaults([
            'data_class'=> Driver::class,
            'attr'=>array('novalidate'=>'novalidate'),
        ]);
    }
}

最佳答案

Pomm 的转换器使用字段类型来确定应该调用哪个转换器。您的字段应该是 extrainfo

创建这个新类型:

CREATE DOMAIN extrainfo AS jsonb;

并将其用于 infodata 列:

ALTER TABLE driver ALTER COLUMN infodata TYPE extrainfo;

关于php - Symfony3 项目中的 POMM2,注册转换器时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45814354/

相关文章:

postgresql - 在一个表上截断被另一个表的选择阻塞

postgresql - swarm环境docker容器中增加/dev/shm(docker stack deploy)

postgresql - Pommbundle 与另一个表的关系

php - 从 mysql 获取数组的反转结果

javascript - 检测智能 watch 何时访问网页

php - 在创建类似功能以导入和映射 CSV 方面寻求帮助,类似于 Mailchimp

sql - PostgreSQL 将行转置为列

php - 自动选择带有pomm项目的特定hstore

php - 使用 Pomm 清除数据库数据

php - preg_split 字符串不在单引号之间