• Eloquent
  • Dependency Injection
  • Миграции
  • Валидация
  • Роутинг
  • ENV
  • Тесты
  • Шаблонизатор

Lalavel 5.2 requirements

  • PHP >= 5.5.9
  • OpenSSL PHP Extension

  • PDO PHP Extension

  • Mbstring PHP Extension

  • Tokenizer PHP Extension

Lalavel 5.3 requirements

  • PHP >= 5.6.4

IoC контейнер

  1. Внедрение зависимостей (Dependency Injection)
  2. Сервис-контейнер (ServiceContainer)
  3. Отражения (Reflection)
<?php
namespace Example\Namespase;

use App\ClassA;
use App\ClassB;

class SomeClass extends AnotherClass {

    public function doSomething(ClassA $myVar, ClassB $mySecondVar)
    {
        //
    }
}

$myObj = new SomeClass;
$myObj->doSomething();

Eloquent

<?php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\ModelNotFoundException;

class User extends Model
{
    protected $primaryKey = 'email';

    private $avatarPath = '/userfiles/avatars/';

    protected $fillable = ['username', 'email', 'password'];

    protected $hidden = ['password'];

    public function phones()
    {
      return $this->hasMany('\App\Models\Phone');
    }

    public function getImageAttribute($image)
    {
      return $this->imagePath . $image;
    }
}


try {
    $user = User::findOrFail('elforastero@ya.ru')->with('phones');
} catch (ModelNotFoundException $e) {
    abort(404);
}

$user->phones->map(function($phone) {
    echo $phone->number, ' ', $phone->type;
});

6 типов отношений

<?php

// User model

public function company()
{
    return $this->hasOne('Company');
}

public function phones()
{
    return $this->hasMany('Phone');
}

public function roles()
{
    return $this->belongsToMany('Role');
}

public function photos()
{
    return $this->morphToMany('Photo', 'imageable');
}

// morphToMany()
// hasManyThrough()

Scopes

public function scopeActive($query)
{
    return $query->where('active', 1)
}


$users = User::all()->active();
public function scopeActive($query)
{
    return $query->where('active', 1)
                 ->where('last_visit', '>', Carbon::now()->subWeek());
}
public function scopeActive($query)
{
    return $query->where('active', 1)
                 ->where('last_visit', '>', Carbon::now()->subWeek())
                 ->where('age', '>=', 18);
}
use Illuminate\Database\Eloquent\SoftDeletes;

class User extends Model
{
    use SoftDeletes;

    // Первичный ключ
    protected $primaryKey = 'email';

    // Автозаполенение
    protected $fillable = ['username', 'email', 'password'];

    // Список недоступного для извлечения
    protected $hidden = ['password'];

    // Конвертация типов
    protected $casts = [
        'active'   => 'bool',
        'is_admin' => 'bool',
        'options'  => 'array',
    ];

    private $avatarPath = '/userfiles/avatars/';

    // Преобразователь
    public function setIsAdminAttribute($user)
    {
        if($user->roles->contains(Role::ADMIN)) {
            return true;
        }
        return false;
    }
}

User::destroy('elforastero@ya.ru');

Коллекции

// Модели возврщают коллекции

$orders = Order::with(['goods', 'client'])->all()
    ->sortByDesc('created_at');

$orders = $orders->groupBy('payment_type');

$orders->map(function($order) {
    echo $order->goods->first()->articul;
    echo $order->client->name;
});


// Коллекции можно создавать вручную

$myCollection = collect([1, 2, 3, 4]);

echo $myCollection->max();
echo $myCollection->min();
echo $myCollection->avg();

Миграции

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AlterUsersTableAddAgeColumn extends Migration
{
  /**
   * Выполнение миграций.
   *
   * @return void
   */
  public function up()
  {
    Schema::table('users', function (Blueprint $table) {
      $table->integer('age')->unsigned();
    });
  }

  /**
   * Отмена миграций.
   *
   * @return void
   */
  public function down()
  {
    Schema::table('users', function(Blueprint $table) {
        $table->dropColumn('age');
    });
  }
}
public function up() {
    Schema::create('phone_user', function($table) {
        $table->integer('user_id')->unsigned();
        $table->integer('phone_id')->unsigned();

        // Составной первичный ключ
        $table->primary(['user_id', 'phone_id']);

        // Внешний ключ
        $table->foreign('user_id')
              ->references('id')
              ->on('users')
              ->onDelete('cascade');

        $table->foreign('phone_id')
              ->references('id')
              ->on('phone')
              ->onDelete('cascade')
    });
}

phone_user table

// Increments
$table->increments('id');
$table->bigIncrements('id');
// Numbers
$table->integer('votes');
$table->tinyInteger('votes');
$table->smallInteger('votes');
$table->mediumInteger('votes');
$table->bigInteger('votes');
$table->float('amount');
$table->double('column', 15, 8);
$table->decimal('amount', 5, 2);
//String and Text
$table->char('name', 4);
$table->string('email');
$table->string('name', 100);
$table->text('description');
$table->mediumText('description');
$table->longText('description');
//Date and Time
$table->date('created_at');
$table->dateTime('created_at');
$table->time('sunrise');
$table->timestamp('added_on');
$table->timestamps();
// Adds created_at and updated_at columns
$table->nullableTimestamps();
// Others
$table->binary('data');
$table->boolean('confirmed');
$table->softDeletes();
// Adds deleted_at column for soft deletes
$table->enum('choices', array('foo', 'bar'));
$table->rememberToken();
// Adds remember_token as VARCHAR(100) NULL
$table->morphs('parent');
// Adds INTEGER parent_id and STRING parent_type
->nullable()
->default($value)
->unsigned()

