Home  >  Article  >  PHP Framework  >  How to get started with Laravel quickly? 100 practical tips to share

How to get started with Laravel quickly? 100 practical tips to share

青灯夜游
青灯夜游forward
2022-09-27 20:26:232496browse

How to get started with Laravel quickly? 100 practical tips to share

To provide you with some tips for using Laravel, of course you are welcome to PR if you have any ideas!

Github address: https://github.com/ LaravelDaily/laravel-tips

Controller

Single Behavior Controller

When your controller only If there is a method, you might as well try the __invoke() method to transform the current controller into an "invokable" controller.

To understand the benefits and usage of single behavior controllers, please refer to:

Simple use of single-behavior controllers:

Define routes as follows:

Route::get('user/{id}', 'ShowProfile');

Create a single behavior controller through the command:

php artisan make:controller ShowProfile --invokable

Modify the controller code as follows:

class ShowProfile extends Controller
{
    public function __invoke($id)
    {
        return view('user.profile', [
            'user' => User::findOrFail($id)
        ]);
    }
}

Redirect to the specified method of the specified controller

You can redirect to a route or link through redirect(), but when you want to redirect to a specific method and need to carry some parameters, the action method can Help you implement it, the code is as follows:

return redirect()->action('SomeController@method', ['param' => $value]);

Simple processing of successful interface operation without return

When you execute certain logic on the interface, but do not need to return content , you can directly return the 204 status code. This is easy to do in Laravel:

Tips: 204 Status Code Description

public function reorder(Request $request)
{
    foreach ($request->input('rows', []) as $row) {
        Country::find($row['id'])->update(['position' => $row['position']]);
    }

    return response()->noContent();
}

Model

Eloquent’s date filtering

Laravel’s Eloquent Orm provides whereDay(), whereMonth(), whereYear() , whereDate() and whereTime() allow you to filter dates. Simple example:

$products = Product::whereDate('created_at', '2018-01-31')->get();
$products = Product::whereMonth('created_at', '12')->get();
$products = Product::whereDay('created_at', '31')->get();
$products = Product::whereYear('created_at', date('Y'))->get();
$products = Product::whereTime('created_at', '=', '14:13:58')->get();

Convenient operations for Inter type data Increments (increase) and decrements (decrease)

If you only operate the increase (decrease) of numeric type fields , you can try increment()decrement()) method:

Post::find($post_id)->increment('view_count');
User::find($user_id)->increment('points', 50);

Get and set the current user login information

You can use make:observer to create an observer, and then set the current user's information by modifying the model event creating(). The code is as follows: <br>For detailed usage, please refer to the model events and Observer in Laravel

class PostObserver
{
    public function creating(Post $post)
    {
        $post->user_id = auth()->id();
    }
}

Batch recovery of data after soft deletion

When the data is deleted using soft deletion, You can restore deleted data in batches through the following methods:

Post::withTrashed()->where('author_id', 1)->restore();

Return of specific model fields

DefaultModel::all() will Returns all fields, whether you need them or not. Of course, you can also specify the columns to be returned by passing parameters to all(). As follows:

$users = User::all(['id', 'name', 'email']);

Failed or successful query

findOrFail() method can directly throw an exception when querying no data that meets the conditions. .

$user = User::where('email', 'povilas@laraveldaily.com')->firstOrFail();

Customization of column names returned by data

Use select in an Eloquent query to set the fields of the query, and then you can rename the fields through "as" For the name you want:

$users = DB::table('users')->select('name', 'email as user_email')->get();

Map processing of query results

Since in Eloquent, the get method will return Collection type data, so get it through the get method After the data, you can process it directly through the map() method:

$users = User::where('role_id', 1)->get()->map(function (User $user) {
    $user->some_column = some_function($user);
    return $user;
});

Do not use timestamps related fields

By default, laravel will Add timestamps related fields (created_at, updated_at) in migration and model. If you don't want to use it, you can remove the related fields in migrate, or set the timestamps attribute in the model and set this attribute to false You can achieve:

class Company extends Model
{
    public $timestamps = false;
}

Modify the default time field

When you want to use Laraevl's Eloquent Orm in an existing database , your time field is different from Laravel's default field, how to deal with this? You can set the currently used timestamp field by reassigning a value to the following constant:

class Role extends Model{
    const CREATED_AT = 'create_time';
    const UPDATED_AT = 'update_time';
}

快速通过 created_at 排序

在此之前你是这样实现的:

User::orderBy('created_at', 'desc')->get();

当然,你也可以使用更简单的方式:

User::latest()->get();

默认 latest() 会通过 created_at 进行排序。

这里还有个反方法可以用: oldest()  将会通过 created_at 字段进行升序排序。

User::oldest()->get();

当然你也可以通过传递参数来执行想要进行排序的字段,如下:

$lastUpdatedUser = User::newest('updated_at')->first();

创建记录时的自增

当你在创建记录的时候,你同时希望对某个字段进行自增操作的时候,你可以在  boot()  方法中注册 creating 方法来实现。举个例子,现在你有个 “position” 字段,你希望在你完成新增操作的时候同时对该字段 +1 ,实现代码如下:

class Country extends Model {
    protected static function boot()
    {
        parent::boot();

        Country::creating(function($model) {
            $model->position = Country::max('position') + 1;
        });
    }
}

使用 whereRaw() 使查询效率更快

使用 whereRaw() 方法,通常可以使查询效率更高。例如你想获取 30+ 天未登录的用户,你可以通过以下实现:

User::where('active', 1)
    ->whereRaw('TIMESTAMPDIFF(DAY, created_at, updated_at) > ?', 30)
    ->get();

多个作用域

你可以同时创建多个作用域,当然可以在一个查询中使用多个作用域。

模型中定义:

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

public function scopeRegisteredWithinDays($query, $days) {
    return $query->where('created_at', '>=', now()->subDays($days));
}

controller 中使用:

$users = User::registeredWithinDays(30)->active()->get();

Carbon自动转换

如果你想使用 whereDate() 查询今天的记录,你可以通过直接 now() 而无需进行 ->toDateString(),因为他会自动转换。

// Instead of
$todayUsers = User::whereDate('created_at', now()->toDateString())->get();
// 不需要转换 now()
$todayUsers = User::whereDate('created_at', now())->get();

通过首字符分组

你可以通过任意你想实现的方式进行分组,下面是通过对姓名首字符的分组方法:

$users = User::all()->groupBy(function($item) {
    return $item->name[0];
});

限制数据列的更新

如果你希望设置一个不可更新的列,你可以通过以下方式实现:

class User extends Model
{
    public function setEmailAttribute($value)
    {
        if ($this->email) {
            return;
        }

        $this->attributes['email'] = $value;
    }
}

查询多个

Eloquent 方法 find() 可以通过传递数组参数实现多个记录的查询:

// Will return Eloquent Model
$user = User::find(1);
// Will return Eloquent Collection
$users = User::find([1,2,3]);

使用 UUID 替代 自增列

如果你不想在数据表中使用自增列要怎么办?下面叫你如何实现

数据迁移:

Schema::create('users', function (Blueprint $table) {
    // $table->increments('id');
    $table->uuid('id')->unique();
});

模型:

class User extends Model
{
    public $incrementing = false;
    protected $keyType = 'string';

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

        User::creating(function ($model) {
            $model->setId();
        });
    }

    public function setId()
    {
        $this->attributes['id'] = Str::uuid();
    }
}

模型关联

可排序的模型关联

你可以在你的关联中使用 orderBy对关联进行排序:

public function products()
{
    return $this->hasMany(Product::class);
}

public function productsByName()
{
    return $this->hasMany(Product::class)->orderBy('name');
}

有条件的模型关联

如果你在使用模型关联的时候经常需要额外的进行 where 查询,你可以直接通过对关联进行条件查询,实现方式如下:

Model:

public function comments()
{
    return $this->hasMany(Comment::class);
}

public function approved_comments()
{
    return $this->hasMany(Comment::class)->where('approved', 1);
}

对结果的筛选:havingRaw()

