简体   繁体   English

在 Symfony4 中注册自定义 Doctrine 类型

[英]Register custom Doctrine type in Symfony4

So I have this custom Doctrine type所以我有这个自定义的 Doctrine 类型

namespace App\\Doctrine\\Types;命名空间 App\\Doctrine\\Types;

use Doctrine\\DBAL\\Platforms\\AbstractPlatform;使用 Doctrine\\DBAL\\Platforms\\AbstractPlatform; use Doctrine\\DBAL\\Types\\TextType;使用 Doctrine\\DBAL\\Types\\TextType;

class MyType extends TextType
{
   private $prefix='';

   public function getName()
   {
      return 'my_type';
   }
   public function setPrefix(string $prefix)
   {
      $this->prefix=$prefix;
   }
}

I registerd in in the config/packages/doctrine.yml:我在 config/packages/doctrine.yml 中注册:

doctrine:
    dbal:
        types:
            my_type: App\Doctrine\Types\MyType

Then in Kernel boot() I'm trying to add some parameters to this type:然后在 Kernel boot() 中,我尝试向这种类型添加一些参数:

public function boot() {
   parent::boot();

   $myType=Type::getType('my_type');
   $myType->setPrefix('abc');
}

This works perfectly the first time I run the app.这在我第一次运行该应用程序时非常有效。 The prefix is set for the type and can be used through the whole app.前缀是为类型设置的,可以在整个应用程序中使用。 However, the second time I get an Exception:但是,我第二次遇到异常:

Unknown column type "encrypted_text" requested.请求了未知的列类型“encrypted_text”。 Any Doctrine type that you use has to be registered with \\Doctrine\\DBAL\\Types\\Type::addType().您使用的任何 Doctrine 类型都必须使用 \\Doctrine\\DBAL\\Types\\Type::addType() 进行注册。 You can get a list of all the known types with \\Doctrine\\DBAL\\Types\\Type::getTypesMap().您可以使用 \\Doctrine\\DBAL\\Types\\Type::getTypesMap() 获取所有已知类型的列表。 If this error occurs during database introspection then you might have forgotten to register all database types for a Doctrine Type.如果在数据库内省期间发生此错误,那么您可能忘记为 Doctrine 类型注册所有数据库类型。 Use AbstractPlatform#registerDoctrineTypeMapping() or have your custom types implement Type#getMappedDatabaseTypes().使用 AbstractPlatform#registerDoctrineTypeMapping() 或让您的自定义类型实现 Type#getMappedDatabaseTypes()。 If the type name is empty you might have a problem with the cache or forgot some mapping information.如果类型名称为空,则可能是缓存有问题或忘记了一些映射信息。

I then changed boot() to :然后我将 boot() 更改为:

    public function boot() {
       parent::boot();
       if (!Type::hasType('my_type')) {
           Type::addType('my_type', 'App\Doctrine\Types\MyType');
       }
       $myType=Type::getType('my_type');
       $myType->setPrefix('abc');
   }

Now the exception is gone, but the prefix is not set.现在异常消失了,但没有设置前缀。 I know the exceptions gives me information about what to do but I really don't know where to start.我知道异常给了我关于做什么的信息,但我真的不知道从哪里开始。

Can anyone point me in the right direction?任何人都可以指出我正确的方向吗?

For now I fixed it by removing it from config/packages/doctrine.yml so it's not registered there anymore.现在我通过从 config/packages/doctrine.yml 中删除它来修复它,所以它不再在那里注册。 In Kernel I can now load it:在内核中,我现在可以加载它:

    public function boot() {
       parent::boot();
       if (!Type::hasType('my_type')) {
           Type::addType('my_type', 'App\Doctrine\Types\MyType');
       }
       $myType = Type::getType('my_type');
       $myType->setPrefix('abc');
   }

I still can't really understand why this works before building the cache but not once the cache is build.我仍然无法真正理解为什么这在构建缓存之前有效,但在构建缓存后就不行了。 But well, I can continue now.不过好吧,我现在可以继续了。

If someone has a better answer, I'd be more than happy to accept it.如果有人有更好的答案,我很乐意接受。

#This is may answer!!!


 **IMPORTANTE!! Because in Symfony/PHP (NO Object Oriented Language) don't storaging a state it's need make this form to mapping an ENUM type or any Custom Type similary to ENUM.**

