Как расширить класс JoinClause в laravel

Мы хотели бы расширить класс JoinClause, который Query \ Builder использует для формулирования предложений соединения.

Мы уже расширили построитель запросов BaseModel следующим образом: (По сути, CoreBaseModel - это просто модель с некоторыми дополнительными функциями.)

abstract class BaseModel extends CoreBaseModel
{
    function newBaseQueryBuilder()
    {
        return new BaseModelQueryBuilder($this->getConnection());
    }
}

Пример кода в BaseModelQueryBuilder:

class BaseModelQueryBuilder extends Builder
{
    function findOverlapping($from, $till, $from_column, $till_column)
    {
        return $this
            ->orWhereBetween($from_column, [$from, $till])
            ->orWhereBetween($till_column, [$from, $till])
            ->orWhere(function($query) use($from_column, $till_column, $from, $till)
            {
                //Around
                $query
                    ->where($from_column, '<=' , $from)
                    ->where($till_column, '>=', $till);
            });
    }
}

Это хорошо, потому что затем вы можете использовать функцию findOverlapping не только в каждом запросе, но и в каждом подзапросе этой модели.

Проблема в том, что это не работает для расширенных предложений соединения:

BaseModel::join('table_name', function($join)
{
    $join->where(function($query)
    {
        $query->findOverlapping('2018-01-01', '2018-21-31', 'from', 'till');
    });
});

Ошибка:

Call to undefined method Illuminate\Database\Query\JoinClause::findOverlapping()

Итак, я копался, пытаясь найти решение этой проблемы, и нашел функцию соединения на Illuminate\Database\Query\Builder, которая выглядит так:

/**
 * Add a join clause to the query.
 *
 * @param  string  $table
 * @param  \Closure|string  $first
 * @param  string|null  $operator
 * @param  string|null  $second
 * @param  string  $type
 * @param  bool    $where
 * @return $this
 */
public function join($table, $first, $operator = null, $second = null, $type = 'inner', $where = false)
{
    $join = new JoinClause($this, $type, $table);

    // If the first "column" of the join is really a Closure instance the developer
    // is trying to build a join with a complex "on" clause containing more than
    // one condition, so we'll add the join and call a Closure with the query.
    if ($first instanceof \Closure) {
        call_user_func($first, $join);

        $this->joins[] = $join;

        $this->addBinding($join->getBindings(), 'join');
    }

    // If the column is simply a string, we can assume the join simply has a basic
    // "on" clause with a single condition. So we will just build the join with
    // this simple join clauses attached to it. There is not a join callback.
    else {
        $method = $where ? 'where' : 'on';

        $this->joins[] = $join->$method($first, $operator, $second);

        $this->addBinding($join->getBindings(), 'join');
    }

    return $this;
}

Итак, я скопировал функцию на BaseModelQueryBuilder, сделал копию класса Illuminate\Database\Query\JoinClause и назначил ее первому оператору замещающей функции соединения: $join = new BaseModelJoinClause($this, $type, $table)

Обратите внимание, что я не менял код в классе BaseModelJoinClause по сравнению с исходным классом JoinClause (кроме операторов use и пространства имен c). Тем не менее, даже с этим тонким изменением (назначен только новый класс, который является точной копией оригинала) все запросы начинают давать сбой с такими ошибками, как: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax.

Если у кого-то есть советы по решению этой проблемы или есть опыт расширения класса JoinClause на laravel, любая помощь приветствуется :) Если вы думаете, что вам нужна дополнительная информация, дайте мне знать.

В последней версии 5.7.20 добавлен метод Builder::newJoinClause() для упрощения расширения класса JoinClause: github.com/laravel/framework/pull/26948

Jonas Staudenmeir 08.01.2019 19:27

Спасибо за отзыв, приятно видеть, что разработчики laravel позаботились об этих вещах :)

Rob Biermann 09.01.2019 09:06
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать 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
258
0

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