你可以在各种地方使用 RAW DB 查询,包括  groupBy()  和 havingRaw() 后面:

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

Eloquent has() 方法可以作用于深层的关联

Eloquent has() 方法可以通过 books.ratings 的方式,而使查询可以做用于更深层的关联上!

// Author -> hasMany(Book::class);
// Book -> hasMany(Rating::class);
$authors = Author::has('books.ratings')->get();

通过 Has 方法对 hasMany 数据限制

在一对多关联中, hasMany() 允许通过 has() 方法进行关联数据条数的限制:

// Author -> hasMany(Book::class)
$authors = Author::has('books', '>', 5)->get();

模型默认值

你可以通过 belongsTo 关联, to avoid fatal errors when calling it like {{ $post->user->name }} if $post->user doesn’t exist.

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

一次性创建多条关联记录

如果你定义了 hasMany()  关联,你可以通过 saveMany() 来一次性创建多条关联数据:

$post = Post::find(1);
$post->comments()->saveMany([
    new Comment(['message' => 'First comment']),
    new Comment(['message' => 'Second comment']),
]);

快速且精确的加载

通过 with 你可以获取关联表甚至特定字段信息:

$users = App\Book::with('author:id,name')->get();

你可以使用他获取更深一层次的关联:

$users = App\Book::with('author.country:id,name')->get();

上级信息的级联更新

例如你想在更新评论信息的时候想同时更新上级关联的帖子信息的 updated_at 字段,你可以通过指定 $touch 属性实现:

class Comment extends Model{
    protected $touches = ['post'];
 }

总是检测关联是否存在

永远不要在未检测关联是否存在的情况下使用 $model->relationship->field

It may be deleted for whatever reason, outside your code, by someone else’s queued job etc.

可以通过 if-else,在 Blade 中使用 {{ $model->relationship->field ?? '' }} , 或者 {{ optional($model->relationship)->field }} 进行检测。

使用 withCount() 获取记录条数

如果你定义了 hasMany() 关联,当你想要统计关联数据的数量的时候,尝试下 withCount 吧。例子, 假如你有一个 Post 模型,该模型会有多个 Comments 关联,看下如何使用 withCount() 吧:

public function index(){
    $users = User::withCount(['posts', 'comments'])->get();
    return view('users', compact('users'));
 }

然后在模板文件中使用  {relationship}_count 属性就可以获取相应的数据统计了:

@foreach ($users as $user)
<tr>
    <td>{{ $user->name }}</td>
    <td class="text-center">{{ $user->posts_count }}</td>
    <td class="text-center">{{ $user->comments_count }}</td>
</tr>
@endforeach

关联查询的筛选条件

如果你想要在加载关联的时候做一些条件限制,可以通过回调函数实现。例如你想获取国家的前3个城市,可以通过以下代码实现:

$countries = Country::with(['cities' => function($query) {
    $query->orderBy('population', 'desc');
    $query->take(3);}])->get();

始终加载关联

你即可以通过 $with 属性设置模型始终会加载的关联,也可以在构造函数中动态处理加载项:

class ProductTag extends Model
{
    protected $with = ['product'];

    public function __construct() {
        parent::__construct();
        $this->with = ['product'];

        if (auth()->check()) {
            $this->with[] = 'user';
        }
    }
}

belongsTo 和 hasMany 的使用

定义 belongsTo 关联和 hasMany 关联,这样可以在创建关联数据的时候有由系统填充关联字段信息:

// 如果定义了 Post -> belongsTo(User), and User -> hasMany(Post)...
// 以前你需要这样创建文章信息...
Post::create([
    'user_id' => auth()->id(),
    'title' => request()->input('title'),
    'post_text' => request()->input('post_text'),
]);

// 现在,你可以这样
auth()->user()->posts()->create([
    'title' => request()->input('title'),
    'post_text' => request()->input('post_text'),
]);

自定义归属关联名称

使用 as 可以重命名您的关联:

模型中定义:

public function podcasts() {
    return $this->belongsToMany('App\Podcast')
        ->as('subscription')
        ->withTimestamps();
}

控制器中使用:

