问题:Doctrine 注册自定义 DQL 函数

我想创建一个返回半径内所有广告的方法,所以我试图添加函数:earth_distance_operatorearth_boxll_to_earthpostgress。

配置.yml

orm:
        auto_generate_proxy_classes: "%kernel.debug%"
        auto_mapping: true
        dql:
            numeric_functions:
                earth_box: Delivve\WebBundle\DQL\EarthBox
                ll_to_earth: Delivve\WebBundle\DQL\LLToEarth
                earth_distance_operator: Delivve\WebBundle\DQL\EarthDistanceOperator

EarthBox.php

class EarthBox extends FunctionNode
{
    private $earth;
    private $radius;

    public function getSql(SqlWalker $sqlWalker)
    {
        return 'earth_box(' . $this->earth->dispatch($sqlWalker) . ', ' . $this->radius->dispatch($sqlWalker) . ')';
    }

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

        $this->earth = $parser->StringPrimary();
        $parser->match(Lexer::T_COMMA);

        $this->radius = $parser->ArithmeticPrimary();
        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    }
} 

EarthDistanceOperator.php

class EarthDistanceOperator extends FunctionNode
{
    private $operator;
    private $first;
    private $second;

    /**
     * @param SqlWalker $sqlWalker
     *
     * @return string
     */
    public function getSql(SqlWalker $sqlWalker)
    {
        return sprintf("%s %s %s",
            $this->first->dispatch($sqlWalker),
            $this->operator->value,
            $this->second->dispatch($sqlWalker)
        );
    }
    /**
     * @param Parser $parser
     *
     * @return void
     */
    public function parse(Parser $parser)
    {
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);

        $this->first = $parser->StringPrimary();
        $parser->match(Lexer::T_COMMA);

        $this->operator = $parser->StringExpression();
        $parser->match(Lexer::T_COMMA);

        $this->second = $parser->StringPrimary();
        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    }
} 

LLToEath.php

class LLToEarth extends FunctionNode
{
    private $latitude;
    private $longitude;

    public function getSql(SqlWalker $sqlWalker)
    {
        return 'll_to_earth(' . $this->latitude->dispatch($sqlWalker) . ', ' . $this->longitude->dispatch($sqlWalker) . ')';
    }

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

        $this->latitude = $parser->ArithmeticPrimary();
        $parser->match(Lexer::T_COMMA);

        $this->longitude = $parser->ArithmeticPrimary();
        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    }
} 

我的问题是,当我在存储库中创建函数时,他没有给函数 ll_to_eath 无限期

