Pull to refresh

25 Laravel Tips and Tricks

Reading time 11 min
Views 83K
Original author: Jeffrey Way
Было время, достаточно недавно, когда PHP и его сообщество ненавидели. Главная шутка была про то, насколько ужасен PHP.

Да, к сожалению, сообщество и экосистема просто были ниже сообществ других современных языков по уровню. Казалось, что предназначение PHP было прожить большинство времени в форме беспорядочных тем для WordPress.

Но позже, на удивление, вещи начали меняться — и достаточно быстро. Как будто пока ведьма помешивала горшочек, из ниоткуда начали появляться новаторские проекты. Наверно, самый заметный проект был Composer: наиболее полный менеджер зависимостей для PHP (как Bundler для Ruby или NPM для Node.js). В прошлом PHP разработчики были вынуждены совладать с PEAR (что было страшным сном, на самом деле), сейчас, благодаря Composer, они могут просто обновить JSON файл, и немедленно подтянуть все нужные зависимости. Здесь — профайлер, там — фреймворк для тестирования. Это занимает секунды.

В переполненном мире PHP фреймворков, как раз, когда CodeIgniter начал выдыхаться, фреймворк Laravel Тэйлора Отвелла возник из пепла, чтобы стать любимцем общества. С таким простым и элегантным синтаксисом, создавать приложения с Laravel и PHP было абсолютной забавой! Далее, c четвертой версией фреймворка, полностью использовавшим Composer, наконец-то показалось, что для сообщества все вещи встают на места.

image

Хотите миграций (контроль версий базы данных)? Сделано! Как насчёт мощной реализации Active Record? Конечно, Eloquent сделает всё за вас. Как насчёт возможности тестировать? Безусловно! Маршрутизация (роутинг)? Непременно! Что насчёт хорошо протестированного HTTP слоя? Благодаря Composer, Laravel использует много превосходных Symfony компонентов. Когда доходит до дела, есть все шансы, что Laravel уже это может вам предложить!

image

Раньше PHP был похож на игру Дженга — в одном кубике от того, чтобы развалиться — вдруг, благодаря Laravel и Composer, загорелся свет в конце тоннеля. Так что уберем все намёки, и давайте пороемся во всем, что фреймворк может предложить!

1. Красноречивые запросы*


Laravel предлагает одну из самых мощных реализаций Active Record в мире PHP. Скажем, у вас есть таблица orders вместе с Eloquent моделью Order.
class Order extends Eloquent {}

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

Готово! Или, может, эти заказы должны быть отсортированы по дате. Легко:
$orders = Order::orderBy('release_date', 'desc')->get();

А что, если вместо получения записи, нам надо сохранить новый заказ в базу. Мы, конечно, можем это сделать.
$order = new Order;
$order->title = 'Xbox One';
$order->save();

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

* — Eloquent — название реализации Active Record в Laravel, а также в переводе с английского красноречивый.

2. Гибкая маршрутизация (роутинг)


Laravel уникален тем, что может быть использован разными способами. Предпочитаете более простой и похожий на Sinatra роутинг? Laravel легко может это сделать, используя анонимные функции
Route::get('orders', function()
{
    return View::make('orders.index')
        ->with('orders', Order::all());
});

Это может быть полезным для маленьких проектов и API, но есть большие шансы, что вам понадобятся контроллеры для большинства ваших проектов. Окей, Laravel это тоже умеет.
Route::get('orders', 'OrdersController@index');

Готово! Заметили, как Laravel растет по мере ваших потребностей? Уровень приспособления — вот, что делает фреймворк таким популярным сегодня.

3. Отношения без проблем


Что мы делаем в объектах, когда нужно определить отношения? Например, задача точно принадлежит пользователю. Как это указать в Laravel? Предположив, что нужные таблицы в базе данных созданы, мы только должны обратиться к связанным Eloquent моделям.
class Task extends Eloquent {
    public function user()
    {
        return $this->belongsTo('User');
    }
}

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

Всё готово! Давайте получим все задачи пользователя с id = 1. Для этого нам понадобится всего 2 строчки кода.
$user = User::find(1);
$tasks = $user->tasks;

Впрочем, так как мы указали отношение с обеих сторон, если мы захотим получить пользователя, за которым закреплена данная задача, это также легко сделать.
$task = Task::find(1);
$user = $task->user;


4. Связь формы с моделью


Очень часто, будет полезным связать форму с моделью. Очевидный пример — когда Вы хотите изменить какую-то запись в базе. Связав форму с моделью, мы можем моментально заполнить поля формы данными из базы.
{{ Form::model($order) }}
    <div>
        {{ Form::label('title', 'Title:') }}
        {{ Form::text('title') }}
    </div>
 
    <div>
        {{ Form::label('description', 'Description:') }}
        {{ Form::textarea('description') }}
    </div>
{{ Form::close() }}

