Как проверить на существование таблицы модели в 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 в новых проектах.