Советы по Laravel. Часть 1.

Советы по Ларавел

Laravel полон скрытых жемчужин, недокументированных или малоизвестных функций, опций и «хаков». Все что я нашёл, за время своей работы, я оформил в отдельную статью. Это первая её часть.

Совет 1. Вызываемые Контроллеры

Если вы хотите создать контроллер только с одним действием, вы можете использовать метод __invoke() и даже создать «вызываемый» (invokable) контроллер.

namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
class ShowProfile extends Controller
{
    /**
     * Показать профайл данного пользователя
     *
     * @param  int  $id
     * @return Response
     */
    public function __invoke($id)
    {
        return view('user.profile', ['user' => User::findOrFail($id)]);
    }
}

Маршруты:

Route::get('user/{id}', 'ShowProfile');

Artisan команда для создания такого контроллера:

php artisan make:controller ShowProfile --invokable

 

Совет 2. Беззнаковое целое

Для внешнего ключа в миграции вместо integer() используйте unsignedInteger() или integer()->unsigned(), в противном случае вы можете получить ошибку SQL.

Schema::create('employees', function (Blueprint $table) {
    $table->unsignedInteger('company_id');
    $table->foreign('company_id')->references('id')->on('companies');
    // ...
});

 

Совет 3. OrderBy в отношениях Eloquent

Вы можете указывать orderBy() прямо в определении отношений.

public function products()
{
    return $this->hasMany(Product::class);
}
public function productsByName()
{
    return $this->hasMany(Product::class)->orderBy('name');
}

 

Совет 4. Порядок миграций

Если вы хотите изменить порядок миграций в БД, просто переименуйте временную метку файла, например 2018_08_04_070443_create_posts_table.php в 2018_07_04_070443_create_posts_table.php (изменено с 2018_08_04 на 2018_07_04). Они запускаются в алфавитном порядке.

 

Совет 5. Сырые запросы к БД

Вы можете использовать сырые запросы к базе данных в различных местах, включая функцию havingRaw() после groupBy().

Product::groupBy('category_id')->havingRaw('COUNT(*) > 1')->get();

 

Совет 6. переменная $loop в foreach

Внутри цикла foreach вы можете проверить является ли текущая запись первой/последней, просто используя переменную $loop.

@foreach ($users as $user)
    @if ($loop->first)
        Это первая итерация.
    @endif
    @if ($loop->last)
        Это последняя итерация.
    @endif
    <p>Это пользователь {{ $user->id }}</p>
@endforeach

У неё есть и другие свойства, например, $loop->iteration или $loop->count.
Подробнее здесь: https://laravel.com/docs/master/blade#the-loop-variable

 

Совет 7. Методы where для времени в Eloquent

В Eloquent вы можете проверьте дату с помощью функций whereDay(), whereMonth(), whereYear(), whereDate() и whereTime().

$products = Product::whereDate('created_at', '2018-01-31')->get();
$products = Product::whereMonth('created_at', '12')->get();
$products = Product::whereDay('created_at', '31')->get();
$products = Product::whereYear('created_at', date('Y'))->get();
$products = Product::whereTime('created_at', '=', '14:13:58')->get();

 

Совет 8. Группа маршрутов внутри группы

В маршрутах можно создать группу внутри группы, назначив определенный мидлвар только некоторым URL-адресам в «родительской» группе.

Route::group(['prefix' => 'account', 'as' => 'account.'], function() {
    Route::get('login', 'AccountController@login');
    Route::get('register', 'AccountController@register');
    Route::group(['middleware' => 'auth'], function() {
        Route::get('edit', 'AccountController@edit');
    });
})

 

Совет 9. Инкременты и декременты

Если вы хотите инкрементировать значение поля в таблице, просто используйте функцию increment(). Можно увеличивать не только на 1, но и на нужно вам число, например, 50.

Post::find($post_id)->increment('view_count');
User::find($user_id)->increment('points', 50);

 

Совет 10. Существует ли шаблон?

Вы можете проверить, существует ли файл шаблона, прежде чем загрузить его.