Так как форма связана с объектом модели Order, в полях будет отображаться данные из таблицы. Вот так просто!

5. Кеш запросов в базу


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

Давайте получим все вопросы из базы данных, но при этом закешируем запрос, так как вряд ли эта таблица будет часто изменяться.
$questions = Question::remember(60)->get();

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

6. Композиторы шаблонов


Вы столкнётесь с ситуациями, когда несколько шаблонов потребуют некоторую переменную или кусок данных. Хороший пример этого — навигационное меню, которое отображает список тегов.
Чтобы контроллеры были с минимальным кодом, Laravel предлагает композиторы шаблонов (вьюшек), чтобы управлять такими вещами.
View::composer('layouts.nav', function($view)
{
    $view->with('tags', ['tag1', 'tag2']);
});

Использовав этот кусок кода, в любой момент, когда подгружен файл layouts/nav.blade.php, у него (у файла) будет доступ к переменной $tags.

7. Простая авторизация


Laravel использует очень простой подход к авторизации. Просто передайте массив данных, которые Вы, скорее всего, получили из формы логина, в Auth::attempt(). Если предоставленный массив соответствует тому, что сохранено в таблице users, пользователь моментально будет авторизован.
$user = [
    'email' => 'email',
    'password' => 'password'
];
 
if (Auth::attempt($user))
{
    // пользователь авторизован
}

Что если надо произвести выход при переходе, например на /logout URI?
Route::get('logout', function()
{
    Auth::logout();
     
    return Redirect::home();
});


8. Ресурсы


Работать RESTfully в Laravel также очень легко! Чтобы объявить контроллер ресурс, просто вызовите Route::resource() следующим образом.
Route::resource('orders', 'OrdersController');

Этот код зарегистрирует 8 роутов.

  • GET /orders
  • GET /orders/:order
  • GET /orders/create
  • GET /orders/:order/edit
  • POST /orders
  • PUT /orders/:order
  • PATCH /orders/:order
  • DELETE /orders/:order


Далее, OrdersController может быть сгенерирован из командной строки:

php artisan controller:make OrdersController

В этом контроллере, каждый метод будет соответствовать одному из роутов, описанных выше. Например, /orders вызовет метод index, /orders/create — метод create и так далее.

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

9. Шаблонизатор Blade


Да, PHP по натуре язык шаблонов, но он не стал слишком хорошим. Впрочем, ничего страшного. Laravel предлагает свой движок Blade, чтобы восполнить пробел. Просто назовите ваши шаблоны с расширением .blade.php, и они соответствующим образом будут парситься. Теперь мы можем делать следующее:
@if ($orders->count())
    <ul>
        @foreach($orders as $order)
            <li>{{ $order->title }}</li>
        @endforeach
    </ul>
@endif


10. Средства для тестирования


Так как 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']);
}


11. Компонент “Дистанционное управление”


Частью Laravel 4.1, который был выпущен в ноябре 2013, стала возможность написать консольную команду для Artisan, чтобы по SSH подключаться к серверу и выполнять любые действия. Просто используйте SSH фасад:
SSH::into('production')->run([
    'cd /var/www',
    'git pull origin master'
]);

В метод run() передайте массив команд, а Laravel займётся всем остальным! Теперь, так как есть смысл выполнять команды в качестве Artisan команд, вам всего лишь нужно выполнить php artisan command:make DeployCommand и в метод fire() написать нужный код для выполнения деплоя.

12. События


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

Продуманное использование событий даст вам много возможностей.
Event::listen('user.signUp', function()
{
    // выполните то, что надо,
    // когда пользователь регистрируется
});

Как и большинство вещей в Laravel, если вы предпочитаете указывать название класса, а не анонимную функцию, вы можете спокойно это сделать. Laravel разрулит всё, используя IoC контейнер.
Event::listen('user.signUp', 'UserEventHandler');


13. Покажите маршруты


image

Приложение растёт, и может стать тяжело посмотреть, какие роуты описаны. Особенно, если Вы не уделяли должного внимания файлу routes.php (например, излишния описания роутов).

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


14. Очереди


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

Зачем заставлять пользователей ждать, пока произойдут эти события, если мы можем отправить выполняться эти события в бекграунде?
Queue::push('SignUpService', compact('user'));

Наверно, самое замечательное, это то, что Laravel превосходно работает с Iron.io “push” очередями. Это значит, что даже не имея опыта работы с воркерами или демонами, мы всё равно можем использовать очереди. Просто опишите роут с помощью команды php artisan queue:subscribe, и Iron.io будет отправлять данные на этот урл каждый раз, когда задача отправлена в очередь. А этот роут в свою очередь выполнит нужные действия.
image

15. Простая валидация


Когда нужна валидация, Laravel снова приходит нам на помощь! Используя класс 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
}



16. Tinker


