Как обновить таблицу с помощью Doctrine2 ORM и заставить ее автоматически преобразовывать типы данных?

Вопрос в названии.

У меня есть собственный класс IP-адресов, который использует функции INET_NTOA и INET_ATON и расширяет Doctrine \ DBAL \ Types \ Type.

Что я пробовал

1

$qb->update(static::class, 't');
$qb->set('t.field', false);
$qb->where($qb->expr()->eq('t.ip', '127.0.0.1'));
$qb->getQuery()->execute();

что вызывает [Syntax Error] line 0, col 41: Error: Expected Literal, got 'WHERE'

2

$qb->update(static::class, 't');
$qb->set('t.field', $qb->expr()->literal(false));
$qb->where($qb->expr()->eq('t.ip', '127.0.0.1'));
$qb->getQuery()->execute();

что вызывает [Syntax Error] line 0, col 63: Error: Expected Literal, got '127.0.0.1'

3

$qb->update(static::class, 't');
$qb->set('t.field', $qb->expr()->literal(false));
$criteria = Criteria::create()->where(Criteria::expr()->eq('t.ip', '127.0.0.1'));
$qb->addCriteria($criteria);
$qb->getQuery()->execute();

что приводит к:

An exception occurred while executing 'UPDATE table SET field = 0 WHERE ip = ?' with params ["127.0.0.1"]:
SQLSTATE[22007]: Invalid datetime format: 1292 Truncated incorrect DOUBLE value: '127.0.0.1'`

UPD:

Мой собственный IPType:

namespace app\types;

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

class IpType extends Type
{
    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform): string
    {
        return $platform->getIntegerTypeDeclarationSQL(['unsigned' => true]);
    }

    public function canRequireSQLConversion(): bool
    {
        return true;
    }

    public function convertToPHPValueSQL($sqlExpr, $platform): string
    {
        return sprintf('INET_NTOA(%s)', $sqlExpr);
    }

    public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform): string
    {
        return sprintf('INET_ATON(%s)', $sqlExpr);
    }

    public function getName(): string
    {
        return 'ip_address';
    }
}

и объявление IP в моем классе Entity:

/**
 * @Column(type = "ip_address")
 * @var string
 */
protected $ip;

Вы пробовали $ qb-> expr () -> eq ('t.ip', $ qb-> expr () -> literal ('127.0.0.1'))?

Tomáš Neumaier 03.01.2019 19:57

@ TomášNeumaier да, это вызывает ту же ошибку, что и в третьем случае

DevilishSkull 04.01.2019 00:35
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
2
108
1

Ответы 1

Вам необходимо реализовать собственный класс тип отображения, например. IP и используйте его для определения отображений для ваших сущностей. Преобразование значений может быть выполнено с помощью функций ip2long() и long2ip(), при необходимости обратитесь к ответу это для получения дополнительной информации по этой теме.

я хочу поддерживать ipv6

DevilishSkull 03.01.2019 18:58

Вы можете поддерживать любой формат, который вам может понадобиться, общий принцип заключается в создании пользовательских типов сопоставления, если вы хотите автоматическое преобразование значений.

Flying 03.01.2019 19:01

и я также хотел бы сделать как можно больше преобразований, используя MySQL, а не PHP

DevilishSkull 03.01.2019 19:01

и да, у меня есть IPType, который расширяет Doctrine \ DBAL \ Types \ Type (вторая строка моего вопроса об этом)

DevilishSkull 03.01.2019 19:02

@DevilishSkull Извините, использование нестандартного типа не ясно из вашего вопроса

Flying 03.01.2019 19:12

У тебя есть какие-либо идеи?

DevilishSkull 08.01.2019 22:47

@DevilishSkull, можете ли вы обновить свой вопрос и добавить свой собственный класс типа Doctrine? Использование настраиваемого типа должно быть правильным ответом на ваш собственный вопрос, но, поскольку он у вас уже есть - может быть, что-то не так с самим классом? Также может быть стоит опубликовать хотя бы часть объекта, который включает свойство, использующее ваш настраиваемый тип.

Flying 09.01.2019 11:06

обновлено. Я до сих пор не понимаю, почему возникает третья ошибка.

DevilishSkull 10.01.2019 03:11

@DevilishSkull У меня есть одна мысль: вы явно передаете свой IP-адрес Criteria, но если вы посмотрите в источники, как отображаются критерии, вы увидите, что они просто объединяются. Я бы предложил вместо этого передать именованный параметр :ip и назначить его для запроса через setParameter. У этого метода есть третий аргумент $type, поэтому, если он не будет работать неявно - вы можете попробовать передать его тип явно. Не могли бы вы попробовать?

Flying 10.01.2019 11:44

мне помогла следующая строчка $qb->andWhere('t.ip= :ip')->setParameter('ip', $ip, 'ip_address');. Однако есть ли способ автоматически определить тип параметра? Теоретически это возможно, потому что я явно указываю имя объекта и столбца.

DevilishSkull 10.01.2019 19:01

@DevilishSkull Согласно источникам Doctrine разрешение параметров выполняется здесь и более или менее зависит от статической логики, вероятно, из-за соображений производительности. Самый простой способ, который я вижу из источников, - это создать собственный класс Parameter и использовать getParameters()->add(new IpParameter()) для установки пользовательского параметра.

Flying 10.01.2019 20:51

Другие вопросы по теме