Skip to content

Custom DQL functions: TypedExpression returning StringType does not cast to string #11537

@janedbal

Description

@janedbal

While implementing better expression type inference in phpstan-doctrine, I added support even for TypedExpression as those are the only way how to have type inference with custom functions.

But the problem is that it is designed to use Type::convertToPHPValue which is no-op for StringType (it keeps whatever the value is, no casting performed). This means that all TypedExpressions returning StringType are actually not typed at all.

I kept this exception in phpstan-doctrine, but this feels like a design flaw and can definitelly cause some WTF moments.

Obviously, anybody can solve it by custom Type that do cast to string, but that requires deeper knowledge of how things work.

use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\SqlWalker;
use Doctrine\ORM\Query\TokenType;

class Date extends FunctionNode implements TypedExpression
{
    public $date;

    public function getSql(SqlWalker $sqlWalker): string
    {
        return 'DATE(' . $sqlWalker->walkArithmeticPrimary($this->date) . ')';
    }

    public function parse(Parser $parser): void
    {
        $parser->match(TokenType::T_IDENTIFIER);
        $parser->match(TokenType::T_OPEN_PARENTHESIS);

        $this->date = $parser->ArithmeticPrimary();

        $parser->match(TokenType::T_CLOSE_PARENTHESIS);
    }

    public function getReturnType(): Type
    {
        return Type::getType(Types::STRING); // "broken"
    }
}

I dont really have any proposal of how to make this better. Maybe just document it?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions