作为程序员一定要保持良好的睡眠,才能好编程

laravel-Eloquent基础使用

发布时间:2020-01-29



生成模型


在开始之前,让我们先来创建一个 Eloquent 模型。模型通常存放在 app 目录下,但是你也可以自由的放置在任何地方,只要它能够根据你的 composer.json 文件的指导进行自动的加载。所有的 Eloquent 模型都继承自 Illuminate\Database\Eloquent\Model 类。


最简单的创建一个模型类的方式就是使用 make:model Artisan 命令:

php artisan make:model User


当然也可以生成迁移文件,比如:

-m

-migration

php artisan make:model User --migration

php artisan make:model User -m




Eloquent 模型约定



现在,让我们来看一个 Flight 模型的示例,我们将通过它获取和存储数据库中 flights 表的数据:



表名 $table 

flight 模型自动对应数据库中的flights表,如果不是这张表 则可以 使用$table 属性指定表名。


主键 $primarykey

使用primarykey属性指定主键,默认是 id


时间戳 $timestamps

默认的,Eloquent 期望模型表中存在 created_at 和 updated_at 列,如果你不希望 Eloquent 自主的管理这两列,

你可以在模型中设置 $timestamps 属性为 false:


如果你需要自定义时间戳的格式,你可以设置 $dateFormat 属性。


数据库连接 $connection


默认的,所有的 Eloquent 模型都会使用应用配置的默认的数据库连接。default


如果你希望模型使用不同的数据库连接,你可以使用 $connection 属性。


还可以使用 setConnection($name) 这个方法,设置连接


可以使用 getConnectionName() 获取到当前的数据库连接






检索单个模型 / 统计

当然,除了可以从表中检索出所有的记录之外,你也可以使用 find 和 first 方法来从数据库中检索出单条的数据。这将会返回一个单独的模型实例:

// Retrieve a model by its primary key...
$flight = App\Flight::find(1);
// Retrieve the first model matching the query constraints...
$flight = App\Flight::where('active', 1)->first();


你也可以使用 find 方法时传递一个包含主键所组成的数组,这将返回所有匹配到记录的集合:

$flights = App\Flight::find([1, 2, 3]);

返回记录的集合



未发现时的异常


有时候,你可能希望在没有找到匹配的模型时抛出一个异常。这对路由或者控制器来说尤其有用。findOrFail 和 firstOrFail 方法可以从查询中检索出首个匹配的结果,但是,如果结果中没有匹配的项,那么会抛出一个 Illuminate\Database\Eloquent\ModelNotFoundException 异常:


$model = App\Flight::findOrFail(1);
$model = App\Flight::where('legs', '>', 100)->firstOrFail();

如果异常没有被捕获,那么会直接传递给用户一个 404 HTTP 响应。所以当你在使用这些方法时是没有必要编写明确的检查并返回 404 响应的:


Route::get('/api/flights/{id}', function ($id) {
  return App\Flight::findOrFail($id); 
});




检索统计


当然,你可以使用 count,sum,max 和其他 查询生成器 所提供的的 聚合函数。这些方法会返回适当的数值,而不是完整的模型实例:

$count = App\Flight::where('active', 1)->count();
$max = App\Flight::where('active', 1)->max('price');



基础插入

想要在数据库中插入新的记录,只需要简单的创建模型实例,然后设置模型的属性,再调用 save 方法就可以了:

<?php
namespace App\Http\Controllers;
use App\Flight;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class FlightController extends Controller
{
  /**
   * Create a new flight instance.
   *
   * @param Request $request
   * @return Response
   */
   public function store(Request $request)
   {
     // Validate the request...
     $flight = new Flight;
     $flight->name = $request->name;
     $flight->save();
   }
}


在这个例子中,我们简单的从流入的 HTTP 请求中的 name 参数分配到 App\Flight 模型实例的 name 属性上。

当我们调用 save 方法时,这条记录将会插入到数据库中,

同时 created_at 和 updated_at 时间戳也会自动的被进行设置,所以这并不需要进行手动的设置它们。


基础的更新

save 方法也可用来更新数据库中已经存在的数据模型。为了更新模型,你应该首先检索到它们,然后设置任何你想要更新的属性,接着调用 save 方法。这一次,updated_at 时间戳会自动的进行更新,所以你并不需要手动的更新这个值:


$flight = App\Flight::find(1);
$flight->name = 'New Flight Name';
$flight->save();

你也可以针对查询匹配的多个模型进行更新操作。比如,所有 active 并且 destination 为 San Diego 的航班将会被标记为延迟:


App\Flight::where('active', 1)
          ->where('destination', 'San Diego')
          ->update(['delayed' => 1]);

update 方法接收一个想要更新的列的键值对数组。


集合

对于像 allget 这样的 Eloquent 方法会返回多个结果,这将返回一个 Illuminate\Database\Eloquent\Collection 实例。Collection 类提供了各种有用的方法与 Eloquent 结果进行交互。当然,你可以简单的对集合进行循环,因为他实现了 ArrayAccess 接口:

foreach ($flights as $flight) {
  echo $flight->name;
}



对结果进行分块 chunk

如果你需要处理数千条 Eloquent 记录,那么你可以使用 chunk 方法。chunk 方法会从 Eloquent 模型中检索出一小块记录,然后将其传递给 Closure 进行处理。使用 chunk 方法在处理大量结果集时可有有效的降低内存的消耗:


Flight::chunk(200, function ($flights) {
  foreach ($flights as $flight) {
    //
  } 
});


传递到方法的第一个参数是你要设置进行分块的大小。而传递到第二个参数的闭包将会在从数据库检索出每块内容时进行调用。


批量赋值

你也可以使用 create 方法来在一行中存储一个新的模型。一个新增的模型实例将会从方法中返回。事实上,

在开始做这些之前,你需要先指定模型的 fillable 或者 guarded 属性,它们是针对批量赋值时的保护措施。


当用户通过 HTTP 请求传递一些意外的参数时,这可能会造成批量赋值时一些问题的出现,或许参数中存在一些你并不想改变的列值的参数。

比如,一个恶意的用户可能会在请求中嵌入一个 is_admin 参数,然后这些参数映射到你的 create 方法中,这就使用户将自己升级为了超级管理员。


所以,在开始之前,你需要先定义哪些模型属性是可以进行批量分配的。你可以使用模型 $fillable 属性,

让我们在 Flight 模型中添加允许 name 属性的批量赋值:



而 $fillable 就像是为批量赋值提供了一种白名单的机制。你也可以选择使用 $guarded。$guarded 属性应该包含一个你不想要进行批量赋值的属性所组成的数组。所有不在这个数组中的属性都将可以进行批量赋值。所以,$guarded 就像一个黑名单的功能。当然,你应该只使用 $fillable 或者 $guarded 中的一个,而不是全部:



例如:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model{
  /**
   * The attributes that aren't mass assignable.
   *
   * @var array
   */
   protected $guarded = ['price'];
   
   protected $fillable = [''];
   
}


其他插入方法 firstOrNew  firstOrCreate


firstOrNew 方法和 firstOrCreate 方法一样,但是它在模型没找到时只会返回一个新的模型实例,并不会在数据库中新增一条记录。

你需要手动的使用 save 方法来将其存储到数据库中:


这里也有其他两种方法可以使用批量赋值进行模型的创建:firstOrCreate 和 firstOrNew。

firstOrCreate 方法会尝试根据给定的列的键值对从数据库定位相关的模型。

如果相关的模型没有找到,那么会根据给定的属性在数据库中新增一条记录。






删除模型


你可以在模型实例中使用 delete 方法来删除模型:


$flight = App\Flight::find(1);


$flight->delete();


根据键删除存在的模型 (直接根据主键进行删除)


在上面的例子中,我们先从数据库中检索出相关的模型,然后才调用 delete 方法来进行删除。事实上,如果你知道了模型的主键,那么你完全可以不用去检索到它。你可以直接使用 destroy 方法来进行删除:


App\Flight::destroy(1);

App\Flight::destroy([1, 2, 3]);

App\Flight::destroy(1, 2, 3);




当前区间


当前区间允许你在模型中定义一些可以复用的常用的约束。比如,你可能经常需要检索一些受欢迎的用户。你可以简单的在模型方法中前置 scope 命名来定义一个区间.


区间应该总是返回一个查询生成器的实例:


<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
  /**
   * Scope a query to only include popular users.
   *
   * @return \Illuminate\Database\Eloquent\Builder
   */
   public function scopePopular($query)
   {
     return $query->where('votes', '>', 100);
   }
   /**
    * Scope a query to only include active users.
    *
    * @return \Illuminate\Database\Eloquent\Builder
    */
    public function scopePopular($query)
    {
      return $query->where('votes', '>', 100);
    }
    /**
     * Scope a query to only include active users.
     *
     * @return \Illuminate\Database\Eloquent\Builder
     */
     public function scopeActive($query)
     {
       return $query->where('active', 1);
     }
}

利用区间查询


一旦区间进行了定义,你可以在模型进行查询时调用区间方法,事实上,你在调用区间方法时并不需要包含 scope 前缀。你甚至可以链式的调用其它的区间:


$users = App\User::popular()->active()->orderBy('created_at')->get();




事件

Eloquent 模型可以触发多种事件,这允许你在模型的生命周期的各个关键点进行 hook 操作。你可以使用下面的方法进行 Hook:creating,created,updating,updated,saving,saved,deleting,deleted,restoring,restored。事件允许你轻松的在模型进行存储或更新操作时进行执行额外的操作。


基础用法

当一个新的模型首次进行存储操作时,会触发 creating 和 created 事件。如果模型已经存在于数据库中,并且调用 save 方法,那么 updating / updated 事件将会被触发。事实上,在这两种情况下,saving 和 saved 事件都会被触发。


举个示例,让我们在服务提供者中定义一个 Eloquent 事件监听器。在我们的事件监听器中,我们将在给定的模型中调用 isValid 方法,当模型并没有通过验证时将返回 false。如果从 Eloquent 事件监听器中返回 false,那么将取消 save / update 操作:



<?php
namespace App\Providers;
use App\User;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
  /**
   * Bootstrap any application services.
   *
   * @return void
   */
   public function boot()
   {
     User::creating(function ($user) {
       if (! $user->isValid()) {
         return false;
       }
     });
   }
   /**
    * Register the service provider.
    *
    * @return void
    */
    public function register()
    {
      //
    }
}



参考文档:https://www.jianshu.com/p/98e5de87816d