Вопрос в названии.
У меня есть собственный класс 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;
@ TomášNeumaier да, это вызывает ту же ошибку, что и в третьем случае






Вам необходимо реализовать собственный класс тип отображения, например. IP и используйте его для определения отображений для ваших сущностей. Преобразование значений может быть выполнено с помощью функций ip2long() и long2ip(), при необходимости обратитесь к ответу это для получения дополнительной информации по этой теме.
я хочу поддерживать ipv6
Вы можете поддерживать любой формат, который вам может понадобиться, общий принцип заключается в создании пользовательских типов сопоставления, если вы хотите автоматическое преобразование значений.
и я также хотел бы сделать как можно больше преобразований, используя MySQL, а не PHP
и да, у меня есть IPType, который расширяет Doctrine \ DBAL \ Types \ Type (вторая строка моего вопроса об этом)
@DevilishSkull Извините, использование нестандартного типа не ясно из вашего вопроса
У тебя есть какие-либо идеи?
@DevilishSkull, можете ли вы обновить свой вопрос и добавить свой собственный класс типа Doctrine? Использование настраиваемого типа должно быть правильным ответом на ваш собственный вопрос, но, поскольку он у вас уже есть - может быть, что-то не так с самим классом? Также может быть стоит опубликовать хотя бы часть объекта, который включает свойство, использующее ваш настраиваемый тип.
обновлено. Я до сих пор не понимаю, почему возникает третья ошибка.
@DevilishSkull У меня есть одна мысль: вы явно передаете свой IP-адрес Criteria, но если вы посмотрите в источники, как отображаются критерии, вы увидите, что они просто объединяются. Я бы предложил вместо этого передать именованный параметр :ip и назначить его для запроса через setParameter. У этого метода есть третий аргумент $type, поэтому, если он не будет работать неявно - вы можете попробовать передать его тип явно. Не могли бы вы попробовать?
мне помогла следующая строчка $qb->andWhere('t.ip= :ip')->setParameter('ip', $ip, 'ip_address');. Однако есть ли способ автоматически определить тип параметра? Теоретически это возможно, потому что я явно указываю имя объекта и столбца.
@DevilishSkull Согласно источникам Doctrine разрешение параметров выполняется здесь и более или менее зависит от статической логики, вероятно, из-за соображений производительности. Самый простой способ, который я вижу из источников, - это создать собственный класс Parameter и использовать getParameters()->add(new IpParameter()) для установки пользовательского параметра.
Вы пробовали $ qb-> expr () -> eq ('t.ip', $ qb-> expr () -> literal ('127.0.0.1'))?