Вам бонус- начислено 1 монета за дневную активность. Сейчас у вас 1 монета

73 совета и хитростей Laravel и Eloquent в 2021 году

Лекция



Привет, Вы узнаете о том , что такое laravel, Разберем основные их виды и особенности использования. Еще будет много подробных примеров и описаний. Для того чтобы лучше понимать что такое laravel, eloquent , настоятельно рекомендую прочитать все из категории Фреймворки. Famworks ( программная платформа).

73 совета и хитростей Laravel и Eloquent   в 2021 году

1. Инкременты и декременты

Вместо:

$article = Article::find($article_id);
$article->read_count++;
$article->save();

Можно сделать:

$article = Article::find($article_id);
$article->increment('read_count');

Также будет работать:

Article::find($article_id)->increment('read_count');
Article::find($article_id)->increment('read_count', 10); // +10
Product::find($produce_id)->decrement('stock'); // -1

2. X или Y методы

Eloquent имеет несколько функций, которые объединяют два метода, например “сделай X, иначе сделай Y”.

Пример 1 – findOrFail():

Вместо:

$user = User::find($id);
if (!$user) { abort (404); }

Используйте:

$user = User::findOrFail($id);

Пример 2 – firstOrCreate():

Вместо :

$user = User::where('email', $email)->first();
if (!$user) {
  User::create([
    'email' => $email
  ]);
}

Используйте:

$user = User::firstOrCreate(['email' => $email]);

3. Метод boot() модели

В модели Eloquent есть волшебный метод boot(), где вы можете переопределить поведение по умолчанию:

class User extends Model
{
    public static function boot()
    {
        parent::boot();
        static::updating(function($model)
        {
            // выполнить какую-нибудь логику
            // переопределить какое-нибудь свойство, например $model->something = transform($something);
        });
    }
}

Вероятно, одним из наиболее популярных примеров является установка значения некоторого поля в момент создания экземпляра модели. Предположим, вы хотите сгенерировать UUID поле в этот момент.

public static function boot()
{
  parent::boot();
  self::creating(function ($model) {
    $model->uuid = (string)Uuid::generate();
  });
}

4. Отношения с условием и сортировкой

Обычный способ определения отношений:

public function users() {
    return $this->hasMany('App\User');    
}

Но знаете ли вы, что сюда мы можем добавить where или orderBy? Например, если вам нужно специальное отношения для некоторых типов пользователей, упорядоченное по электронной почте, вы можете сделать так:

public function approvedUsers() {
    return $this->hasMany('App\User')->where('approved', 1)->orderBy('email');
}

5. Свойства модели: timestamps, appends и тд.

Существует несколько «параметров» Eloquent модели в виде свойств класса. Самые популярные из них, вероятно, следующие:

class User extends Model {
    protected $table = 'users';
    protected $fillable = ['email', 'password']; // какие поля могут быть заполнены выполняя User::create()
    protected $dates = ['created_at', 'deleted_at']; // какие поля будут типа Carbon
    protected $appends = ['field1', 'field2']; // доп значения возвращаемые в JSON
}

Но подождите, есть еще:

protected $primaryKey = 'uuid'; //  не должно быть "id"
public $incrementing = false; // и не должно быть автоинкрементом
protected $perPage = 25; // Да, вы можете переопределить число записей пагинации (по умолчанию 15)
const CREATED_AT = 'created_at';
const UPDATED_AT = 'updated_at'; // Да, даже эти названия также могут быть переопределены
public $timestamps = false; // или не использоваться совсем

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

6. Поиск нескольких записей

Всем известен метод find(), правда?

$user = User::find(1);