Роутинг

// routes.php
// put, patch, delete, options

Route::get('/user/{id}', 'UserController@show');

Route::post('/user', 'UserController@save');


// Модель в роуте
Route::get('/user/{user}', function(App\Models\User $user) {
    return view('user.one')->with('user', $user);
});

// Именованные маршруты
Route::get('/{username}', [
    'name' => 'profile',
    'uses' => 'ProfileController@showProfile']
);

// Редирект на именованный маршрут
return redirect()->route('profile');
return redirect()->route('profile', $user);

// Редирект на экшн
return redirect()->action('ProfileController@showProfile');
// Группы роутов
Route::group([
    'namespace' => 'Api',
    'prefix' => '/api/v1'
], function() {
    // RESTful контроллер
    Route::controller('/auth', 'AuthController');
});
$ php artisan route:list


POST                           | api/v1/auth/login/{one?}/{two?}/{three?}/{four?}/{five?}    |                      | App\Http\Controllers\Api\AuthController@postLogin             |            |
GET|HEAD                       | api/v1/auth/login/{one?}/{two?}/{three?}/{four?}/{five?}    |                      | App\Http\Controllers\Api\AuthController@getLogin              |            |
GET|HEAD                       | api/v1/auth/logout/{one?}/{two?}/{three?}/{four?}/{five?}   |                      | App\Http\Controllers\Api\AuthController@getLogout             |            |
GET|HEAD                       | api/v1/auth/register/{one?}/{two?}/{three?}/{four?}/{five?} |                      | App\Http\Controllers\Api\AuthController@getRegister           |            |
POST                           | api/v1/auth/register/{one?}/{two?}/{three?}/{four?}/{five?} |                      | App\Http\Controllers\Api\AuthController@postRegister          |            |
GET|HEAD|POST|PUT|PATCH|DELETE | api/v1/auth/{_missing}                                      |                      | App\Http\Controllers\Api\AuthController@missingMethod         |            |

Валидация

<?php
namespace App\Http\Controllers;

use App\Http\Controller;
use Illuminate\Http\Request;

class UserController extends Controller {
    
    public function create(Request $request) {

        // Автоматически высылает ошибки
        // Если запрос ajax, вернет json c кодом 422
        $this->validate($request, [
            'name' => 'required|string|min:6|max:30',
            'email' => 'required|email|unique:users',
            'password' => 'required|min:6|confirmed',
        ]);

        // do something
    }
}
Accepted
Active URL
After (Date)
Alpha
Alpha Dash
Alpha Numeric
Array
Before (Date)
Between
Boolean
Confirmed
Date
Date Format
Different
Digits
Digits Between
E-Mail
Exists (Database)
Image (File)
In
Integer
IP Address
JSON
Max
MIME Types (File)
Min
Not In
Numeric
Regular Expression
Required
Required If
Required Unless
Required With
Required With All
Required Without
Required Without All
Same
Size
String
Timezone
Unique (Database)
URL

Шаблонизатор

1. Построен по принципу DRY

2. Преобразуется в нативный PHP

@extends('layouts.master')

@section('title', 'Page Title')

@section('sidebar')
    @parent

    <p>This is appended to the master sidebar.</p>
@endsection

@section('content')
    <p>This is my body content.</p>
@endsection
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>@yield('title')</title>
</head>
<body>
    <aside class="g-sidebar">
        @yield('sidebar')
    </aside>
    <section class="g-content">
        @yield('content')
    </section>
</body>
</html>

layouts/master.blade.php

page.blade.php

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

@if(Auth::check())
    Привет, {{ Auth::user()->name }}
@else
    Мы тебя не знаем
@endif

// Неэкранированный вывод
{!! $post->text !!}

Хелперы

// asset()  
<link rel="stylesheet" href="{{ asset('css/main.css') }}">

// route()
echo route('profile');

// back()
return back();

// csrf_field();
<form>
{{ csrf_field() }}
</form>

// dd();
dd($user);

// view()
return view('main');

Настройка окружения

APP_ENV=local
APP_DEBUG=true
APP_KEY=SomeRandomString

DB_HOST=localhost
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync

MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

Тесты

class ExampleTest extends TestCase {

    public function testBasicExample()
    {
        $this->visit('/')
             ->see('Laravel 5')
             ->dontSee('Rails');
    }

    public function testNewUserRegistration()
    {
        $this->visit('/register')
             ->type('Taylor', 'name')
             ->check('terms')
             ->press('Register')
             ->seePageIs('/dashboard');
    }
    
    // Тестирование json api
    public function testBasicExample()
    {
        $this->post('/user', ['name' => 'Sally'])
             ->seeJson([
                'created' => true,
                ]);
    }
}

Artisan

$ php artisan help migrate


$ php artisan make:model User

$ php artisan make:controller PhotoController

$ php artisan make:migration create_products_table

$ php artisan route:list

// Можно создавать свои команды

$ php artisan make:console SendEmails --command=emails:send

Что не уместилось в доклад

Планировщик задач

Работа с почтой

Очереди

Сидинг данных

Middlewares

Сессии/Куки/Логи

Кэш

Работа с ФС

Admin panel

Dive into Laravel

By El Forastero

Dive into Laravel

  • 607