AdRepository.php

    public function findByExceptOwner($paramFetcher)
    {
        $departureOriginal = $paramFetcher['departure'];
        $departureArray = preg_split('/ - /', $departureOriginal);
        $departureCityArray = preg_split('/,/', $departureArray[count($departureArray) - 2]);
        $departureUFArray = preg_split('/,/', $departureArray[count($departureArray) - 1]);
        $departure = $departureCityArray[count($departureCityArray) -1].' - '.$departureUFArray[0];

        $destinationOriginal = $paramFetcher['destination'];
        $destinationArray = preg_split('/ - /', $destinationOriginal);
        $destinationCityArray = preg_split('/,/', $destinationArray[count($destinationArray) - 2]);
        $destinationUFArray = preg_split('/,/', $destinationArray[count($destinationArray) - 1]);
        $destination = $destinationCityArray[count($destinationCityArray) -1].' - '.$destinationUFArray[0];

        dump($departure);
        dump($destination);

        $query = $this->getEntityManager()->createQueryBuilder('ad');

        // parâmetros iniciais da query: status, departure de destination
        $query->select('ad')
            ->from('DelivveWebBundle:'.$paramFetcher['type'], 'ad')
            ->where('ad.owner <> :ownerId')
            ->andWhere($query->expr()->eq('ad.status', ':status'))
            ->andWhere($query->expr()->like('ad.departure', ':departure'))
            ->andWhere($query->expr()->like('ad.destination', ':destination'))
            ->andWhere('ad.dateFinal <= :today')
            ->setParameter('ownerId', $paramFetcher['ownerId'])
            ->setParameter('status', 'new')
            ->setParameter('departure', "%{$departure}%")
            ->setParameter('destination', "%{$destination}%")
            ->setParameter('today', new \DateTime("now"));

        // raio de busca com centro nas coordenadas de departure
        if ($paramFetcher['departure_latitude'] && $paramFetcher['departure_longitude'] && $paramFetcher['radius']) {
            $query
                ->andWhere('earth_distance_operator(earth_box(ll_to_earth(:departure_lat, :departure_lon), :radius), \'@>\', ll_to_earth(ad.departureLatitude, ad.departureLongitude)) = true')
                ->setParameter('departure_lat', floatval($paramFetcher['departure_latitude']), \Doctrine\DBAL\Types\Type::FLOAT)
                ->setParameter('departure_lon', floatval($paramFetcher['departure_longitude']), \Doctrine\DBAL\Types\Type::FLOAT)
                ->setParameter('radius', floatval($paramFetcher['radius']) / 1.609, \Doctrine\DBAL\Types\Type::FLOAT);
        }

        // raio de busca com centro nas coordenadas de destionation
        if ($paramFetcher['destination_latitude'] && $paramFetcher['destination_longitude'] && $paramFetcher['radius']) {
            $query
                ->andWhere('earth_distance_operator(earth_box(ll_to_earth(:destination_lat, :destination_lon), :radius), \'@>\', ll_to_earth(ad.destinationLatitude, ad.destinationLongitude)) = true')
                ->setParameter('destination_lat', floatval($paramFetcher['destination_latitude']), \Doctrine\DBAL\Types\Type::FLOAT)
                ->setParameter('destination_lon', floatval($paramFetcher['destination_longitude']), \Doctrine\DBAL\Types\Type::FLOAT)
                ->setParameter('radius', floatval($paramFetcher['radius']) / 1.609, \Doctrine\DBAL\Types\Type::FLOAT);
        }

        dump($query->getQuery());
        dump($query->getQuery()->getResult());
        die();
        return ;
    }

这是这个给的错误,有人帮助我吗?

SQLSTATE[42883]: Undefined function: 7 ERROR: function ll_to_earth(unknown, unknown) does not exist

`

[2/2] DBALException: An exception occurred while executing 'SELECT m0_.created_at AS created_at0, m0_.updated_at AS updated_at1, m0_.id AS id2, m0_.departure AS departure3, m0_.departure_latitude AS departure_latitude4, m0_.departure_longitude AS departure_longitude5, m0_.destination AS destination6, m0_.destination_latitude AS destination_latitude7, m0_.destination_longitude AS destination_longitude8, m0_.landmark AS landmark9, m0_.transportation AS transportation10, m0_.date AS date11, m0_.price AS price12, m0_.status AS status13, m0_.responsible AS responsible14, m0_.package_type AS package_type15, m0_.date_final AS date_final16, m0_.type AS type17, m0_.user_id AS user_id18 FROM Sender s1_ INNER JOIN my_ad m0_ ON s1_.id = m0_.id WHERE m0_.user_id <> ? AND m0_.status = ? AND m0_.departure LIKE ? AND m0_.destination LIKE ? AND m0_.date_final <= ? AND earth_box(ll_to_earth(?, ?), ?) @> ll_to_earth(m0_.departure_latitude, m0_.departure_longitude) = true AND earth_box(ll_to_earth(?, ?), ?) @> ll_to_earth(m0_.destination_latitude, m0_.destination_longitude) = true' with params [2, "new", "% S\u00e3o Carlos - SP%", "%S\u00e3o Carlos - SP%", "2015-09-22 10:10:04", "-22.0087082", "-47.89092629999999", 18.645121193288, "-22.0087082", "-47.89092629999999", 18.645121193288]:

SQLSTATE[42883]: Undefined function: 7 ERROR: function ll_to_earth(unknown, unknown) does not exist
LINE 1: ...on LIKE $4 AND m0_.date_final <= $5 AND earth_box(ll_to_eart...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.

解答

事实上,错误不在代码中,而是在我机器的配置中。我的银行没有安装earthdistance模块;

安装模块:

CREATE EXTENSION cube;
CREATE EXTENSION earthdistance;
Logo

PostgreSQL社区为您提供最前沿的新闻资讯和知识内容

更多推荐