$podcasts = $user->podcasts();foreach ($podcasts as $podcast) {
    // instead of $podcast->pivot->created_at ...
    echo $podcast->subscription->created_at;
}

数据迁移

迁移执行顺序

通过修改迁移文件的时间戳前缀可以达到排序迁移执行数据的目的。例如:将2018_08_04_070443_create_posts_table.php 修改为 2018_07_04_070443_create_posts_table.php ( 修改 2018_08_042018_07_04 ).

Migration 设定时间戳时区

迁移中 timestamps()timestampsTz() 都可以设定时区。

Schema::create('employees', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->string('email');
    $table->timestampsTz();
});

另外还有 dateTimeTz(), timeTz(), timestampTz(), softDeletesTz().

数据 Migrations 类型

一些特定值得迁移类型:

$table->geometry('positions');
$table->ipAddress('visitor');
$table->macAddress('device');
$table->point('position');
$table->uuid('id');

更多类型查阅: official documentation.

默认时间戳

通过 timestamp() 设定列为时间戳类型,通过<br>useCurrent() 设定该列的默认值。

$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->useCurrent();

视图

foreach 中 $loop 的使用

通过 $loop 判断该数据是否是最先/最后的数据:

@foreach ($users as $user)
     @if ($loop->first)
        This is the first iteration.
     @endif

     @if ($loop->last)
        This is the last iteration.
     @endif

     <p>This is user {{ $user->id }}</p>
@endforeach

当然他还有其他可用属性例如: $loop->iteration$loop->count.<br>详情阅读: official documentation.

如何判断 View 是否存在?

在你加载 view 之前你可以判断 view 是否存在,从而避免不必要的错误显示。

if (view()->exists('custom.page')) {
 // Load the view
 }

你可以提供多个 view 供选择:

return view()->first(['custom.dashboard', 'dashboard'], $data);

错误模板页面

快速创建特定错误的页面,你只要以该错误code命名并创建相应的 blade 即可。例如: 500(resources/views/errors/500.blade.php)/403(resources/views/errors/403.blade.php),系统会通过相应的 code 自动匹配错误显示页面。

直接使用 view

可以直接在路由中绑定需要显示的 view:

// 在 controller 绑定 view
Route::get('about', 'TextsController@about');
class TextsController extends Controller
{
    public function about()
    {
        return view('texts.about');
    }
}
// 直接在路由中绑定
Route::view('about', 'texts.about');

Blade @auth

在 Blade 中直接使用 auth() 可以判断以及获取当前登录的用户信息:

例子:

@if(auth()->user())
    // 用户已登录
@endif

或者更简单的方式:

@auth
    // 鉴权通过
@endauth

相反的方法 @guest

@guest    
// 鉴权未通过
@endguest

Blade中循环嵌套中使用 $loop

Blade 循环嵌套,可以通过 $loop 获取上层数据:

@foreach ($users as $user)
    @foreach ($user->posts as $post)
        @if ($loop->parent->first)
            This is first iteration of the parent loop.
        @endif
    @endforeach
@endforeach

自定义 Blade 指令

Laravel 提供了简单的方式自定义 Blade 指令,只需在  app/Providers/AppServiceProvider.php 注册自己的指令即可。例子:你想要使用新的标签替换 <br> 标签:

<textarea>@br2nl($post->post_text)</textarea>

将该指令添加到 AppServiceProvider 的  boot() 方法中:

public function boot()
{
    Blade::directive('br2nl', function ($string) {
        return "<?php echo preg_replace(&#39;/\<br(\s*)?\/?\>/i', \"\n\", $string); ?>";
    });
}

Blade 指令说明: IncludeIf, IncludeWhen, IncludeFirst

当你不确定 Blade 的组件是否存在的时候可以使用一下方法:

仅仅在存在时加载该组件:

@includeIf('partials.header')

仅仅在有权限的时候加载该组件

@includeWhen(auth()->user()->role_id == 1, 'partials.header')

当该组件不存在时,会加载默认组件:

@includeFirst('adminlte.header', 'default.header')

路由

路由组嵌套

