Лекция
Привет, Вы узнаете о том , что такое laravel, Разберем основные их виды и особенности использования. Еще будет много подробных примеров и описаний. Для того чтобы лучше понимать что такое laravel, eloquent , настоятельно рекомендую прочитать все из категории Фреймворки. Famworks ( программная платформа).
Вместо:
$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
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]);
В модели 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(); }); }
Обычный способ определения отношений:
public function users() { return $this->hasMany('App\User'); }
Но знаете ли вы, что сюда мы можем добавить where или orderBy? Например, если вам нужно специальное отношения для некоторых типов пользователей, упорядоченное по электронной почте, вы можете сделать так:
public function approvedUsers() { return $this->hasMany('App\User')->where('approved', 1)->orderBy('email'); }
Существует несколько «параметров» 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 и посмотрите все используемые трэйты.
Всем известен метод find(), правда?
$user = User::find(1);
Удивительно, как мало кто знает о том, что он может принимать несколько ID`шников в виде массива:
$users = User::find([1,2,3]);
Есть элегантный способ превратить:
$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'));
Немного больше чем "трюк". Что делать если у вас есть темы форума, но вы хотите их отсортировать, по их последним постам? Довольно популярное требование в форумах с последними обновленными темами вверху, правда?
Сначала опишите отдельную связь для последнего поста в теме:
public function latestPost() { return $this->hasOne(\App\Post::class)->latest(); }
И после, в вашем контроллере, вы можете выполнить такую "магию":
$users = Topic::with('latestPost')->get()->sortByDesc('latestPost.created_at');
Многие из нас пишут условные запросы с «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();
Допустим, у вас есть пост, принадлежащий автору, и 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' ]); }
Представьте что у вас есть такой преобразователь:
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.
Что делать, если вы хотите, чтобы 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 здесь.
Иногда нужно добавить сырые выражения в наш 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();
Без глубоких объяснений, вот лучший способ сделать копию записи в базе данных:
$task = Tasks::find(1); $newTask = $task->replicate(); $newTask->save();
Не совсем о Eloquent, это скорее о коллекциях, но все же мощный метод — для обработки больших наборов данных. Метод позволяет разбить набор данных на кусочки.
Вместо:
$users = User::all(); foreach ($users as $user) { // ...
Можно сделать:
User::chunk(100, function ($users) { foreach ($users as $user) { // ... } });
Мы все знаем Artisan команду:
php artisan make:model Company
Но знаете ли вы, что есть три полезных флага для создания дополнительных файлов модели?
php artisan make:model Company -mcr
Знаете ли вы, что метод ->save() может принимать параметры? Как результат мы можем “игнорировать” updated_at функциональность, которая по умолчанию должна была установить текущую метку времени.
Посмотрите на следующий пример:
$product = Product::find($id); $product->updated_at = '2019-01-01 10:00:00'; $product->save(['timestamps' => false]);
Здесь переписыавается updated_at предустановленным значением.
Вы когда-нибудь задумывались над тем, что этот код возвращает?
$result = $products->whereNull('category_id')->update(['category_id' => 2]);
Я имею в виду, что обновление выполняется в базе данных, но что будет содержать этот $result?
Ответ: затронутые строки. Поэтому, если вам нужно проверить, сколько строк было затронуто, вам не нужно ничего вызывать — метод update() вернет это число для вас.
Что делать если у вас есть 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); })
Вы можете передать массив параметров в orWhere().
“Обычный” способ:
$q->where('a', 1); $q->orWhere('b', 2); $q->orWhere('c', 3);
Вы можете сделать так:
$q->where('a', 1); $q->orWhere(['b' => 2, 'c' => 3]);
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 задачи, которые были громоздкими для исполнения, смехотворно просты.
Laravel уникальна тем, что его можно использовать несколькими способами. Предпочитаете более простую, более синтатроподобную систему маршрутизации? Конечно, Laravel может предложить это довольно легко, используя закрытие.
Route::get('orders', function() { return View::make('orders.index') ->with('orders', Order::all()); });
Это может оказаться полезным для небольших проектов и API, но, скорее всего, вам понадобятся контроллеры для большинства ваших проектов. Это нормально; Ларавел тоже может это сделать!
Route::get('orders', 'OrdersController@index');
Готово. Обратите внимание, как Laravel растет с вашими потребностями? Этот уровень размещения является тем, что делает структуру столь же популярной, как и сегодня.
Что мы делаем в случаях, когда мы должны определять отношения? Например, задача, безусловно, принадлежит пользователю. Как мы можем представить это в 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;
Часто бывает полезно связать форму с моделью. Очевидным примером этого является то, что вы хотите отредактировать некоторую запись в своей базе данных. Об этом говорит сайт https://intellect.icu . При привязке модели модели мы можем мгновенно заполнить поля формы значениями из соответствующей строки таблицы.
{{ Form::model($order) }}
{{ Form::label('title', 'Title:') }} {{ Form::text('title') }}
{{ Form::label('description', 'Description:') }} {{ Form::textarea('description') }}
{{ Form::close() }}
Поскольку форма теперь связана с конкретным экземпляром заказа, входы будут отображать правильные значения из таблицы. Просто!
Слишком много запросов к базе данных, и очень быстро ваше приложение может стать как меласса. К счастью, Laravel предлагает простой механизм кэширования этих запросов, используя только один вызов метода.
Давайте возьмем все вопросы из базы данных, но кешируем запрос, так как вряд ли эта таблица будет часто обновляться.
$questions = Question::remember(60)->get();
Это оно! Теперь, в течение следующего часа запросов страниц, этот запрос останется кешированным, и база данных не будет затронута.
Вы столкнетесь с ситуациями, когда несколько видов требуют определенной переменной или части данных. Хорошим примером этого является панель навигации, на которой отображается список тегов.
Слишком простое управление контроллерами, Laravel предлагает просмотр композиторов для управления такими вещами.
View::composer('layouts.nav', function($view) { $view->with('tags', ['tag1', 'tag2']); });
С помощью этого фрагмента кода, в любое время, когда загружается представление layouts nav.blade.php, он будет иметь доступ к переменной $ tags, равной предоставленному массиву.
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(); });
Работать 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.
Хотя, да, PHP по своей природе является языком шаблонов, он не превратился, чтобы стать слишком хорошим. Все в порядке; Laravel предлагает свой двигатель Blade, чтобы заполнить пробел. Просто назовите свои представления с расширением.blade.php, и они будут автоматически проанализированы соответственно. Теперь мы можем делать такие вещи, как:
@if ($orders->count())
@endif
Поскольку 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']); }
В рамках Laravel 4.1, который планируется выпустить в ноябре 2013 года, вы можете легко написать команду Artisan SSH на свой сервер и выполнить любое количество действий. Это так же просто, как использование фасада SSH:
SSH::into('production')->run([ 'cd /var/www', 'git pull origin master' ]);
Передайте массив команд методу run (), и Laravel справится с остальными! Теперь, поскольку имеет смысл выполнять такой код как команду Artisan, вам нужно только запустить команду php artisan: сделать DeployCommand и вставить соответствующий код в метод пожарной команды, чтобы быстро создать выделенную команду развертывания!
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');
По мере расширения приложения может быть сложно просмотреть, какие маршруты были зарегистрированы. Это особенно верно, если надлежащий уход не был предоставлен вашему файлу route.php (т. Е. Оскорбительная неявная маршрутизация).
Laravel предлагает команду полезных маршрутов, в которой будут отображаться все зарегистрированные маршруты, а также методы контроллера, которые они запускают.
php artisan routes
Подумайте, когда пользователь зарегистрируется для вашего приложения. Вероятно, должен произойти ряд событий. Необходимо обновить таблицу базы данных, добавить список бюллетеней, добавить счет-фактуру, отправить приветственное письмо и т. Д. К сожалению, подобные действия имеют тенденцию занять много времени.
Почему заставить пользователя ждать этих действий, когда мы можем вместо этого бросить их в фоновом режиме?
Queue::push('SignUpService', compact('user'));
Возможно, самая захватывающая часть - это то, что Laravel блестяще предлагает поддержку Iron.io push queues. Это означает, что даже без унции опыта «работника» или «демона» мы все еще можем использовать возможности очередей. Просто зарегистрируйте конечную точку URL-адреса, используя полезную команду php artisan queue для Laravel: подписать команду, а Iron.io будет проверять ваш выбранный URL каждый раз, когда задание добавляется в очередь.
Простые шаги для повышения производительности!
Когда требуется проверка (и когда это не так), Ларавел снова приходит на помощь! Использование класса 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();
Особенно, когда вы впервые изучаете Laravel, полезно поработать с ядром. Команда Larsvel по команде мастеров Artisan может помочь в этом.
Как часть версии 4.1, команда tinker еще более мощная, теперь она использует популярный компонент Boris.n
$ php artisan tinker > $order = Order::find(1); > var_dump($order->toArray()); > array(...)
Подумайте о миграции в качестве контроля версий для своей базы данных. В любой момент вы можете «откат» всех миграций, повторить их и многое другое. Возможно, истинная сила заключается в том, чтобы подталкивать приложение к производству и запускать одну команду миграции 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?
В то время как Laravel предлагает ряд полезных генераторов, невероятно полезный сторонний пакет, называемый «Laravel 4 Generators», делает это еще больше. Создавайте ресурсы, файлы семян, сводные таблицы и миграции с помощью схемы!
В этом предыдущем совете мы были вынуждены вручную написать схему. Однако с включенным пакетом генераторов мы можем:
php artisan generate:migration create_users_table --fields="username:string, password:string"
Генератор позаботится обо всем остальном. Это означает, что с помощью двух команд вы можете подготовить и построить новую таблицу базы данных.
Laravel 4 Генераторы могут быть установлены через Composer.n
Как отмечалось ранее, существует множество экземпляров, когда может быть полезно писать пользовательские команды. Они могут использоваться для создания приложений, создания файлов, развертывания приложений и всего промежуточного.
Поскольку это такая общая задача, Laravel делает процесс создания команды настолько простым, насколько это возможно.
php artisan command:make MyCustomCommand
Эта команда создаст необходимый шаблон для вашей новой пользовательской команды. Затем, из недавно созданных команд приложения MyCustomCommand.php, заполните соответствующее имя и описание:
protected $name = 'command:name'; protected $description = 'Command description.';
И, наконец, в методе класса fire () класса класса выполните любое действие, которое вам нужно. Как только закончите, единственный оставшийся шаг - зарегистрировать команду с Artisan, начиная с приложения Artisan.php.
Artisan::add(new MyCustomCommand);
Хочешь верь, хочешь нет; это оно! Теперь вы можете вызывать свою пользовательскую команду с терминала.
Laravel сильно использует шаблон фасада. Это позволяет использовать чистый статический синтаксис, который вам, несомненно, понравится (Route:: get (), Config:: get () и т. Д.), Но при этом позволяет полностью тестировать за кулисами.
Поскольку эти «базовые классы» разрешены из контейнера IoC, мы можем легко обменять эти базовые экземпляры с помощью mocks для целей тестирования. Это позволяет осуществлять такой контроль, как:
Validator::shouldReceive('make')->once();
Да, мы вызываем shouldReceive прямо от фасада. За кулисами Laravel использует превосходную структуру Mockery для этого. Это означает, что вы можете свободно использовать эти фасады в своем коде, сохраняя при этом 100% тестируемость.
Поскольку строительные формы часто могут быть громоздкой задачей, строитель форм Laravel делает это для облегчения процесса, а также использует многие особенности, связанные с построением формы. Вот несколько примеров:
{{ Form::open() }} {{ Form::text('name') }} {{ Form::textarea('bio') }} {{ Form::selectYear('dob', date('Y') - 80, date('Y')) }} {{ Form::close() }}
Как насчет задач, таких как запоминание ввода из предыдущего представления формы? Laravel может делать все это автоматически!
В основе Laravel лежит его мощный контейнер IoC, который является инструментом, который помогает управлять зависимостями классов. Примечательно, что контейнер имеет возможность автоматически разрешать классы без конфигурации!
Просто введите типы зависимостей внутри конструктора и, после создания экземпляра, Laravel будет использовать PHP Reflection API для интеллектуального считывания ключей типа и попытаться ввести их для вас.
public function __construct(MyDependency $thing) { $this->thing = $thing; }
Пока вы запрашиваете класс из контейнера IoC, это разрешение будет выполняться автоматически.
$myClass = App::make('MyClass');
Важно отметить, что контроллеры всегда разрешены из контейнера IoC. Таким образом, вы можете бесплатно отключить зависимости вашего контроллера, и Laravel впоследствии сделает все возможное, чтобы ввести их для вас. N
Несмотря на то, что для небольших проектов может работать одна среда, для любых приложений размера несколько оснований окажутся необходимыми. Разработка, тестирование, производство... все они необходимы и требуют собственной конфигурации.
Возможно, ваша тестовая среда использует базу данных в памяти для тестирования. Возможно, ваша среда разработки использует разные ключи 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'; });
Теперь, если не задана переменная окружения (которую вы будете делать для производства), среда будет по умолчанию локальной.
Laravel, опять же, использует простой подход к настройке. Создайте папку в конфигурации приложения, которая соответствует вашей желаемой среде, и любые файлы конфигурации в ней будут иметь приоритет, если имя среды совпадает. Таким образом, чтобы, скажем, установить другой ключ API для биллинга для разработки, вы можете:
app/config/development/billing.php return [ 'api_key' => 'your-development-mode-api-key' ];
Конфигурация switcharoo является автоматической. Просто введите Config:: get ('billing.api_key'), и Laravel правильно определит, какой файл читать.
Когда дело доходит до образования, сообщество Laravel, несмотря на относительно молодой возраст, является бесконечным. Менее чем через год было выпущено полдюжины разных книг, связанных со всеми вопросами развития Ларавеля.
Узнайте все от основ, до тестирования, создания и поддержки больших приложений!
Это не пересказ лучших практик вроде SOLID, паттернов и пр. с адаптацией под Laravel. Здесь собраны именно практики, которые игнорируются в реальных Laravel проектах. Также, рекомендую ознакомитсья с хорошими практиками в контексте PHP. Смотрите также обсуждение хороших практик Laravel.
Каждый класс и метод должны выполнять лишь одну функцию.
Плохо:
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; }
По своей сути, это лишь один из частных случаев принципа единой ответственности. Выносите работу с данными в модели при работе с 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(); } }
Следуя принципам тонкого контроллера и 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', ]; } }
Контроллер должен выполнять только свои прямые обязанности, поэтому выносите всю бизнес логику в отдельные классы и сервис классы.
Плохо:
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'); } } }
Этот принцип призывает вас переиспользовать код везде, где это возможно. Если вы следуете принципу 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(); }
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();
Плохо:
$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());
Плохо (будет выполнен 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
Плохо:
if (count((array) $builder->getQuery()->joins) > 0)
Лучше:
// Determine if there are any joins. if (count((array) $builder->getQuery()->joins) > 0)
Хорошо:
if ($this->hasJoins())
Плохо:
let article = `{{ json_encode($article) }}`;
Лучше:
Или{{ $article->name }}
В Javascript файле:
let article = $('#article').val();
Еще лучше использовать специализированный пакет для передачи данных из бэкенда во фронтенд.
Непосредственно в коде не должно быть никакого текста.
Плохо:
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'));
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 |
Следуйте стандартам 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 |
Плохо:
$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') |
Внедрение классов через синтаксис new Class создает сильное сопряжение между частями приложения и усложняет тестирование. Используйте контейнер или фасады.
Плохо:
$user = new User; $user->create($request->all());
Хорошо:
public function __construct(User $user) { $this->user = $user; } .... $this->user->create($request->all());
Передайте данные из .env файла в кофигурационный файл и используйте config() в приложении, чтобы использовать эти данными.
Плохо:
$apiKey = env('API_KEY');
Хорошо:
// config/api.php 'key' => env('API_KEY'), // Используйте данные в приложении $apiKey = config('api.key');
{{ 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 }}
Не размещайте логику в маршрутах.
Старайтесь не использовать "сырой" PHP в шаблонах Blade.
«Нормальный» метод:
$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 ( программная платформа)
Ответы на вопросы для самопроверки пишите в комментариях, мы проверим, или же задавайте свой вопрос по данной теме.
Комментарии
Оставить комментарий
Фреймворки. Famworks ( программная платформа)
Термины: Фреймворки. Famworks ( программная платформа)