For customize and mapping you types as Enum in DB table, you need to have a higher version Symfony >= 4.4 for to use this Bundle.为了自定义和映射您在 DB 表中键入的 Enum,您需要有更高版本的 Symfony >= 4.4 才能使用此 Bundle。 Execute it in your project (command prompt)在您的项目中执行它(命令提示符)

                composer req fresh/doctrine-enum-bundle 
Link  example --> [https://github.com/fre5h/DoctrineEnumBundle][1] .
I made do this and it's ok for my app.

1 1

    So, copy this class from this link 
    [https://github.com/fre5h/DoctrineEnumBundle/blob/master/DBAL/Types/AbstractEnumType.php][1] 
    and storage it in src/DBAL/Types =(IF NOT EXIST, CREATE IT), in your project Symfony => 4.4 o higher version.

    #This is your Base class type.

2 2

    Create this Table in Your Database (in my case I'm using MySql DB):

    CREATE TABLE players (
        id INT AUTO_INCREMENT NOT NULL,
        position ENUM('PG', 'SG', 'SF', 'PF', 'C') NOT NULL,
        PRIMARY KEY(id)
    ) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = INNODB
    *****************

3 3

    Create an Entity class for mapping table  (Players) from your Databae inside your project level directory.

    D:SYMFONY\app\myApp
    php bin/console doctrine:mapping:import "App\Entity" annotation --path=src/Entity --filter="Players"

4 4

    Create getter and setters for your new Entity:

    D:SYMFONY\app\myApp
    php bin/console make:entity --regenerate App 

5 5

    Generate your CRUD operation for Entty class + frontend.

    D:SYMFONY\app\myApp
    php bin/console make:entity --regenerate App 

6 6

 Create your custom Type class BasketballPositionType 

    <?php
namespace App\DBAL\Types;

use Fresh\DoctrineEnumBundle\DBAL\Types\AbstractEnumType;

final class BasketballPositionType extends AbstractEnumType
{
    public const POINT_GUARD = 'PG';
    public const SHOOTING_GUARD = 'SG';
    public const SMALL_FORWARD = 'SF';
    public const POWER_FORWARD = 'PF';
    public const CENTER = 'C';

    protected static $choices = [
        self::POINT_GUARD => 'Point Guard',
        self::SHOOTING_GUARD => 'Shooting Guard',
        self::SMALL_FORWARD => 'Small Forward',
        self::POWER_FORWARD => 'Power Forward',
        self::CENTER => 'Center'
    ];
}


7 7

Go inside this path in your Symfony project at 

                      D:SYMFONY\app\myApp\config\packages

and create this class php : doctrime.php.
This class it's necesary for to Register your new Type. 
Can you find more information at link for register new type in synfony 
[https://symfony.com/doc/current/doctrine/dbal.html][1]

so - REGISTER YOUR NEW TYPE
    Copy this fragment of code end paste in doctrime.php class:

    <?php
    $container->loadFromExtension('doctrine', [
        'dbal' => [
            'mapping_types' => [
                'enum'  => 'string', /////////mapping enum to as stringa
            ],
            'types' => [
                'BasketballPositionType' => App\DBAL\Types\BasketballPositionType::class,
            ],
        ],
    ]);

   So, bindig ENUM type db in String and your new Type is "BasketballPositionType"  !!!!


8 8

    Now, use your Custom Type in your Entity Class mapping 'Players'.

     <?php

namespace App\Entity;
     ** very important
use App\DBAL\Types\BasketballPositionType;  
use Fresh\DoctrineEnumBundle\Validator\Constraints as DoctrineAssert; 

use Doctrine\ORM\Mapping as ORM;

/**
 * Players
 *
 * @ORM\Table(name="players")
 * @ORM\Entity
 */
class Players
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="position", type="BasketballPositionType", length=255, nullable=false)
     * @DoctrineAssert\Enum(entity="App\DBAL\Types\BasketballPositionType")
     */
    private $position;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getPosition(): ?string
    {
        return $this->position;
    }

    public function setPosition(string $position): self
    {
        $this->position = $position;

        return $this;
    }


}

RUN运行

         ####################### RUM #######################

             Run you Symfony embeded server 
                                    [  symfony serve ]
             And go later in browser at https://127.0.0.1:8000/players


        I'm use CMDER prompt command because it has Git incorporated. 
        It's very easy!!

      [1]: https://symfony.com/doc/current/doctrine/dbal.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM