Как проверить на существование таблицы модели в Laravel

Как проверить на существование таблицы модели в Laravel

Иногда, в Laravel, необходимо убедиться, существует ли какая-то конкретная таблица на момент запуска приложения. И в зависимости от результата, исполнять код, или нет. И в этой статье я покажу, как убедиться в наличии таблицы в базе данных в приложении на Laravel.

Причин для подобных проверок может быть множество:

  • модульная структура, где код подключается динамически;
  • развёртывание проекта, где таблиц ещё не существует, а код из провайдеров пытается обратиться к модели с ещё не созданной таблицей;
  • глобальный шаринг переменной модели в представления.

И, как раз таки, второй вариант и случился со мной недавно. Ко мне попал проект, который мне нужно было поднять локально: прописать конфигурационные данные, запустить миграции, и протестировать работу.

Однако, на стадии выполнения миграций я получил ошибку: Base table or view not found: 1146 Table..., что означает, что какой-то сервис провайдер обращается к таблице к которой ещё нет. Заглянув в код, увидел что в сервис-провайдере подгружаются конфигурационные данные из БД, и на основе них инициализируются остальные сервисы.

Проверка существования таблицы в Laravel

Чтобы узнать, существует ли таблица в базе данных нужно написать код, передав название таблицы:

\Schema::hasTable('table_name'); // true | false

if(\Schema::hasTable('table_name')) {
    // таблица существует
} else {
    // таблица не существует
    // передаём параметры по-умолчанию, или не делаем ничего
}

Проверка выполняется ли код Laravel из консоли

Однако, для решения этой задачи, мы можем воспользоваться и другим подходом. Ведь, чтобы поправить вышеописанную ошибку, нам достаточно применить миграции, таблица будет создана и приложение не будет валиться с ошибкой. Потому, нам достаточно проверить, выполняется ли текущий код из консоли, и если да, то пропустить выполнение кода, который обращается к БД. В прошлой статье мы уже рассматривали этот подход более подробно.

Для проверки среды выполнения, можно воспользоваться кодом:

if (app()->runningInConsole()) {
    // приложение запущено из консоли
    // php artisan ...
} else {
    // обычный режим работы приложения, выполняем обращения к БД
}

Реальный кейс

В этом разделе я приведу код, из проекта, о котором рассказывал в самом начале. И вот моя реализация:

class ClientsServiceProvider extends ServiceProvider
{
    public function register()
    {
        // инициализируем сервис на основе данных, полученных из БД
        $this->app->singleton(SyncDataService::class, function(Application $app) {
            $configs = collect([]);
            
            // Запись (new Config())->getTable() вернёт имя таблицы модели
            // Аналогичная запись, как и \Schema::hasTable('configs'), но надёжнее на случай смены имени
            if (\Schema::hasTable((new Config())->getTable())) {
                $configs = Config::whereIn('key', ['1c_site_id', '1c_site_password'])->get()->keyBy('key');
            }

            /** @var Config $siteId */
            $siteId = $configs->get('1c_site_id');
            /** @var Config $password */
            $password = $configs->get('1c_site_password');

            return new SyncDataService(
                $siteId ? $siteId->getValue() : '',
                $password ? md5($password->getValue()) : '',
                $app->get(SoapClient::class)
            );
        });
    }

    public function boot()
    {
        //
    }
}

И, если такой таблицы не существует, то просто передаём значения по-умолчанию, лишь бы приложение не крашилось и позволило применить все миграции.

Резюме

В этой статье разобрались, как проверить на существование таблицы в приложении Laravel, используя инструменты фреймворка. А, так же, как исправить распространённую ошибку в приложениях Laravel - Base table or view not found, возникающую при миграции или запуске приложения. Надеюсь, что теперь вы успешно применили миграции, и в будущем сможете избежать любых ошибок при выполнении миграций Laravel в новых проектах.