php教程如何快速上手 Laravel ?100 个实用小技巧分享

 所属分类:php教程

 浏览:170次-  评论: 0次-  更新时间:2022-12-12
描述:更多教程资料进入php教程获得。 Laravel 9 保姆级视频教程,想学不会都难!进入学习给大家提供一些 Laravel 使用的小技巧, 当然你有...
更多教程资料进入php教程获得。

Laravel 9 保姆级视频教程,想学不会都难!进入学习

给大家提供一些 Laravel 使用的小技巧, 当然你有任何想法欢迎 PR !

Github 地址:https://github.com/LaravelDaily/laravel-tips

控制器

单行为控制器

当你的控制器仅有一个方法的时候,不妨尝试下 __invoke() 方法来,让当前控制器变身为 “invokable” 控制器。

想要了解单行为控制器的好处以及用法请参考:

  • 翻译:Laravel 应用设计:单行为控制器的魅力
  • 翻译:如何更好地使用单行为控制器

单行为控制器的简单使用:

定义路由,如下:

Route::get('user/{id}', 'ShowProfile');
登录后复制

通过命令创建单行为控制器:

php artisan make:controller ShowProfile --invokable
登录后复制

修改控制器代码,如下:

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

重定向到指定控制器的指定方法

你可以通过 redirect() 重定向到某个路由或者某个链接,但是当你希望重定向到一个特定方法,并且需要携带一些参数的时候,action 方法可以帮你实现,代码如下:

return redirect()->action('SomeController@method', ['param' => $value]);
登录后复制

接口操作成功而无返回的简单处理

当你在接口执行了某些逻辑,但是不需要返回内容的时候,你可以直接返回 204 状态码。 在 Laravel 中这很容易实现:

Tips: 204 状态码说明

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

    return response()->noContent();
}
登录后复制

模型

Eloquent 的日期筛选

Laravel 的 Eloquent Orm 提供了 whereDay(), whereMonth(), whereYear(), whereDate()whereTime() 供你对日期进行筛选。简单例子:

$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();
登录后复制

Inter 类型数据的便捷操作 Increments(增加) 和 decrements(减少)

你如果仅仅是操作数字类型字段的增加(减少),你可以尝试下 increment()decrement()) 方法:

Post::find($post_id)->increment('view_count');
User::find($user_id)->increment('points', 50);
登录后复制

获取设置当前用户登录的信息

你可以使用 make:observer 来创建一个观察者,然后通过修改模型事件 creating() 来设定当前用户的信息,代码如下 :
详细使用可以查阅 Laravel 中的模型事件与 Observer

class PostObserver
{
    public function creating(Post $post)
    {
        $post->user_id = auth()->id();
    }
}
登录后复制

软删除后的数据批量恢复

当使用软删除删除数据之后,你可以通过以下方法批量恢复删除的数据:

Post::withTrashed()->where('author_id', 1)->restore();
登录后复制

特定模型字段的返回

默认的 Model::all() 会返回所有字段,不管你是否有需要,当然你也可以通过给 all() 传递参数来指定返回的列。如下:

$users = User::all(['id', 'name', 'email']);
登录后复制

失败或者成功的查询

findOrFail() 方法,可以在查询没有符合条件数据的时候直接抛出异常。

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

数据返回的列名称的自定义

在 Eloquent 查询中使用 select 可以设置查询的字段,然后你可以通过 “as” 给字段重命名为你想要的名称:

$users = DB::table('users')->select('name', 'email as user_email')->get();
登录后复制

查询结果的 Map 处理

由于 Eloquent 中,get 方法将返回 Collection 类型的数据,所以在通过 get 方法获取数据之后,你可以直接通过 map() 方法来处理:

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

不使用 timestamps 相关字段

默认的,laravel 会在 migration 以及 model 中添加 timestamps 相关字段(created_at,updated_at),如果你不想使用他,你可以在migrate 中移除相关字段,或者在 model 中设置 timestamps属性,将该属性设置为 false 即可实现:

class Company extends Model
{
    public $timestamps = false;
}
登录后复制

修改默认时间字段

当你想要在已存在的数据库中使用 Laraevl 的 Eloquent Orm的时候,你的时间字段又不同于 Laravel 默认字段,这时候怎么处理呢?你可以通过给以下常量重新赋值来设置当前使用的时间戳字段:

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() 设定列为时间戳类型,通过
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.
详情阅读: 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('/\<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() 下包含了那些路由呢?
你可以在 /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视频教程】

以上就是如何快速上手 Laravel ?100 个实用小技巧分享的详细内容,更多请关注zzsucai.com其它相关文章!

 标签: php,Laravel,
积分说明:注册即送10金币,每日签到可获得更多金币,成为VIP会员可免金币下载! 充值积分充值会员更多说明»

讨论这个素材(0)回答他人问题或分享使用心得奖励金币

〒_〒 居然一个评论都没有……

表情  文明上网,理性发言!