if (view()->exists('custom.page')) {
    // Загрузить шаблон
}

Вы даже можете определить массив шаблонов, и только первый найденный будет загружен фактически.

return view()->first(['custom.dashboard', 'dashboard'], $data);

 

Совет 11. Без полей меток времени

Если ваша таблица не содержит полей меток времени created_at и updated_at, вы можете указать модели Eloquent, через $timestamps = false, что бы она их не использовала.

class Company extends Model
{
    public $timestamps = false;
}

 

Совет 12. Поля миграции с часовыми поясами

Знаете ли вы, что в миграциях есть не только timestamps(), но и timestampsTz() для часового пояса.

Schema::create('employees', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->string('email');
    $table->timestampsTz();
});

Кроме того, есть dateTimeTz(), timeTz(), timestampTz(), softDeletesTz().

 

Совет 13. Eloquent метод has() еще глубже

Вы можете использовать функцию has() для запроса отношений на глубину в два слоя!

// Author -> hasMany(Book::class);
// Book -> hasMany(Rating::class);
$authors = Author::has('books.ratings')->get();

 

Совет 14. Типы полей миграций

Есть несколько интересных типы полей, например:

$table->geometry('positions');
$table->ipAddress('visitor');
$table->macAddress('device');
$table->point('position');
$table->uuid('id');

Просмотреть все типы: https://laravel.com/docs/master/migrations#creating-column

 

Совет 15. Справка по команде Artisan

Чтобы узнать параметры команды artisan, выполните её с флагом —help:

php artisan make:model --help

Параметры:

-a, --all — Генерирует миграцию, фабрику и контроллер ресурсов для модели
-c, --controller — создает новый контроллер для модели
-f, --factory — создает новую фабрику для модели
--force — принудительное создание класса, даже если модель уже существует.
-m, --migration — создает новый файл миграции для модели.
-p, --pivot — указывает, должна ли создаваемая модель быть пользовательской моделью промежуточной таблицы.
-r, --resource — указывает, должен ли сгенерированный контроллер быть контроллером ресурсов.
-h, --help — показывает эту справку
-q, --quiet — не выводить никаких сообщений
-V, --version — показыает версии приложения
--ansi — включить вывод ANSI
--ansi — включить вывод ANSI
--no-ansi — отключить вывод ANSI
-n, --no-interaction — не задавать интерактивных вопросов
-- env[=ENV] — среда, в которой должна выполниться команда
- v|vv|vvv, --verbose — объем отображаемых сообщений: 1 - нормальный вывод, 2 - подробный вывод и 3 — отладка

 

Совет 16. Временная Метка по умолчанию

При создании миграций вы можете использовать типа поля ->timestamp() с параметром ->useCurrent(), который выставит дефолтным значением CURRENT_TIMESTAMP.

$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->useCurrent();

 

Совет 17. Установка залогиненного пользователя через Наблюдателя

Используйте make:observer и метод creating() для автоматической установки поля user_id для залогиненного пользователя.

class PostObserver
{
    /**
     * Обрабатываем событие «создание» записи.
     *
     * @param  \App\Post  $post
     * @return void
     */
    public function creating(Post $post)
    {
        $post->user_id = auth()->id();
    }
}

 

Совет 18. Мягкое удаление: множественное восстановление

При использовании мягкого удаления (soft-deletes) вы можете восстановить одним запросом разом несколько записей.

Post::withTrashed()->where('author_id', 1)->restore();

 

Совет 19. HasMany() — имеет много, а сколько именно?

В Eloquent отношении hasMany() вы можете отфильтровать записи, которые имеют X дочерних записей.

// Author -> hasMany(Book::class)
$authors = Author::has('books', '>', 5)->get();

 

Совет 20. Валидация изображения

При проверке загруженных изображений можно указать требуемые размеры:

'photo' => 'dimensions:max_width=4096,max_height=4096'

 

Продолжение: Советы по Laravel. Часть 2.

 

Автор: Povilas Korop
Перевод: Алексей Широков

Наш Телеграм-канал — следите за новостями о Laravel.