20 тайных сокровищ Laravel

20 тайных сокровищ Laravel

Фреймворк Laravel полон тайн, которые мне повезло раскопать во время работы над различными задачами. Некоторые из них были более-менее известны, другие были недокументированными функциями или хаками. Сейчас я поделюсь с вами моими находками.

01: Привязка родительских меток времени

Как понятно из заголовка — вы можете привязать родительскую метку времени при обновлении дочерней модели. Например, есть две сущности Post и Comment, имеющие родительские и дочерние отношения. И когда обновляется модель Comment, вы можете автоматически обновить метку времени у updated_at родительской модели. Eloquent делает это очень просто — добавьте свойство touch, содержащее имена отношений к дочерней модели.

<?php
  namespace App;
  use Illuminate\Database\Eloquent\Model;
  class Comment extends Model
  {
      /**
      * All of the relationships to be touched.
      *
      * @var array
      */
      protected $touches = ['post'];
      /**
      * Get the post that the comment belongs to.
      */
      public function post()
      {
          return $this->belongsTo('App\Post');
      }
  }

 

02: «Жадная загрузка (Eager Loading)» с определенными столбцами

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

$users = App\Book::with('author:id,name')->get();

 

03: Аутентификация пользователя для одного запроса

Вы можете использовать Auth::once(), чтобы аутентифицировать пользователя для одного запроса. Сеансы cookies использоваться не будут. Очень удобно для построения API без сохранения состояния.

if (Auth::once($credentials)) {
    //
}

 

04: Редирект в контроллер с параметрами

Вы можете использовать redirect() не только на конкретный url или маршрут, но и на метод конкретного контроллера с нужными параметрами.

return redirect()->action('SomeController@method',    ['param' => $value]);

 

05: Как избежать ошибок в отношениях, используя withDefault()

При вызове отсутствующего отношения, вы получите фатальную ошибку, например $post->user->name. Чтобы избежать этого используйте withDefault().

/**  * Get the author of the post.  */
public function user()
{   
return $this->belongsTo('App\User')->withDefault();
}

 

06: Двухуровневая $loop в шаблонах Blade

При работе с циклами в Blade вы можете использовать переменную $loop даже во вложенном цикле для показа родительских переменных.

@foreach ($users as $user)   
@foreach ($user->posts as $post)       
    @if ($loop->parent->first)           
      This is first iteration of the parent loop.       
  @endif   
@endforeach
@endforeach

 

07: Изменение результат запроса

При выполнение запроса Eloquent вы можете изменить результат при помощи map().

$users = User::where('role_id', 1)->get()->map(function (User $user) {
    $user->some_column = some_function($user);
    return $user;
});

 

08: dd() очень просто

Вместо dd($result) вы можете сделать $test->dd() прямо в конце вашего Eloquent запроса.

// Вместо
$users = User::where('name', 'Taylor')->get();
dd($users);
// Сделайте
$users = User::where('name', 'Taylor')->get()->dd();

 

09: Используйте hasMany для saveMany

Если у вас есть отношение hasMany() и, из родительского объекта, вы хотите сохранить дочерние объекты, то вы можете это сделать с помощью saveMany().

$post = Post::find(1);
$post->comments()->saveMany([
    new Comment(['message' => 'First comment']),
    new Comment(['message' => 'Second comment']),
]);

 

10: Указывайте столбцы в Model::all()

При использовании User::all() вы можете указать, какие столбцы нужно получить.

$users = User::all(['id', 'name', 'email']);

 

11: @auth в Blade

Вместо оператора if для проверки аутентифицирован ли пользователь, вы можете использовать директиву @auth.

// Обычный способ
   @if(auth()->user())   
       // Пользователь аутентифицирован
   @endif

   // Краткий способ
   @auth   
       // Пользователь аутентифицирован
   @endauth

 

12: Превью писем

Вы можете просматривать письма, как обычный шаблон Blade, не отправляя их.

Route::get('/mailable', function () {
       $invoice = App\Invoice::find(1);
       return new App\Mail\InvoicePaid($invoice);
   });

 

13: hasMany с особыми проверками

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

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

 

14: Множественное восстановление «Мягкого удаления (Soft Deletes)»

Если вы используете мягкое удаление, то вы можете восстановить несколько записей одновременно.

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

 

15: Миграционные столбцы с часовыми поясами

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

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

 

16: Существует ли View?

Вы можете проверить существует ли View или нет.

if (view()->exists('custom.page')) {
    // Load the view
}

 

17: Группа маршрутов внутри группы

В маршрутах вы можете создавать группу с группой маршрутов и даже прикреплять к ним нужные middleware.

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');   
    });
});

 

18: Методы проверки дат в 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();

 

19: Применение orderBy() к отношениям

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

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

 

20: Беззнаковое целое

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

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

 

Автор: Jebran Ali
Перевод: Demiurge Ash