{{TOC}} --- //**Примечание переводчика**// Я новичок в PHP, но при этом очень давно и серьезно занимаюсь разработкой баз данных - на "low level" (только хардкор, только SQL) Много проектов реализуются по шаблону проектирования -"глупый GUI" в силу разных причин (Например - интерфейс пишет субподряд, и требуется гибкость системы без изменения кода приложения). Настал момент когда я решил - пора попробовать перейти на "светлую" сторону! Лара - это то, что должно мне помочь сделать это легко и перестать наконец писать всё на SQL!!!111 Данная статья - объясняет основы , базис прямо для таких как я (for beginners) , что, где и для чего. Надеюсь, что этот перевод поможет еще кому нибудь. Всем добра! --- //**Вступление**// Итак- что же называется Laravel? Вы уже наверно слышали о нем, но наверно не понимаете до конца о чем идет речь? Или наверное вы уже используете его, но хотите узнать побольше о его великолепных возможностях появившихся в 5 версии? Отлично! Тогда этот пост точно для Вас! Larevel - это одновременно самый молодой и в тоже время наиболее популярный PHP framework. Итак: Как PHP и Laravel работают вместе? Давайте поближе посмотрим почему он так популярен, а так же как вы могли бы его использовать. Мы пройдемся по основным функциональным возможностям, а так же поговорим о совершенно новых функциях появившихся в 5 версии. Laravel - это полноценный PHP Framework для работы со всеми видами приложений. Создан по современным стандартам и с использованием лучших практик, с целью сделать высокоуровневое программирование легким и веселым занятием. Так же предполагается, что Lavarel сделает старт разработки нового приложения кам можно более легким и при этом в процессе разработки не потеряется "гибкость". У же во второй раз подряд Laravel выиграл номинацию :((http://www.sitepoint.com/best-php-framework-2015-sitepoint-survey-results "SitePoint PHP framework survey")) Давайте поближе посмотрим на компоненты framerwork'а и поймем почему вам на 100% следует знать все об этой технологии. --- //**Routes (Маршруты)**// Компоненты маршрутизации это основа для любого Framework'а. Они получают на вход запрашиваемые URL и принимают решение куда их перенаправить. В первом примере мы определим, что хотим вернуть строку "Hello World", когда пользователь запрашивает root url нашего приложения (например www.myapp.com). %% Route::get('/', function() { return 'Hello World'; }); %% Но это еще не все. Теперь мы вызовем метод контроллера для вот такого URL: "www.myapp.com/users/1" "{id}" - это параметр, который будет доступен в методе контроллера. В нашем примере "{id}" должен быть равен 1. %% Route::get('user/{id}', 'UserController@showProfile'); %% В обоих примерах мы ожидаем метод запроса GET. Вы конечно же можете использовать другие методы запроса HTTP (POST DELETE или PUT) так же как и GET. %% // Еще примеры маршрутизации Route::post('user', 'UserController@store'); Route::put('user/{id}', 'UserController@update'); Route::delete('user/{id}', 'UserController@delete'); %% Теперь Вы понимаете по какой дорожке мы пойдем. Давайте кое-что прихватим в дорогу,а именно кое-какие данные. --- //**Eloquent (Красноречивость)**// Eloquent - это Object Relational Mapper of Laravel(ORM) - Объектно реляционный сопоставитель. ORM - позволяет нам сопоставить объекты нашего приложения с таблицами в базе данных. Например если мы конструируем блог, тогда посты, страницы фотографий или комментариев могут быть такими объектами. ORM берет на себя управление такими объектами таким образом, что нам не нужно писать ни строчки SQL (кроме случаев когда мы сами этого хотим) Единственная вещь, которая нам нужна для работы с Eloquent, это модель таблицы из базы данных являющаяся расширением класса Model. (речь идет о производном классе, который является наследником класса Model по каноническому описанию ООП - Примечание переводчика) %% class User extends Model { protected $table = 'my_users'; } %% Если наш производный класс назвать "User", Laravel автоматически будет искать в базе таблицу с именем "user". Что изменить такое поведение по-умолчанию, нужно добавить переменную $table с требуемым значением имени таблицы. Теперь мы готовы получить немного основ магии Eloquent. %% // Получить всех пользователей User::all(); // Получить определенного пользователя по его идентификатору User::find(1); // Я думаю и теперь вызнаете, что вам не нужны эти комментарии //(примечание переводчика: Аффтар шутит - смысл строки кода: удалить определенный объект по его идентификатору) User::destroy(1); //Выдать первого пользователя с именем Джим-хороший мальчик User::where('name', 'Jim')->first(); %% Разве эти инструкции вызова не элегантны и не приятны глазу? Вы моментально понимаете, что мы делаем просто читая код. Давайте проделаем еще кое чего разного для создания, чтения, изменения и удаления (Это называется базовыми функциями CRUD - Create-Read-Update-Delete) %% // Создание $user = new User; $user->name = 'Jim'; $user->save(); // Чтение $user = User::where('name', 'Jim')->first(); // Изменение $user->update(['name' => 'John']); // Удаление $user->delete(); %% Это только самая вершина айсберга. Существует еще очень много что Вы можете делать с Eloquent, например: Работа с реляциями, массивная загрузка данных и коллекции. Примечание автора: Работа с Eloquent это не то, что требуется принудительно, но у меня не было ни одного проекта без Eloquent. --- //**Facades**// (Витрины или Фасады - кому как больше нравится) В Laravel вы имеете доступ к объектам фреймворка через Фасады. Они похожи на вызов статических методов класса (Методы,для вызова которых не требуется создание экземпляра класса владельца этого метода - по каноническому описанию ООП Примечание переводчика), но это не совсем тот случай. Факт, что не-статические методы вызываются "под капотом" (имеется ввиду скрытая реализация Примечание переводчика) Laravel просто делает доступным использование простого синтаксиса. Новичков это может немного смутить, но это делает использование этих классов чертовски простым. %% // Using Laravel Cache Facade $value = Cache::get('key'); // Using Laravel Auth Facade if (Auth::check()) { // The user is logged in... } %% Вы так же можете определять свои собственные Фасады. Многие пакеты Laravel также их используют. Просто надо запомнить, что Фасады это маленькие помощники для вызова методов классов в Laravel. --- //**Artisan (Мастер)**// Каждый хороший фреймворк имеет интерфейс командной строки (CLI). В Laravel он называется Artisan (Мастер) и построен на основе консоли Symfony. Atisan предоставляет полезные команды для вашего процесса разработки. Существует много всего, что Вы можете сделать с помощью Artisan и вот некоторые примеры этого: %%(sh) // Список всех команд Artisan php artisan list // Кэшировать маршруты php artisan route:cache // Or create a migration (there is a sperate section about migrations) // Или определить миграцию (есть отдельная глава про миграцию) php artisan migrate:make create_users_table %% Ознакомьтесь также со всеми остальными командами Artisan. Они помогут вам разрабатывать быстрее и избавят Вас от рутинных вещей. (В исходном тексте опечатка, автор пишет что Вы обязательно будете вынуждены заботится о скучных вещах - заниматься рутиной you do have to take care of the boring stuff. По смыслу подходит: you don't have to take care of the boring stuff. Примечание переводчика) --- //**Controller (Контроллер)**// Мы уже видели, что возможно получить ответ от маршрутизаторов напрямую, прямо из вашего routes.php файла. Это один из приемлемых вариантов, но нам нужен более понятный путь. Контроллеры помогут нам структурировать наши приложения. Наши маршрутизаторы будут вызывать методы контроллера для выполнения определенных заданий перед тем как мы вернем данные или целое представление. Пример контроллера сначала получает переменную $id от нашего маршрутизатора методом: %%Route::get ('user/{id}', 'UserController@showProfile');%% . Затем он возвращает представление с данными объекта пользователя, идентификатор которого был получен в значении переменной $id %% User::findOrFail($id)]); } } %% --- //**Resource Controller (Контроллер ресурса)**// Существует большой шанс того, что мы работая с объектами нашей БД (с ресурсами в данном случае), хотели бы, что бы некоторые почти одинаковые действия выполнялись бы снова и снова. Давайте представим в нашем приложении есть фотографии, подумаем - возможности каких действий над ними Вы хотели бы иметь: * Показать все изображения фотографий * Показать форму создания фотографии * Сохранение фотографии * Показать определенную фотографию * Показать форму редактирования определенной фотографии * Удалить определенную фотографию * ... Все это подходит для фотографий, постов комментариев и других типов ресурсов. При кривом подходе мы должны были бы написать маршруты для всех этих действий, которые были бы соединены с методами контроллера. Это могло бы выглядеть следующим образом: %% Route::get('/photo', 'PhotoController@index'); Route::get('/photo/create', 'PhotoController@create'); Route::post('/photo', 'PhotoController@store'); Route::get('/photo/{id}', 'PhotoController@show'); Route::get('/photo/update/{id}', 'PhotoController@edit'); Route::delete('/photo/{id}', 'PhotoController@destroy'); ... %% Я думаю вы поняли. Это слишком много писанины и повторов. Подумайте теперь еще и о контроллере и его методах, которые вам также придется написать. Вот тут то и наступает удобство Laravel %%RESTful%% сервиса %%resource controller%%. Команда Artisan включяет магию: %%(sh) php artisan make:controller PhotoController --resource %% Будет сделано две вещи: * Первое - будет создан контроллер %%PhotoController%% с методами для индексации, создания, сохранения, представления, редактирования, сохранения изменений и удаления. (ориг. index, create, store, show, edit, update and destroy Примечание переводчика) * Второе - Вы сможете использовать ресурс маршрута(метод %%resource%% класса %%Route%% - Примечание переводчика) для соединения этих методов с маршрутами. %% // Defining a resource route //Определение ресурса маршрута Route::resource('photo', 'PhotoController'); %% Таблица ниже показывает созданные маршруты и подсоединенные методы контроллера. Это спасет ваше время и это еще одна выдающаяся черта Laravel. {{Image http://christoph-rumpel.com/assets/post-images/laravel_routes.png, align=left, height=500px}} --- //**Migrations**// (Миграции) Все мы бывали в такой ситуации. Вы начинаете новый проект и через некоторое время замечаете, что вам нужна еще одна таблица или колонка. ОК - Вы могли бы просто добавить их вашу локальную базу. Ну и что - это важно? >"//**Migrations**// are like version control for your database structure" >"//**Migrations**// - это как контроль версий для структуры вашей БД" Другие разработчики получают последнюю версию кода из систем контроля версий, но только //**НЕ**// изменения в БД структуре. //**НЕ**// до тех пор пока нет //Migrations// (Очень спорное суждение. п При хранении DDL кода баз данных в системах контроля версий есть проблемы, связанные в основном, с компиляцией. При компиляции в БД меняется только один объект (или несколько) ,тогда как при компиляции кода языков программирования компилируется весь проект. Поэтому при работе с БД есть сложность в синхронизации актуальности кода структур в самой БД и в хранилище контроля версий. В любом случае при работе с БД в крупных проектах контроль версии необходим! Например для выпусков релизов можно сравнивать состояния кода разных веток хранилища и т.д, Примечание переводчика) Просто есть файлы описывающие ваши изменения в структуре БД. Очень просто например как: "Я добавил таблицу USERS c полями..." или "Я изменил определение поля из таблицы RECIPES поменяв тип данных с VARCHAR на TEXT". Эти файлы живут внутри вашего репозитория, следовательно Вы можете отгружать изменения кода таким образом, что бы другие разработчики знали о них тоже. %% increments('id'); $table->string('email')->unique(); $table->rememberToken(); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('users'); } } %% Это пример того как обычно выглядят файл миграции. Это класс с методами %%up()%% и %%down()%%. Первым делом мы определяем те изменения, которые мы хотели бы сделать в структуре нашей БД (как добавление, удаление, изменения таблиц или колонок). В методе %%down()%% мы отклоняем изменения кода полученные из %%up()%% метода. Это делается по тому, что нам бы хотелось иметь возможность откатывать изменения в некоторых случаях. В нашем случае удаление новой таблицы могло бы быть противоположностью её создания. (Если метод %%up()%% содержит скрипт создания таблицы, тогда метод %%down()%% содержит скрипт удаления этой таблицы. Примечание переводчика) В Laravel вы можете запустить миграцию командой artisan: %%php artisan migrate%%. Эта команда проверит наличие новых фактов миграций и если требуется произведет изменения структуры вашей БД. В любом случае Вы не захотели бы работать без таких возможностей. --- //**Form requests**// (Требования к форме) Это моя любимая возможность в Laravel 5 и да, и она кое-что проделывает над формами. Это простой способ валидации ваших форм через пользовательские классы. Что бы создать новое требование проверки формы используйте команду Artisan %%php artisan make:request StorePhotoRequest%%. Значение имени предполагает, что мы используем этот запрос для валидации новых данных о фотографиях. Давайте взглянем на два важных метода созданного класса: %% * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return \Auth::check(); } /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ 'title' => 'required|string', 'description' => 'required|string', ]; } %% В методе %%authorize()%% мы определяем является ли запрос авторизованным? (Сюрприз!) False будет возвращаться в ответ на "403 HTTP response", True позволит запросу пройти. В нашем методе %%authorize()%% мы проверяем является ли пользователь авторизованным. Метод %%rules()%% возвращает массив с типичными для Laravel правилами валидации. Мы определяем некоторые колонки и требования к ним такие как - заголовок должен быть строкой. Ок - это понятно. Но вы можете подумать - почему это так не обычно реализовано? Во -первых отдельный класс это лучший вариант для управления этими валидациями. Это еще не все. Давайте посмотрим на то, как мы вызываем валидацию: %% // From the PhotoController public function store(StorePhotoRequest $request) { // The incoming request is valid... // Входящий запрос валиден (здесь уже точно! Примечание переводчика) } %% Ага, опять принудительно указанный тип входящего параметра это то, что достаточно для вызова валидации до передачи запроса в тело метода. (Другими словами, имя типа входящего параметра - это достаточно, что бы подвергнуть валидации значение этого параметра, перед тем как исполнение попадает в область видимости метода %%store(...)%%, а все потому что создан класс - требования к форме с именем равным имени прикладного класса - и экземпляр прикладного класса принудительно подвергается проверке. Примечание переводчика) Если валидация провалена запрос никогда не проникнет внутрь метода. Удивительно правда? Примечание: Требования к формам это новая функциональность в Laravel 5. --- //**Dependency Injection**// (Внедрение зависимостей) Dependency Injection - это шаблон проектирования, который позволяет избежать статического кодирования (hardcoding) зависимостей. Это помогает сделать ваше приложение более модульным и удерживает Вас от создания сверхсвязанных классов. Также это полезно при тестировании, потому что вы можете легко переопределить зависимость на тестовый класс. >"Dependency Injection is a key element of agile architecture - Ward Cunningham" >"Внедрение зависимости - ключевой элемент динамичной архитектуры" %% class UsersController extends BaseController { public function getIndex() { return Response::make('Hello users!'); } } %% В этом классе управления пользователями %%UsersController%% мы используем %%Response%% класс (и таки -да , это тоже Фасад), внутри метода %%getIndex()%%. Это абсолютно нормально, когда вы делаете маленький проект и вам не надо или Вы не хотите тестировать этот класс. Если нет, то это все таки плохая практика. Наш %%UserController%% класс является //тесно связанным// (//tightly coupled//) с классом %%Response%%. Это как раз то чего мы хотим избежать с помощью //Внедрения зависимости//. -- //**Constructor injection**// (Внедрение через конструктор) Одним из путей решения было бы наличие в конструкторе внедрения: %% class UsersController extends BaseController { protected $response; public function __construct(Response $response) { $this->response = $response; } public function getIndex() { return $this->response->make('Hello Users!'); } } %% Здесь мы внедрили %%Response%% класс внутрь конструктора через принудительно указанный тип входящего параметра. Laravel понимает, что вам нужен объект этого класса, и предоставит его для Вас. Другими словами, наш %%UserController%% теперь - это слабосвязанный класс с классом %%Response%%. Мы можем легко переключить это и подделать тип для тестирования. (В данном случае директива экземпляра класса %%responce%% объявляет его как закрытый объект класса %%UsersController%% (%% protected $response;%%) и, что важно, без указания типа экземпляра! Тип прилетает в конструкторе, и, если тип надо сменить, то достаточно поменять это в одном месте. Если использовать методы как статические (как требуется от Фасадов), то при смене типа класса придется переименовать тип в миллионе мест. Примечание переводчика) --- //**Method injection**// (Внедрение через метод) Вполне возможно, что вам совсем не нужно внедрение класса %%Response%% во все методы класса %%UserController%%. В этом случае //внедрение через метод// очень удобно. Мы можем внедрить класс в наш метод %%UserController%% через аргументы. Теперь нам больше не понадобится конструктор и наш код стал короче. %% class UsersController extends BaseController { public function getIndex(Response $response) { return $response->make('Hello World!'); } } %% (Странно, но по моему мнению мы опять получили сверхсвязанные классы. Ведь сколько методов используют принудительно указанный тип параметра, в стольких местах и понадобится переименование - разве нет? Примечание переводчика) Примечание: Внедрение через метод это новая возможность в Laravel 5. --- //**Заключение**// Я надеюсь, что смог показать, как приятно работать c Laravel над вашими приложениях. Все построено, что бы помочь вам работать над вашими проектами и делать работу быстро и с удовольствием. Конечно, рассмотрены только базовые компоненты, знание которых вам понадобится на старте. Это даже лучше, когда Вы сами находите маленькие трюки и возможности, которые доступны вам. Итак, давайте сделайте что-нибудь невероятное прямо сейчас! (Перевод: Лапшин Кирилл- Советский Союз - январь 2016) -- //**Еще некоторые элементы Laravel**// --- //Elixir// Elixir это API для написания Gulp задач в Laravel. Gulp это JavaScript менеджер задач такой как Grunt. Вы можете управлять вашими элементами и автоматизировать эти задачи. (минимизировать, объединять, оптимизировать изображения, и т.д.) ((http://laravel.com/docs/5.0/elixir "Подробнее на английском")) --- //Homestead// Homestead - это готовая к использованию виртуальная машина vagrant box специально оптимизированная для Laravel. ((http://laravel.com/docs/5.0/homestead "Подробнее на английском")) --- ////