image

Особенно, если вы используете Laravel в первый раз, может быть полезным повозиться с ядром. Команда tinker поможет с этим.

Tinker использует популярный компонент Boris.

$ php artisan tinker

> $order = Order::find(1);
> var_dump($order->toArray());
> array(...)


17. Миграции


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

Чтобы приготовить схема для новой таблицы users, мы можем выполнить:
php artisan migrate:make create_users_table

Команда сгененерирует файл миграции, который вы наполните так, как вам нужно. Как будете готовы, команда php artisan migrate создаст таблицу. Вот и всё! Нужно откатить изменения? Легко! php artisan migrate:rollback.

Вот пример таблица для таблицы ЧаВО.
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?

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


Laravel предлагает некоторое количество генераторов. Но также есть пакет, который называется “Laravel 4 Generators”, и он зашел еще дальше. Он может генерировать ресурсы, файлы для наполнения базы, pivot таблицы и миграции.

В предыдущем пункте мы вынуждены были сами писать схему. Но используя пакет генераторов, мы можем выполнить команду:

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


А генератор сделает всё остальное. С этой командой вы сможет подоготовить и создать новую таблицу в базе.
Laravel 4 Generators может быть установлен через Composer.

19. Консольные команды


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

Так как это распространенная задача, Laravel делает процесс создания команд наиболее простым.
php artisan command:make MyCustomCommand

Это команда сгенерирует нужный шаблон для Вашей кастомной команды. Далее, в только что созданном файле app/commands/MyCustomCommand.php, заполните название и описание.
protected $name = 'command:name';
protected $description = 'Command description.';

И, в методе fire() выполните нужные действия. После этого останется только зарегистрировать команду для Artisan, в файле app/start/artisan.php.
Artisan::add(new MyCustomCommand);

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

20. Тестируйте фасады


Laravel много использует шаблон Фасад. Это даёт возможность использовать “статический” синтаксис, который, без сомнений, Вам понравится (Route::get(), Config::get(), и так далее), и при этом позволяет полностью тестировать их.

Так как “лежащий в основе” класс разруливается через IoC контейнер, мы легко можем подменить “нижние” классы с нашими тестовыми. Это позволяет нам делать следующее:
Validator::shouldReceive('make')->once();

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

21. Хелперы форм


Так как построение форм часто бывает громоздкой задачей, в дело вступает построитель форм в Laravel, чтобы облегчить этот процесс, а также использовать некоторые “особенности стиля”, связанные с конструированием форм. Вот несколько примеров:
{{ Form::open() }}
    {{ Form::text('name') }}
    {{ Form::textarea('bio') }}
    {{ Form::selectYear('dob', date('Y') - 80, date('Y')) }}
{{ Form::close() }}

Что насчёт задачи запоминания введенных данных при прошлой отправке формы? Laravel это делает автоматически!

22. IoC контейнер (Inverse of control)


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

Просто сделайте typehint ваших зависимостей в конструкторе, и при инициализации Laravel, используя PHP Reflection API, грамотно прочитает ваши подсказки и постарается вставить эти классы за вас.
public function __construct(MyDependency $thing)
{
    $this->thing = $thing;
}

Пока вы запрашиваете класс из IoC контейнера, разрешение зависимости произойдет автоматически.
$myClass = App::make('MyClass');

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

23. Окружения


Одно окружение может подойти для маленьких проектов. Для других проектов, несколько окружений — жизненно важно! Разработка, тестирование, продакшн. Всё это жизненно важно и каждое окружение требует своих настроек.

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

К счастью, Laravel снова облегчает нашу работу. Взгляните на файл bootstrap/start.php.

Там находится простая демонстрация настройки local окружения, которое базируется на hostname компьютера.
$env = $app->detectEnvironment(array(

	'local' => array('your-machine-name'),

));

В общем, это будет работать. Но предпочтительнее использовать переменные окружения для таких вещей. Не беспокойтесь, это легко сделать в Laravel! Просто передайте функцию в метод detectEnvironment.
$env = $app->detectEnvironment(function()
{
    return getenv('ENV_NAME') ?: 'local';
});

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

24. Простая настройка


Laravel опять таки использует очень простой подход к конфигурированию. Создайте в папке app/config папку с названием окружения, и любые файлы конфигурации в этой папке будут иметь приоритет над другими, при условии, что вы находитесь в этом окружении. Например, можно задать другой API ключ для dev окружения.
<?php // app/config/development/billing.php
 
return [
    'api_key' => 'your-development-mode-api-key'
];

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

25. Обучаемость


Когда дело доходит до обучения, Laravel сообщество бесконечно хорошее, несмотря на маленький возраст. В течение чуть более года, были опубликованы полдюжины разных книг, связанные с разработкой на Laravel.
Tags:
Hubs:
+33
Comments 190
Comments Comments 190

Articles