Удивительно, как мало кто знает о том, что он может принимать несколько ID`шников в виде массива:

$users = User::find([1,2,3]);

7. WhereX

Есть элегантный способ превратить:

$users = User::where('approved', 1)->get();

В:

$users = User::whereApproved(1)->get(); 

Да, вы можете изменить имя любого поля и добавить его как суффикс в “where”, и оно будет работать как по волшебству. Также в Eloquent ORM есть предустановленные методы, связанные с датой и временем:

User::whereDate('created_at', date('Y-m-d'));
User::whereDay('created_at', date('d'));
User::whereMonth('created_at', date('m'));
User::whereYear('created_at', date('Y'));

8. Сортировка с отношениями

Немного больше чем "трюк". Что делать если у вас есть темы форума, но вы хотите их отсортировать, по их последним постам? Довольно популярное требование в форумах с последними обновленными темами вверху, правда?

Сначала опишите отдельную связь для последнего поста в теме:

public function latestPost()
{
    return $this->hasOne(\App\Post::class)->latest();
}

И после, в вашем контроллере, вы можете выполнить такую "магию":

$users = Topic::with('latestPost')->get()->sortByDesc('latestPost.created_at');

9. Eloquent::when() – без “if-else”

Многие из нас пишут условные запросы с «if-else», что-то вроде этого:

if (request('filter_by') == 'likes') {
    $query->where('likes', '>', request('likes_amount', 0));
}
if (request('filter_by') == 'date') {
    $query->orderBy('created_at', request('ordering_rule', 'desc'));
}

Но лучший способ — использовать when():

$query = Author::query();
$query->when(request('filter_by') == 'likes', function ($q) {
    return $q->where('likes', '>', request('likes_amount', 0));
});
$query->when(request('filter_by') == 'date', function ($q) {
    return $q->orderBy('created_at', request('ordering_rule', 'desc'));
});

Этот пример может показаться не короче или элегантнее, но правильнее будет пробрасывать параметры:

$query = User::query();
$query->when(request('role', false), function ($q, $role) { 
    return $q->where('role_id', $role);
});
$authors = $query->get();

10. Модель по умолчанию для BelongsTo отношений

Допустим, у вас есть пост, принадлежащий автору, и Blade код:

{{ $post->author->name }}

Но что, если автор удален или не установлен по какой-либо причине? Вы получите ошибку на подобии "property of non-object".

Конечно, вы можете предотвратить это следующим образом:

{{ $post->author->name ?? '' }}

Но вы можете сделать это на уровне Eloquent отношений:

public function author()
{
    return $this->belongsTo('App\Author')->withDefault();
}

В этом примере отношение author() возвращает пустую модель App\Author, если автор не прикреплен к посту.

Кроме того, для модели по-умолчанию можно присвоить значениям свойств по-умолчанию.

public function author()
{
    return $this->belongsTo('App\Author')->withDefault([
        'name' => 'Guest Author'
    ]);
}

11. Сортировка по преобразователю

Представьте что у вас есть такой преобразователь:

function getFullNameAttribute()
{
  return $this->attributes['first_name'] . ' ' . $this->attributes['last_name'];
}

Вам нужно отсортировать записи по полю full_name? Такое решение работать не будет:

$clients = Client::orderBy('full_name')->get(); // не работает

Решение довольно простое. Нам нужно отсортировать записи после того как мы их получили.

$clients = Client::get()->sortBy('full_name'); // работает!

Обратите внимание что название функций отличается — это не orderBy, это sortBy.

12. Сортировка по умолчанию

Что делать, если вы хотите, чтобы User::all() всегда сортировался по полю name? Вы можете назначить глобальную заготовку (Global Scope). Вернемся к методу boot(), о котором мы уже говорили выше.

protected static function boot()
{
    parent::boot();

    // Сортировка по полю name в алфавитном порядке
    static::addGlobalScope('order', function (Builder $builder) {
        $builder->orderBy('name', 'asc');
    });
}

Больше информации о Query Scopes здесь.

13. Сырые выражения

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

// whereRaw
$orders = DB::table('orders')
    ->whereRaw('price > IF(state = "TX", ?, 100)', [200])
    ->get();

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

// orderByRaw
User::where('created_at', '>', '2016-01-01')
  ->orderByRaw('(updated_at - created_at) desc')
  ->get();

14. Cделать копию записи в базе данных

Без глубоких объяснений, вот лучший способ сделать копию записи в базе данных:

$task = Tasks::find(1);
$newTask = $task->replicate();
$newTask->save();

15. Chunk() метод для больших таблиц

Не совсем о Eloquent, это скорее о коллекциях, но все же мощный метод — для обработки больших наборов данных. Метод позволяет разбить набор данных на кусочки.

Вместо:

$users = User::all();
foreach ($users as $user) {
    // ...

Можно сделать:

User::chunk(100, function ($users) {
    foreach ($users as $user) {
        // ...
    }
});

16. Создание дополнительных файлов при создании модели

Мы все знаем Artisan команду:

php artisan make:model Company

Но знаете ли вы, что есть три полезных флага для создания дополнительных файлов модели?

php artisan make:model Company -mcr
  • -m создаст файл миграции (migration)
  • -c создаст контроллер (controller)
  • -r указывает на то что контроллер должен быть ресурсом (resourceful)

17. Перезапись updated_at во время сохранения

Знаете ли вы, что метод ->save() может принимать параметры? Как результат мы можем “игнорировать” updated_at функциональность, которая по умолчанию должна была установить текущую метку времени.

Посмотрите на следующий пример:

$product = Product::find($id);
$product->updated_at = '2019-01-01 10:00:00';
$product->save(['timestamps' => false]);

Здесь переписыавается updated_at предустановленным значением.

18. Что является результатом метода update()?

Вы когда-нибудь задумывались над тем, что этот код возвращает?

$result = $products->whereNull('category_id')->update(['category_id' => 2]);

Я имею в виду, что обновление выполняется в базе данных, но что будет содержать этот $result?

Ответ: затронутые строки. Поэтому, если вам нужно проверить, сколько строк было затронуто, вам не нужно ничего вызывать — метод update() вернет это число для вас.

19. Преобразуем скобки в Eloquent запрос

Что делать если у вас есть AND и OR в вашем SQL запросе, как здесь:

... WHERE (gender = 'Male' and age >= 18) or (gender = 'Female' and age >= 65)

Как преобразовать этот запрос в Eloquent запрос? Это неправильный способ:

$q->where('gender', 'Male');
$q->orWhere('age', '>=', 18);
$q->where('gender', 'Female');
$q->orWhere('age', '>=', 65);

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

$q->where(function ($query) {
    $query->where('gender', 'Male')
        ->where('age', '>=', 18);
})->orWhere(function($query) {
    $query->where('gender', 'Female')
        ->where('age', '>=', 65); 
})

20. orWhere с несколькими параметрами

Вы можете передать массив параметров в orWhere().
“Обычный” способ:

$q->where('a', 1);
$q->orWhere('b', 2);
$q->orWhere('c', 3);

Вы можете сделать так:

$q->where('a', 1);
$q->orWhere(['b' => 2, 'c' => 3]);

31. Eloquent Queries

Laravel предлагает одну из самых мощных реализаций Active-Record в мире PHP. Предположим, что у вас есть таблица заказов, а также модель Order Eloquent:

class Order extends Eloquent {}

Мы можем легко выполнить любое количество запросов к базе данных, используя простой, элегантный PHP. Не нужно бросать грязный SQL по комнате. Давайте возьмем все заказы.

$orders = Order::all();

Готово. Или, может быть, эти заказы должны быть возвращены в порядке, согласно дате выпуска. Это легко:

$orders = Order::orderBy('release_date', 'desc')->get();

Что делать, если вместо того, чтобы извлекать запись, нам нужно сохранить новый заказ в базе данных. Конечно, мы можем это сделать.

$order = new Order;
$order->title = 'Xbox One';
$order->save();

Законченный! С Laravel задачи, которые были громоздкими для исполнения, смехотворно просты.


32. Гибкая маршрутизация

Laravel уникальна тем, что его можно использовать несколькими способами. Предпочитаете более простую, более синтатроподобную систему маршрутизации? Конечно, Laravel может предложить это довольно легко, используя закрытие.

Route::get('orders', function()
{
    return View::make('orders.index')
        ->with('orders', Order::all());
});

Это может оказаться полезным для небольших проектов и API, но, скорее всего, вам понадобятся контроллеры для большинства ваших проектов. Это нормально; Ларавел тоже может это сделать!

Route::get('orders', 'OrdersController@index');

Готово. Обратите внимание, как Laravel растет с вашими потребностями? Этот уровень размещения является тем, что делает структуру столь же популярной, как и сегодня.


33. Легкие отношения

Что мы делаем в случаях, когда мы должны определять отношения? Например, задача, безусловно, принадлежит пользователю. Как мы можем представить это в Laravel? Ну, полагая, что необходимые таблицы базы данных настроены, нам нужно только настроить соответствующие модели Eloquent.

class Task extends Eloquent {
    public function user()
    {
        return $this->belongsTo('User');
    }
}
class User extends Eloquent {
    public function tasks()
    {
        return $this->hasMany('Task');
    }
}

И с этим мы закончили! Давайте возьмем все задачи для пользователя с идентификатором 1. Мы можем сделать это в двух строках кода.

$user = User::find(1);
$tasks = $user->tasks;

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

$task = Task::find(1);
$user = $task->user;


34. Связывание формы модели

Часто бывает полезно связать форму с моделью. Очевидным примером этого является то, что вы хотите отредактировать некоторую запись в своей базе данных. Об этом говорит сайт https://intellect.icu . При привязке модели модели мы можем мгновенно заполнить поля формы значениями из соответствующей строки таблицы.

{{ Form::model($order) }}
    

{{ Form::label('title', 'Title:') }} {{ Form::text('title') }}

{{ Form::label('description', 'Description:') }} {{ Form::textarea('description') }}

{{ Form::close() }}

Поскольку форма теперь связана с конкретным экземпляром заказа, входы будут отображать правильные значения из таблицы. Просто!


35. Запросы базы данных кэша

Слишком много запросов к базе данных, и очень быстро ваше приложение может стать как меласса. К счастью, Laravel предлагает простой механизм кэширования этих запросов, используя только один вызов метода.

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

$questions = Question::remember(60)->get();

Это оно! Теперь, в течение следующего часа запросов страниц, этот запрос останется кешированным, и база данных не будет затронута.


36. Просмотр композиторов

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

Слишком простое управление контроллерами, Laravel предлагает просмотр композиторов для управления такими вещами.

View::composer('layouts.nav', function($view)
{
    $view->with('tags', ['tag1', 'tag2']);
});

С помощью этого фрагмента кода, в любое время, когда загружается представление layouts nav.blade.php, он будет иметь доступ к переменной $ tags, равной предоставленному массиву.


37. Простая аутентификация

Laravel использует простой подход к аутентификации. Просто передайте массив учетных данных, которые, скорее всего, получены из формы входа, в Auth:: purchase (). Если предоставленные значения соответствуют тому, что хранится в таблице пользователей, пользователь будет немедленно войти в систему.

$user = [
    'email' => 'email',
    'password' => 'password'
];
if (Auth::attempt($user))
{
    // user is now logged in!
    // Access user object with Auth::user()
}

Что делать, если нам нужно вывести пользователя из системы - возможно, когда удаляется URI выхода из системы? Это тоже легко.

Route::get('logout', function()
{
    Auth::logout();
    return Redirect::home();
});


38. Ресурсы

Работать RESTfully в Laravel никогда не было проще. Чтобы зарегистрировать находчивый контроллер, просто вызовите Route:: resource (), например:

Route::resource('orders', 'OrdersController');

С помощью этого кода Laravel зарегистрирует восемь маршрутов.

GET ordersnGET заказы: ordernGET заказы createnGET заказы: заказать editnPOST ordersnPUT заказы: ordernPATCH заказы: ordernDELETE заказы: ordern

Кроме того, сопутствующий контроллер может быть сгенерирован из командной строки:

php artisan controller:make OrdersController

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

Теперь у нас есть необходимая возможность легко создавать приложения RESTful и API.


39. Blade Templating

Хотя, да, PHP по своей природе является языком шаблонов, он не превратился, чтобы стать слишком хорошим. Все в порядке; Laravel предлагает свой двигатель Blade, чтобы заполнить пробел. Просто назовите свои представления с расширением.blade.php, и они будут автоматически проанализированы соответственно. Теперь мы можем делать такие вещи, как:

@if ($orders->count())
    
  • @foreach($orders as $order)
  • {{ $order->title }}
  • @endforeach

@endif


40. Тестирование

Поскольку Laravel использует Composer, мы мгновенно получаем поддержку PHPUnit в каркасе из коробки. Установите фреймворк и запустите phpunit из командной строки, чтобы проверить его.

Еще лучше, однако, Laravel предлагает ряд тестовых помощников для наиболее распространенных типов функциональных тестов.

Давайте проверим, что домашняя страница возвращает код состояния 200.

public function test_home_page()
{
    $this->call('GET', '/');
    $this->assertResponseOk();
}

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

public function test_contact_page_redirects_user_to_home_page()
{
    $postData = [
        'name' => 'Joe Example',
        'email' => 'email-address',
        'message' => 'I love your website'
    ];
    $this->call('POST', '/contact', $postData);
    $this->assertRedirectedToRoute('home', null, ['flash_message']);
}


41. Удаленный компонент

В рамках Laravel 4.1, который планируется выпустить в ноябре 2013 года, вы можете легко написать команду Artisan SSH на свой сервер и выполнить любое количество действий. Это так же просто, как использование фасада SSH:

SSH::into('production')->run([
    'cd /var/www',
    'git pull origin master'
]);

Передайте массив команд методу run (), и Laravel справится с остальными! Теперь, поскольку имеет смысл выполнять такой код как команду Artisan, вам нужно только запустить команду php artisan: сделать DeployCommand и вставить соответствующий код в метод пожарной команды, чтобы быстро создать выделенную команду развертывания!


42. События

Laravel предлагает элегантную реализацию шаблона наблюдателя, который вы можете использовать во всех приложениях. Слушайте местные события, такие как illuminate.query, или даже огонь и поймайте свои собственные.

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

Event::listen('user.signUp', function()
{
    // do whatever needs to happen
    // when a new user signs up
});

Как и большинство вещей в Laravel, если вы предпочитаете ссылаться на имя класса, а не на закрытие, вы можете свободно это делать. Затем Laravel разрешит его из контейнера IoC.

Event::listen('user.signUp', 'UserEventHandler');


43. Просмотр всех маршрутов

По мере расширения приложения может быть сложно просмотреть, какие маршруты были зарегистрированы. Это особенно верно, если надлежащий уход не был предоставлен вашему файлу route.php (т. Е. Оскорбительная неявная маршрутизация).

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

php artisan routes


44. Очереди

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

Почему заставить пользователя ждать этих действий, когда мы можем вместо этого бросить их в фоновом режиме?

Queue::push('SignUpService', compact('user'));

Возможно, самая захватывающая часть - это то, что Laravel блестяще предлагает поддержку Iron.io push queues. Это означает, что даже без унции опыта «работника» или «демона» мы все еще можем использовать возможности очередей. Просто зарегистрируйте конечную точку URL-адреса, используя полезную команду php artisan queue для Laravel: подписать команду, а Iron.io будет проверять ваш выбранный URL каждый раз, когда задание добавляется в очередь.

Простые шаги для повышения производительности!


45. Простая проверка

Когда требуется проверка (и когда это не так), Ларавел снова приходит на помощь! Использование класса Validator столь же интуитивно, как и может быть. Просто передайте объект под проверку, а также список правил для метода make, и Laravel позаботится обо всем остальном.

$order = [
    'title' => 'Wii U',
    'description' => 'Game console from Nintendo'
];
$rules = [
    'title' => 'required',
    'description' => 'required'
];
$validator = Validator::make($order, $rules);
if ($validator->fails())
{
    var_dump($validator->messages()); // validation errors array
}

Как правило, этот тип кода будет храниться в вашей модели, что означает, что проверка, например, порядка может быть уменьшена до одного вызова метода:

$order->isValid();


46. Тинкер Тинкер

Особенно, когда вы впервые изучаете Laravel, полезно поработать с ядром. Команда Larsvel по команде мастеров Artisan может помочь в этом.

Как часть версии 4.1, команда tinker еще более мощная, теперь она использует популярный компонент Boris.n
$ php artisan tinker
> $order = Order::find(1);
> var_dump($order->toArray());
> array(...)


47. Миграции

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

Чтобы подготовить схему для новой таблицы пользователей, мы можем запустить:

php artisan migrate:make create_users_table

Это создаст файл миграции, который вы затем можете заполнить в соответствии с вашими потребностями. После завершения миграции php artisan создаст таблицу. Это оно! Необходимо отменить это создание? Легко! Перенастройка php-artisan: откат.

Вот пример схемы для часто задаваемых вопросов.

public function up()
{
    Schema::create('faqs', function(Blueprint $table) {
        $table->integer('id', true);
        $table->text('question');
        $table->text('answer');
        $table->timestamps();
    });
}
public function down()
{
    Schema::drop('faqs');
}

Обратите внимание, как метод drop () выполняет инверсию up (). Это позволяет нам откатить миграцию. Разве это не намного проще, чем спорить о связке SQL?


48. Генераторы

В то время как Laravel предлагает ряд полезных генераторов, невероятно полезный сторонний пакет, называемый «Laravel 4 Generators», делает это еще больше. Создавайте ресурсы, файлы семян, сводные таблицы и миграции с помощью схемы!

В этом предыдущем совете мы были вынуждены вручную написать схему. Однако с включенным пакетом генераторов мы можем:

php artisan generate:migration create_users_table --fields="username:string, password:string"

Генератор позаботится обо всем остальном. Это означает, что с помощью двух команд вы можете подготовить и построить новую таблицу базы данных.

Laravel 4 Генераторы могут быть установлены через Composer.n

49. Команды

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

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

php artisan command:make MyCustomCommand

Эта команда создаст необходимый шаблон для вашей новой пользовательской команды. Затем, из недавно созданных команд приложения MyCustomCommand.php, заполните соответствующее имя и описание:

protected $name = 'command:name';
protected $description = 'Command description.';

И, наконец, в методе класса fire () класса класса выполните любое действие, которое вам нужно. Как только закончите, единственный оставшийся шаг - зарегистрировать команду с Artisan, начиная с приложения Artisan.php.

Artisan::add(new MyCustomCommand);

Хочешь верь, хочешь нет; это оно! Теперь вы можете вызывать свою пользовательскую команду с терминала.


50. Mock Facades

Laravel сильно использует шаблон фасада. Это позволяет использовать чистый статический синтаксис, который вам, несомненно, понравится (Route:: get (), Config:: get () и т. Д.), Но при этом позволяет полностью тестировать за кулисами.

Поскольку эти «базовые классы» разрешены из контейнера IoC, мы можем легко обменять эти базовые экземпляры с помощью mocks для целей тестирования. Это позволяет осуществлять такой контроль, как:

Validator::shouldReceive('make')->once();

Да, мы вызываем shouldReceive прямо от фасада. За кулисами Laravel использует превосходную структуру Mockery для этого. Это означает, что вы можете свободно использовать эти фасады в своем коде, сохраняя при этом 100% тестируемость.


51. Form Helpers

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

{{ Form::open() }}
    {{ Form::text('name') }}
    {{ Form::textarea('bio') }}
    {{ Form::selectYear('dob', date('Y') - 80, date('Y')) }}
{{ Form::close() }}

Как насчет задач, таких как запоминание ввода из предыдущего представления формы? Laravel может делать все это автоматически!


52. Контейнер IoC

В основе Laravel лежит его мощный контейнер IoC, который является инструментом, который помогает управлять зависимостями классов. Примечательно, что контейнер имеет возможность автоматически разрешать классы без конфигурации!

Просто введите типы зависимостей внутри конструктора и, после создания экземпляра, Laravel будет использовать PHP Reflection API для интеллектуального считывания ключей типа и попытаться ввести их для вас.

public function __construct(MyDependency $thing)
{
    $this->thing = $thing;
}

Пока вы запрашиваете класс из контейнера IoC, это разрешение будет выполняться автоматически.

$myClass = App::make('MyClass');

Важно отметить, что контроллеры всегда разрешены из контейнера IoC. Таким образом, вы можете бесплатно отключить зависимости вашего контроллера, и Laravel впоследствии сделает все возможное, чтобы ввести их для вас. N

53. Среды

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

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

К счастью, Laravel упрощает нашу работу. Посмотрите на bootstrap start.php в своем приложении.

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

$env = $app->detectEnvironment(array(
    'local' => array('localhost'),
    'production' => array('*.com')
));

Хотя это будет работать, вообще говоря, предпочтительнее использовать переменные окружения для такого рода вещей. Не беспокойся; это все еще выполнимо в Laravel! Вместо этого просто возвращайте функцию из метода detectEnvironment объекта контейнера.

$env = $app->detectEnvironment(function()
{
    return getenv('ENV_NAME') ?: 'local';
});

Теперь, если не задана переменная окружения (которую вы будете делать для производства), среда будет по умолчанию локальной.


54. Простая конфигурация

Laravel, опять же, использует простой подход к настройке. Создайте папку в конфигурации приложения, которая соответствует вашей желаемой среде, и любые файлы конфигурации в ней будут иметь приоритет, если имя среды совпадает. Таким образом, чтобы, скажем, установить другой ключ API для биллинга для разработки, вы можете:

 app/config/development/billing.php
return [
    'api_key' => 'your-development-mode-api-key'
];

Конфигурация switcharoo является автоматической. Просто введите Config:: get ('billing.api_key'), и Laravel правильно определит, какой файл читать.


55. Поверхностное обучение Дальнейшее обучение

Когда дело доходит до образования, сообщество Laravel, несмотря на относительно молодой возраст, является бесконечным. Менее чем через год было выпущено полдюжины разных книг, связанных со всеми вопросами развития Ларавеля.

Узнайте все от основ, до тестирования, создания и поддержки больших приложений!


Это не пересказ лучших практик вроде SOLID, паттернов и пр. с адаптацией под Laravel. Здесь собраны именно практики, которые игнорируются в реальных Laravel проектах. Также, рекомендую ознакомитсья с хорошими практиками в контексте PHP. Смотрите также обсуждение хороших практик Laravel.

56 Принцип единственной ответственности (Single responsibility principle)

Каждый класс и метод должны выполнять лишь одну функцию.

Плохо:


public function getFullNameAttribute()
{
    if (auth()->user() && auth()->user()->hasRole('client') && auth()->user()->isVerified()) {
        return 'Mr. ' . $this->first_name . ' ' . $this->middle_name . ' ' . $this->last_name;
    } else {
        return $this->first_name  . '. ' . $this->last_name;
    }
}

Хорошо:


public function getFullNameAttribute()
{
    return $this->isVerifiedClient() ? $this->getFullNameLong() : $this->getFullNameShort();
}

public function isVerifiedClient()
{
    return auth()->user() && auth()->user()->hasRole('client') && auth()->user()->isVerified();
}

public function getFullNameLong()
{
    return 'Mr. ' . $this->first_name . ' ' . $this->middle_name . ' ' . $this->last_name;
}

public function getFullNameShort()
{
    return $this->first_name  . '. ' . $this->last_name;
}

57 Тонкие контроллеры, толстые модели

По своей сути, это лишь один из частных случаев принципа единой ответственности. Выносите работу с данными в модели при работе с Eloquent или в репозитории при работе с Query Builder или "сырыми" SQL запросами.

Плохо:


public function index()
{
    $clients = Client::verified()
        ->with(['orders' => function ($q) {
            $q->where('created_at', '>', Carbon::today()->subWeek());
        }])
        ->get();

    return view('index', ['clients' => $clients]);
}

Хорошо:


public function index()
{
    return view('index', ['clients' => $this->client->getWithNewOrders()]);
}

class Client extends Model
{
    public function getWithNewOrders()
    {
        return $this->verified()
            ->with(['orders' => function ($q) {
                $q->where('created_at', '>', Carbon::today()->subWeek());
            }])
            ->get();
    }
}

58 Валидация

Следуя принципам тонкого контроллера и SRP, выносите валидацию из контроллера в Request классы.

Плохо:


public function store(Request $request)
{
    $request->validate([
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
        'publish_at' => 'nullable|date',
    ]);

    ....
}

Хорошо:


public function store(PostRequest $request)
{    
    ....
}

class PostRequest extends Request
{
    public function rules()
    {
        return [
            'title' => 'required|unique:posts|max:255',
            'body' => 'required',
            'publish_at' => 'nullable|date',
        ];
    }
}

59 Бизнес логика в сервис-классах

Контроллер должен выполнять только свои прямые обязанности, поэтому выносите всю бизнес логику в отдельные классы и сервис классы.

Плохо:


public function store(Request $request)
{
    if ($request->hasFile('image')) {
        $request->file('image')->move(public_path('images') . 'temp');
    }
    
    ....
}

Хорошо:


public function store(Request $request)
{
    $this->articleService->handleUploadedImage($request->file('image'));

    ....
}

class ArticleService
{
    public function handleUploadedImage($image)
    {
        if (!is_null($image)) {
            $image->move(public_path('images') . 'temp');
        }
    }
}

60 Не повторяйся (DRY)

Этот принцип призывает вас переиспользовать код везде, где это возможно. Если вы следуете принципу SRP, вы уже избегаете повторений, но Laravel позволяет вам также переиспользовать представления, части Eloquent запросов и т.д.

Плохо:


public function getActive()
{
    return $this->where('verified', 1)->whereNotNull('deleted_at')->get();
}

public function getArticles()
{
    return $this->whereHas('user', function ($q) {
            $q->where('verified', 1)->whereNotNull('deleted_at');
        })->get();
}

Хорошо:


public function scopeActive($q)
{
    return $q->where('verified', 1)->whereNotNull('deleted_at');
}

public function getActive()
{
    return $this->active()->get();
}

public function getArticles()
{
    return $this->whereHas('user', function ($q) {
            $q->active();
        })->get();
}

61 Предпочитайте Eloquent конструктору запросов (query builder) и сырым запросам в БД. Предпочитайте работу с коллекциями работе с массивами

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

Плохо:


SELECT *
FROM `articles`
WHERE EXISTS (SELECT *
              FROM `users`
              WHERE `articles`.`user_id` = `users`.`id`
              AND EXISTS (SELECT *
                          FROM `profiles`
                          WHERE `profiles`.`user_id` = `users`.`id`) 
              AND `users`.`deleted_at` IS NULL)
AND `verified` = '1'
AND `active` = '1'
ORDER BY `created_at` DESC

Хорошо:


Article::has('user.profile')->verified()->latest()->get();

62 Используйте массовое заполнение (mass assignment)

Плохо:


$article = new Article;
$article->title = $request->title;
$article->content = $request->content;
$article->verified = $request->verified;
// Привязать статью к категории.
$article->category_id = $category->id;
$article->save();

Хорошо:


$category->article()->create($request->all());

63 Не выполняйте запросы в представлениях и используйте нетерпеливую загрузку (проблема N + 1)

Плохо (будет выполнен 101 запрос в БД для 100 пользователей):


@foreach (User::all() as $user)
    {{ $user->profile->name }}
@endforeach

Хорошо (будет выполнено 2 запроса в БД для 100 пользователей):


$users = User::with('profile')->get();

...

@foreach ($users as $user)
    {{ $user->profile->name }}
@endforeach

64 Комментируйте код, предпочитайте читаемые имена методов комментариям

Плохо:


if (count((array) $builder->getQuery()->joins) > 0)

Лучше:


// Determine if there are any joins.
if (count((array) $builder->getQuery()->joins) > 0)

Хорошо:


if ($this->hasJoins())

65 Выносите JS и CSS из шаблонов Blade и HTML из PHP кода

Плохо:


let article = `{{ json_encode($article) }}`;

Лучше:




Или{{ $article->name }}

В Javascript файле:


let article = $('#article').val();

Еще лучше использовать специализированный пакет для передачи данных из бэкенда во фронтенд.

66 Конфиги, языковые файлы и константы вместо текста в коде

Непосредственно в коде не должно быть никакого текста.

Плохо:


public function isNormal()
{
    return $article->type === 'normal';
}

return back()->with('message', 'Ваша статья была успешно добавлена');

Хорошо:


public function isNormal()
{
    return $article->type === Article::TYPE_NORMAL;
}

return back()->with('message', __('app.article_added'));

67 Используйте инструменты и практики принятые сообществом

Laravel имеет встроенные инструменты для решения часто встречаемых задач. Предпочитайте пользоваться ими использованию сторонних пакетов и инструментов. Laravel разработчику, пришедшему в проект после вас, придется изучать и работать с новым для него инструментом, со всеми вытекающими последствиями. Получить помощь от сообщества будет также гораздо труднее. Не заставляйте клиента или работодателя платить за ваши велосипеды.

Задача Стандартные инструмент Нестандартные инструмент
Авторизация Политики Entrust, Sentinel и др. пакеты, собственное решение
Работа с JS, CSS и пр. Laravel Mix Grunt, Gulp, сторонние пакеты
Среда разработки Homestead Docker
Разворачивание приложений Laravel Forge Deployer и многие другие
Тестирование Phpunit, Mockery Phpspec
e2e тестирование Laravel Dusk Codeception
Работа с БД Eloquent SQL, построитель запросов, Doctrine
Шаблоны Blade Twig
Работа с данными Коллекции Laravel Массивы
Валидация форм Request классы Сторонние пакеты, валидация в контроллере
Аутентификация Встроенный функционал Сторонние пакеты, собственное решение
Аутентификация API Laravel Passport Сторонние пакеты, использующие JWT, OAuth
Создание API Встроенный функционал Dingo API и другие пакеты
Работа со структурой БД Миграции Работа с БД напрямую
Локализация Встроенный функционал Сторонние пакеты
Обмен данными в реальном времени Laravel Echo, Pusher Пакеты и работа с веб сокетами напрямую
Генерация тестовых данных Seeder классы, фабрики моделей, Faker Ручное заполнение и пакеты
Планирование задач Планировщик задач Laravel Скрипты и сторонние пакеты
БД MySQL, PostgreSQL, SQLite, SQL Server MongoDb

68 Соблюдайте соглашения сообщества об именовании

Следуйте стандартам PSR при написании кода.

Также, соблюдайте другие cоглашения об именовании:

Что Правило Принято Не принято
Контроллер ед. ч. ArticleController ArticlesController
Маршруты мн. ч. articles/1 article/1
Имена маршрутов snake_case users.show_active users.show-active, show-active-users
Модель ед. ч. User Users
Отношения hasOne и belongsTo ед. ч. articleComment articleComments, article_comment
Все остальные отношения мн. ч. articleComments articleComment, article_comments
Таблица мн. ч. article_comments article_comment, articleComments
Pivot таблица имена моделей в алфавитном порядке в ед. ч. article_user user_article, articles_users
Столбец в таблице snake_case без имени модели meta_title MetaTitle; article_meta_title
Свойство модели snake_case $model->created_at $model->createdAt
Внешний ключ имя модели ед. ч. и _id article_id ArticleId, id_article, articles_id
Первичный ключ - id custom_id
Миграция - 2017_01_01_000000_create_articles_table 2017_01_01_000000_articles
Метод camelCase getAll get_all
Метод в контроллере ресурсов таблица store saveArticle
Метод в тесте camelCase testGuestCannotSeeArticle test_guest_cannot_see_article
Переменные camelCase $articlesWithAuthor $articles_with_author
Коллекция описательное, мн. ч. $activeUsers = User::active()->get() $active, $data
Объект описательное, ед. ч. $activeUser = User::active()->first() $users, $obj
Индексы в конфиге и языковых файлах snake_case articles_enabled ArticlesEnabled; articles-enabled
Представление snake_case show_filtered.blade.php showFiltered.blade.php, show-filtered.blade.php
Конфигурационный файл snake_case google_calendar.php googleCalendar.php, google-calendar.php
Контракт (интерфейс) прилагательное или существительное Authenticatable AuthenticationInterface, IAuthentication
Трейт прилагательное Notifiable NotificationTrait

69 Короткий и читаемый синтаксис там, где это возможно

Плохо:


$request->session()->get('cart');
$request->input('name');

Хорошо:


session('cart');
$request->name;

Еще примеры:

Часто используемый синтаксис Более короткий и читаемый синтаксис
Session::get('cart') session('cart')
$request->session()->get('cart') session('cart')
Session::put('cart', $data) session(['cart' => $data])
$request->input('name'), Request::get('name') $request->name, request('name')
return Redirect::back() return back()
is_null($object->relation) ? null : $object->relation->id optional($object->relation)->id
return view('index')->with('title', $title)->with('client', $client) return view('index', compact('title', 'client'))
$request->has('value') ? $request->value : 'default'; $request->get('value', 'default')
Carbon::now(), Carbon::today() now(), today()
App::make('Class') app('Class')
->where('column', '=', 1) ->where('column', 1)
->orderBy('created_at', 'desc') ->latest()
->orderBy('age', 'desc') ->latest('age')
->orderBy('created_at', 'asc') ->oldest()
->select('id', 'name')->get() ->get(['id', 'name'])
->first()->name ->value('name')

70 Используйте IoC или фасады вместо new Class

Внедрение классов через синтаксис new Class создает сильное сопряжение между частями приложения и усложняет тестирование. Используйте контейнер или фасады.

Плохо:


$user = new User;
$user->create($request->all());

Хорошо:


public function __construct(User $user)
{
    $this->user = $user;
}

....

$this->user->create($request->all());

71 Не работайте с данными из файла .env напрямую

Передайте данные из .env файла в кофигурационный файл и используйте config() в приложении, чтобы использовать эти данными.

Плохо:


$apiKey = env('API_KEY');

Хорошо:


// config/api.php
'key' => env('API_KEY'),

// Используйте данные в приложении
$apiKey = config('api.key');

72 Храните даты в стандартном формате. Используйте читатели и преобразователи для преобразования формата

Плохо:


{{ Carbon::createFromFormat('Y-d-m H-i', $object->ordered_at)->toDateString() }}
{{ Carbon::createFromFormat('Y-d-m H-i', $object->ordered_at)->format('m-d') }}

Хорошо:


// Модель
protected $dates = ['ordered_at', 'created_at', 'updated_at']
// Читатель (accessor)
public function getSomeDateAttribute($date)
{
    return $date->format('m-d');
}

// Шаблон
{{ $object->ordered_at->toDateString() }}
{{ $object->ordered_at->some_date }}

73 Другие советы и практики

Не размещайте логику в маршрутах.

Старайтесь не использовать "сырой" PHP в шаблонах Blade.

74 Или с несколькими параметрами

«Нормальный» метод:

$q->where('a', 1); $q->orWhere('b', 2); $q->orWhere('c', 3); 

Вы можете передать массив параметров в orWhere().

Вы можете использовать так

 $q->where('a', 1); $q->orWhere(['b' => 2, 'c' => 3]); 

Анализ данных, представленных в статье про laravel, подтверждает эффективность применения современных технологий для обеспечения инновационного развития и улучшения качества жизни в различных сферах. Надеюсь, что теперь ты понял что такое laravel, eloquent и для чего все это нужно, а если не понял, или есть замечания, то не стесняйся, пиши или спрашивай в комментариях, с удовольствием отвечу. Для того чтобы глубже понять настоятельно рекомендую изучить всю информацию из категории Фреймворки. Famworks ( программная платформа)

Ответы на вопросы для самопроверки пишите в комментариях, мы проверим, или же задавайте свой вопрос по данной теме.

создано: 2019-01-31
обновлено: 2021-09-13
132265



Рейтиг 9 of 10. count vote: 2
Вы довольны ?:


Поделиться:

Найди готовое или заработай

С нашими удобными сервисами без комиссии*

Как это работает? | Узнать цену?

Найти исполнителя
$0 / весь год.
  • У вас есть задание, но нет времени его делать
  • Вы хотите найти профессионала для выплнения задания
  • Возможно примерение функции гаранта на сделку
  • Приорететная поддержка
  • идеально подходит для студентов, у которых нет времени для решения заданий
Готовое решение
$0 / весь год.
  • Вы можите продать(исполнителем) или купить(заказчиком) готовое решение
  • Вам предоставят готовое решение
  • Будет предоставлено в минимальные сроки т.к. задание уже готовое
  • Вы получите базовую гарантию 8 дней
  • Вы можете заработать на материалах
  • подходит как для студентов так и для преподавателей
Я исполнитель
$0 / весь год.
  • Вы профессионал своего дела
  • У вас есть опыт и желание зарабатывать
  • Вы хотите помочь в решении задач или написании работ
  • Возможно примерение функции гаранта на сделку
  • подходит для опытных студентов так и для преподавателей



Комментарии


Оставить комментарий
Если у вас есть какое-либо предложение, идея, благодарность или комментарий, не стесняйтесь писать. Мы очень ценим отзывы и рады услышать ваше мнение.
To reply

Фреймворки. Famworks ( программная платформа)

Термины: Фреймворки. Famworks ( программная платформа)