路由组可以使用嵌套:

Route::group(['prefix' => 'account', 'as' => 'account.'], function() {
    Route::get('login', 'AccountController@login');
    Route::get('register', 'AccountController@register');

    Route::group(['middleware' => 'auth'], function() {
        Route::get('edit', 'AccountController@edit');
    });
});

子域通配符

你可以通过动态子域名创建相应的路由:

Route::domain('{username}.workspace.com')->group(function () {
    Route::get('user/{id}', function ($username, $id) {
        //
    });
});

What’s behind the routes?

Auth::routes() 下包含了那些路由呢?<br>你可以在 /vendor/laravel/ui/src/AuthRouteMethods.php 找到:

public function auth()
{
    return function ($options = []) {
        // Authentication Routes...
        $this->get('login', 'Auth\LoginController@showLoginForm')->name('login');
        $this->post('login', 'Auth\LoginController@login');
        $this->post('logout', 'Auth\LoginController@logout')->name('logout');
        // Registration Routes...
        if ($options['register'] ?? true) {
            $this->get('register', 'Auth\RegisterController@showRegistrationForm')->name('register');
            $this->post('register', 'Auth\RegisterController@register');
        }
        // Password Reset Routes...
        if ($options['reset'] ?? true) {
            $this->resetPassword();
        }
        // Password Confirmation Routes...
        if ($options['confirm'] ?? class_exists($this->prependGroupNamespace('Auth\ConfirmPasswordController'))) {
            $this->confirmPassword();
        }
        // Email Verification Routes...
        if ($options['verify'] ?? false) {
            $this->emailVerification();
        }
    };
}

Laravel 7 之前, 存在与文件 /vendor/laravel/framework/src/illuminate/Routing/Router.php

路由注入绑定

你可以通过绑定 user 参数 Route::get('api/users/{user}', function (App\User $user) { … } - 不仅仅可以通过自增 ID 字段筛选,也可以使用 {user}username 字段筛选,只要在模型中这样处理即可:

public function getRouteKeyName() {
    return 'username';
}

快速定义路由控制器

在此之前,你可能这样写:

Route::get('page', 'PageController@action');

上面写法在编辑器中无法从 route 直接跳转到相应的 controller 中,尝试一下方法:

Route::get('page', [\App\Http\Controllers\PageController::class, 'action']);

现在你可以在编辑器中直接点击 PageController 编辑器会根据路径自动找到相关文件(这需要你的编辑器支持,像 phpstorm)。

路由默认值

如果你你不想在路由匹配失败时显示 404 错误页面,你可以通过回调函数设置默认显示内容,这样在路由匹配失败的时候会直接显示你自定义的内容:

Route::group(['middleware' => ['auth'], 'prefix' => 'admin', 'as' => 'admin.'], function () {
    Route::get('/home', 'HomeController@index');
    Route::resource('tasks', 'Admin\TasksController');
});

// 其他路由
Route::fallback(function() {
    return 'Hm, why did you land here somehow?';
});

使用正则验证路由参数

我们可以直接在路由定义时使用  “where” 方法验证路由参数。一个非常典型的情况是在路由的前面加上语言设置, 像 fr/blogen/article/333 这样。我们如何确保这两个首字母不用于语言以外的其他字符串?

routes/web.php:

Route::group([
    'prefix' => '{locale}',
    'where' => ['locale' => '[a-zA-Z]{2}']
], function () {
    Route::get('/', 'HomeController@index');
    Route::get('article/{id}', 'ArticleController@show');
});

全局,访客,用户的限流

你可以通过 throttle:60,1 来限制单位时间内请求某个可连接的此处:

Route::middleware('auth:api', 'throttle:60,1')->group(function () {
    Route::get('/user', function () {
        //
    });
});

你可以针对不同用户组进行不同限制:

// maximum of 10 requests for guests, 60 for authenticated users
Route::middleware('throttle:10|60,1')->group(function () {
    //
});

Also, you can have a DB field users.rate_limit and limit the amount for specific user:

Route::middleware('auth:api', 'throttle:rate_limit,1')->group(function () {
    Route::get('/user', function () {
        //
    });
});

路由的Query params 参数设置

你可以通过 route 方法第二个参数,以数组的形式将query 参数绑定到路由:

Route::get('user/{id}/profile', function ($id) {
    //
})->name('profile');

$url = route('profile', ['id' => 1, 'photos' => 'yes']); // Result: /user/1/profile?photos=yes

验证

图片验证

你可以验证上传图片的尺寸:

['photo' => 'dimensions:max_width=4096,max_height=4096']

自定义验证错误消息

可以自定义现有规则的错误消息,只需要创建相应的语言文件即可 resources/lang/xx/validation.php

'custom' => [
     'email' => [
        'required' => 'We need to know your e-mail address!',
     ],
],

时间验证中的 “now” 和 “yesterday”关键字

您可以通过 before/after 规则来验证日期,并将各种字符串作为参数传递,例如:tomorrow, now, yesterday。 例如:'start_date' => 'after:now'。 它在底层使用 strtotime() 验证。

$rules = [
    'start_date' => 'after:tomorrow',
    'end_date' => 'after:start_date'
];

有条件的验证规则

如果你的验证规则需要同时满足额外的条件,在  FormRequest 方法中定义 withValidator()  添加你的条件即可:

use Illuminate\Validation\Validator;
class StoreBlogCategoryRequest extends FormRequest {
    public function withValidator(Validator $validator) {
        if (auth()->user()->is_admin) {
            $validator->addRules(['some_secret_password' => 'required']);
        }
    }
}

自定义验证消息

通过FormRequestmessages() 方法,你可以自定义验证错误提示信息:

class StoreUserRequest extends FormRequest
{
    public function rules()
    {
        return ['name' => 'required'];
    }

    public function messages()
    {
        return ['name.required' => 'User name should be real name'];
    }
}

验证前置操作

验证前置操作,如果你需要在验证之前对某些字段做一些处理, prepareForValidation() 可以实现该功能:

protected function prepareForValidation()
{
    $this->merge([
        'slug' => Illuminate\Support\Str::slug($this->slug),
    ]);
}

遇到错误时终止验证

默认情况下,laraevl 会在处理完成所有验证规则之后,将错误信息一并返回;当然如果你想在遇到第一个错误的时候就终止继续往下的验证你可以通过添加一下规则: bail

$request->validate([
    'title' => 'bail|required|unique:posts|max:255',
    'body' => 'required',
]);

Policies

一次性检测多个权限

@can Blade 指令可以检测当前用户是否有某个权限,但是当场景复杂点要怎么处理?比如当我在同时拥有多个权限才能进行某个操作的时候? @canany 指令了解下:

@canany(['update', 'view', 'delete'], $post)
    // 当前用户拥有以下其权限: 更新,显示或者删除文章
    @elsecanany(['create'], \App\Post::class)
    // 当前用户无法创建文章
    @endcanany

集合

不要在集合过滤中使用 NULL

你可以在 Eloquent 中使用 Null  过滤,但是在集合( collection )中,Null 过滤将不会生效:

// 这样可以
$messages = Message::where('read_at is null')->get();

// 这样无法正常返回
$messages = Message::all();
$unread_messages = $messages->where('read_at is null')->count();

// 这样也可以
$unread_messages = $messages->where('read_at', '')->count();

在集合上使用自定义 groupBy 回调

如果你想根据某些条件对结果进行分组处理,并且该条件列并非数据库字段,你可以通过 GroupBy 回调实现。

例如,如果你想按注册日期对用户进行分组,代码如下:

$users = User::all()->groupBy(function($item) {
    return $item->created_at->format('Y-m-d');
});

⚠️ Notice: User::all() 将返回集合类型数据,因此这是在集合上进行的 GroupBy 操作

集合的复用

当你在查询结果上使用  ->all() 或者 ->get() 方法的时候,该操作是针对结果集合进行的操作,不会再额外的进行查询操作。

$users = User::all();
echo 'Max ID: ' . $users->max('id');
echo 'Average age: ' . $users->avg('age');
echo 'Total budget: ' . $users->sum('budget');

鉴权

你链接 Auth::once() 吗?

Auth::once() 可以用于构建无状态请求,他不会产生任何 cookie信息,这很有利于接口的开发:

if (Auth::once($credentials)) {
    //
}

更新密码同时更新用户 token

在更新用户密码的同时更新用户 token 很有必要:

模型:

public function setPasswordAttribute($value){
    $this->attributes['password'] = $value;
    $this->attributes['api_token'] = Str::random(100);
}

邮件

将测试邮件存储到 laravel.log

开发过程中,你可能需要测试邮件发送,但是你有不希望测试邮件真正发送到客户邮箱,这时候你可以通过配置 .env 参数 MAIL_DRIVER=log 这样,邮件将会以文本的形式存储到 storage/logs/laravel.log ,而不会真正发送出去。

邮件预览

如果你使用 Mailables 为发送邮件提供服务,那么你可以直接在浏览器中浏览邮件预览,而不必真正的发送:

Route::get('/mailable', function () {
    $invoice = App\Invoice::find(1);
    return new App\Mail\InvoicePaid($invoice);
});

Laravel 通知的默认主题(subject)

如果你在使用 toMail() 发送邮件通知的时候,未指定相关主题(subject)laravel 提供了默认参数可以使用:

因此,你只需要有:

class UserRegistrationEmail extends Notification {
    //
 }

然后你就可以在注册完成收到一封注册邮件提醒。

发送通知

你可以通过 $user->notify() 发送通知给特定用户,你也可以通过 Notification::route() 发送给任何其他需要通知的地方:

Notification::route('mail', 'taylor@example.com')
        ->route('nexmo', '5555555555')
        ->route('slack', 'https://hooks.slack.com/services/...')
        ->notify(new InvoicePaid($invoice)
);

Artisan

Artisan 命令参数

当我们创建我们的 Artisan 命令的时候,可以通过 $this->confirm(), $this->anticipate(), $this->choice()  等方法询问并要求输入参数:

// 确认框
if ($this->confirm('Do you wish to continue?')) {
    //
}

// 附加可选项
$name = $this->anticipate('What is your name?', ['Taylor', 'Dayle']);

// 附加默认值
$name = $this->choice('What is your name?', ['Taylor', 'Dayle'], $defaultIndex);

维护模式

页面维护模式实现如下:

php artisan down

执行上面命令后,再访问站点的时候会得到 503 错误信息。

你也可以通过提供参数实现而外的效果:

  • message 参数指定显示信息
  • retry 参数设定页面重载时间
  • allow 允许访问的 IP
    php artisan down --message="Upgrading Database" --retry=60 --allow=127.0.0.1

当维护完成,运行一下命令上线吧!

php artisan up

数据工厂

Factory 的回调方法

有时候,你某些数据的插入/修改需要基于其他数据的完成,这时你可以通过回调方法实现,例子如下:

$factory->afterCreating(App\User::class, function ($user, $faker) {
    $user->accounts()->save(factory(App\Account::class)->make());
});

通过 Seeds/Factories 生成图片

Faker能生成的不仅仅是文本,还可以生成指定大小的图像:

$factory->define(User::class, function (Faker $faker) {
    return [
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'email_verified_at' => now(),
        'password' => bcrypt('password'),
        'remember_token' => Str::random(10),
        'avatar' => $faker->image(storage_path('images'), 50, 50)
    ];
});

日志和调试

给日志记录传递参数

你可以通过 Log::info() 来记录日志,或者 info() 快捷方法可以实现同样的效果。

Log::info('User failed to login.', ['id' => $user->id]);

更方便的方法 DD

你可以直接通过在查询结果之后的 ->dd() 操作来打印结果。

// Instead of
$users = User::where('name', 'Taylor')->get();
dd($users);
// Do this
$users = User::where('name', 'Taylor')->get()->dd();

【相关推荐:laravel视频教程

The above is the detailed content of How to get started with Laravel quickly? 100 practical tips to share. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:learnku.com. If there is any infringement, please contact admin@php.cn delete