찾다
백엔드 개발PHP 튜토리얼[ Laravel 5.2 文档 ] Eloquent ORM -- 起步

1、简介

Laravel自带的 EloquentORM 提供了一个美观、简单的与数据库打交道的 ActiveRecord 实现,每张数据表都对应一个与该表进行交互的“模型”,模型允许你在表中进行数据查询,以及插入、 更新、删除等操作。

在开始之前,确保在 config/database.php文件中配置好了数据库连接。更多关于数据库配置的信息,请查看文档。

2、定义模型

作为开始,让我们创建一个 Eloquent 模型,模型通常位于 app目录下,你也可以将其放在其他可以被 composer.json文件自动加载的地方。所有Eloquent模型都继承自 Illuminate\Database\Eloquent\Model类。

创建模型实例最简单的办法就是使用 Artisan 命令 make:model:

php artisan make:model User

如果你想要在生成模型时生成数据库迁移,可以使用 --migration或 -m选项:

php artisan make:model User --migrationphp artisan make:model User -m

Eloquent 模型约定

现在,让我们来看一个 Flight模型类例子,我们将用该类获取和存取数据表 flights中的信息:

<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class Flight extends Model{    //}

表名

注意我们并没有告诉 Eloquent 我们的 Flight模型使用哪张表。默认规则是模型类名的复数作为与其对应的表名,除非在模型类中明确指定了其它名称。所以,在本例中,Eloquent 认为 Flight模型存储记录在 flights表中。你也可以在模型中定义 table属性来指定自定义的表名:

<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class Flight extends Model{    /**     * 关联到模型的数据表     *     * @var string     */    protected $table = &#39;my_flights&#39;;}

主键

Eloquent 默认每张表的主键名为 id,你可以在模型类中定义一个 $primaryKey属性来覆盖该约定。

时间戳

默认情况下,Eloquent 期望 created_at和 updated_at已经存在于数据表中,如果你不想要这些 Laravel 自动管理的列,在模型类中设置 $timestamps属性为 false:

a84b450c4152025a3d054999e516c140first();

Not Found 异常

有时候你可能想要在模型找不到的时候抛出异常,这在路由或控制器中非常有用, findOrFail和 firstOrFail方法会获取查询到的第一个结果。然而,如果没有任何查询结果, Illuminate\Database\Eloquent\ModelNotFoundException异常将会被抛出:

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

如果异常没有被捕获,那么HTTP 404 响应将会被发送给用户,所以在使用这些方法的时候没有必要对返回404响应编写明确的检查:

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

获取聚合

当然,你还可以使用查询构建器聚合方法,例如 count、 sum、 max,以及其它查询构建器提供的聚合方法。这些方法返回计算后的结果而不是整个模型实例:

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

5、插入/更新模型

基本插入

想要在数据库中插入新的记录,只需创建一个新的模型实例,设置模型的属性,然后调用 save方法:

<?phpnamespace App\Http\Controllers;use App\Flight;use Illuminate\Http\Request;use App\Http\Controllers\Controller;class FlightController extends Controller{    /**     * 创建一个新的航班实例     *     * @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模型实例的那么属性,当我们调用 save方法时,一条记录将会被插入数据库。 created_at和 updated_at时间戳在 save方法被调用时会自动被设置,所以没必要手动设置它们。

基本更新

save方法还可以用于更新数据库中已存在的模型。要更新一个模型,应该先获取它,设置你想要更新的属性,然后调用 save方法。同样, updated_at时间戳会被自动更新,所以没必要手动设置其值:

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

更新操作还可以同时修改给定查询提供的多个模型实例,在本例中,所有有效且 destination=San Diego的航班都被标记为延迟:

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

update方法要求以数组形式传递键值对参数,代表着数据表中应该被更新的列。

批量赋值

还可以使用 create方法保存一个新的模型。该方法返回被插入的模型实例。但是,在此之前,你需要指定模型的 fillable或 guarded属性,因为所有Eloquent模型都通过批量赋值(Mass Assignment)进行保护。

当用户通过 HTTP 请求传递一个不被期望的参数值时就会出现安全隐患,然后该参数以不被期望的方式修改数据库中的列值。例如,恶意用户通过 HTTP 请求发送一个 is_admin参数,然后该参数映射到模型的 create方法,从而允许用户将自己变成管理员。

所以,你应该在模型中定义哪些属性是可以进行赋值的,使用模型上的 $fillable属性即可实现。例如,我们设置 Flight模型上的 name属性可以被赋值:

<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class Flight extends Model{    /**     * 可以被批量赋值的属性.     *     * @var array     */    protected $fillable = [&#39;name&#39;];}

设置完可以被赋值的属性之后,我们就可以使用 create方法在数据库中插入一条新的记录。 create方法返回保存后的模型实例:

$flight = App\Flight::create([&#39;name&#39; => &#39;Flight 10&#39;]);

$fillable就像是可以被赋值属性的“白名单”,还可以选择使用 $guarded。 $guarded属性包含你不想被赋值的属性数组。所以不被包含在其中的属性都是可以被赋值的,因此,$guarded方法就像“黑名单”。当然,你只能同时使用其中一个——而不是一起使用:

<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class Flight extends Model{    /**     * 不能被批量赋值的属性     *     * @var array     */    protected $guarded = [&#39;price&#39;];}

在这个例子中,除了 $price之外的所有属性都是可以被赋值的。

其它创建方法

还有其它两种可以用来创建模型的方法: firstOrCreate和 firstOrNew。 firstOrCreate方法先尝试通过给定列/值对在数据库中查找记录,如果没有找到的话则通过给定属性创建一个新的记录。

firstOrNew方法和 firstOrCreate方法一样先尝试在数据库中查找匹配的记录,如果没有找到,则返回一个的模型实例。注意通过 firstOrNew方法返回的模型实例并没有持久化到数据库中,你还需要调用 save方法手动持久化:

// 通过属性获取航班, 如果不存在则创建...$flight = App\Flight::firstOrCreate([&#39;name&#39; => &#39;Flight 10&#39;]);// 通过属性获取航班, 如果不存在初始化一个新的实例...$flight = App\Flight::firstOrNew([&#39;name&#39; => &#39;Flight 10&#39;]);

6、删除模型

要删除一个模型,调用模型实例上的 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);

通过查询删除模型

当然,你还可以通过查询删除多个模型,在本例中,我们删除所有被标记为无效的航班:

$deletedRows = App\Flight::where(&#39;active&#39;, 0)->delete();

软删除

除了从数据库删除记录外,Eloquent还可以对模型进行“软删除”。当模型被软删除后,它们并没有真的从数据库删除,而是在模型上设置一个 deleted_at属性并插入数据库,如果模型有一个非空 deleted_at值,那么该模型已经被软删除了。要启用模型的软删除功能,可以使用模型上的 Illuminate\Database\Eloquent\SoftDeletestrait并添加 deleted_at列到 $dates属性:

<?phpnamespace App;use Illuminate\Database\Eloquent\Model;use Illuminate\Database\Eloquent\SoftDeletes;class Flight extends Model{    use SoftDeletes;    /**     * 应该被调整为日期的属性     *     * @var array     */    protected $dates = [&#39;deleted_at&#39;];}

当然,应该添加 deleted_at列到数据表。Laravel Schema构建器包含一个帮助函数来创建该列:

Schema::table(&#39;flights&#39;, function ($table) {    $table->softDeletes();});

现在,当调用模型的 delete方法时, deleted_at列将被设置为当前日期和时间,并且,当查询一个使用软删除的模型时,被软删除的模型将会自动从查询结果中排除。

判断给定模型实例是否被软删除,可以使用 trashed方法:

if ($flight->trashed()) {    //}

查询被软删除的模型

包含软删除模型

正如上面提到的,软删除模型将会自动从查询结果中排除,但是,如果你想要软删除模型出现在查询结果中,可以使用 withTrashed方法:

$flights = App\Flight::withTrashed()                ->where(&#39;account_id&#39;, 1)                ->get();

withTrashed方法也可以用于关联查询中:

$flight->history()->withTrashed()->get();

只获取软删除模型

onlyTrashed方法之获取软删除模型:

$flights = App\Flight::onlyTrashed()                ->where(&#39;airline_id&#39;, 1)                ->get();

恢复软删除模型

有时候你希望恢复一个被软删除的模型,可以使用 restore方法:

$flight->restore();

你还可以在查询中使用 restore方法来快速恢复多个模型:

App\Flight::withTrashed()        ->where(&#39;airline_id&#39;, 1)        ->restore();

和 withTrashed方法一样, restore方法也可以用于关联查询:

$flight->history()->restore();

永久删除模型

有时候你真的需要从数据库中删除一个模型,可以使用 forceDelete方法:

// 强制删除单个模型实例...$flight->forceDelete();// 强制删除所有关联模型...$flight->history()->forceDelete();

7、查询作用域

全局作用域

全局作用域允许我们为给定模型的所有查询添加条件约束。Laravel 自带的软删除功能就使用了全局作用域来从数据库中拉出所有没有被删除的模型。编写自定义的全局作用域可以提供一种方便的、简单的方式来确保给定模型的每个查询都有特定的条件约束。

编写全局作用域

自定义全局作用域很简单,首先定义一个实现 Illuminate\Database\Eloquent\Scope接口的类,该接口要求你实现一个方法:apply。需要的话可以在 apply方法中添加 where条件到查询:

<?phpnamespace App\Scopes;use Illuminate\Database\Eloquent\Scope;use Illuminate\Database\Eloquent\Model;use Illuminate\Database\Eloquent\Builder;class AgeScope implements Scope{    /**     * Apply the scope to a given Eloquent query builder.     *     * @param  \Illuminate\Database\Eloquent\Builder  $builder     * @param  \Illuminate\Database\Eloquent\Model  $model     * @return void     */    public function apply(Builder $builder, Model $model)    {        return $builder->where(&#39;age&#39;, &#39;>&#39;, 200);    }}

应用全局作用域

要将全局作用域分配给模型,需要重写给定模型的 boot方法并使用 addGlobalScope方法:

<?phpnamespace App;use App\Scopes\AgeScope;use Illuminate\Database\Eloquent\Model;class User extends Model{    /**     * The "booting" method of the model.     *     * @return void     */    protected static function boot()    {        parent::boot();        static::addGlobalScope(new AgeScope);    }}

添加作用域后,如果使用 User::all()查询则会生成如下SQL语句:

select * from `users` where `age` > 200

匿名的全局作用域

Eloquent还允许我们使用闭包定义全局作用域,这在实现简单作用域的时候特别有用,这样的话,我们就没必要定义一个单独的类了:

<?phpnamespace App;use Illuminate\Database\Eloquent\Model;use Illuminate\Database\Eloquent\Builder;class User extends Model{    /**     * The "booting" method of the model.     *     * @return void     */    protected static function boot()    {        parent::boot();        static::addGlobalScope(&#39;age&#39;, function(Builder $builder) {            $builder->where(&#39;age&#39;, &#39;>&#39;, 200);        });    }}

我们还可以通过以下方式移除全局作用:

User::withoutGlobalScope(&#39;age&#39;)->get();

移除全局作用域

如果想要在给定查询中移除指定全局作用域,可以使用 withoutGlobalScope:

User::withoutGlobalScope(AgeScope::class)->get();

如果你想要移除某几个或全部全局作用域,可以使用 withoutGlobalScopes方法:

User::withoutGlobalScopes()->get();User::withoutGlobalScopes([FirstScope::class, SecondScope::class])->get();

本地作用域

本地作用域允许我们定义通用的约束集合以便在应用中复用。例如,你可能经常需要获取最受欢迎的用户,要定义这样的一个作用域,只需简单在对应Eloquent模型方法前加上一个 scope前缀,作用域总是返回查询构建器:

<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class User extends Model{    /**     * 只包含活跃用户的查询作用域     *     * @return \Illuminate\Database\Eloquent\Builder     */    public function scopePopular($query)    {        return $query->where(&#39;votes&#39;, &#39;>&#39;, 100);    }    /**     * 只包含激活用户的查询作用域     *     * @return \Illuminate\Database\Eloquent\Builder     */    public function scopeActive($query)    {        return $query->where(&#39;active&#39;, 1);    }}

使用查询作用域

作用域被定义好了之后,就可以在查询模型的时候调用作用域方法,但调用时不需要加上 scope前缀,你甚至可以在同时调用多个作用域,例如:

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

动态作用域

有时候你可能想要定义一个可以接收参数的作用域,你只需要将额外的参数添加到你的作用域即可。作用域参数应该被定义在 $query参数之后:

<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class User extends Model{    /**     * 只包含给用类型用户的查询作用域     *     * @return \Illuminate\Database\Eloquent\Builder     */    public function scopeOfType($query, $type)    {        return $query->where(&#39;type&#39;, $type);    }}

现在,你可以在调用作用域时传递参数了:

$users = App\User::ofType(&#39;admin&#39;)->get();

8、事件

Eloquent模型可以触发事件,允许你在模型生命周期中的多个时间点调用如下这些方法: creating, created, updating, updated, saving, saved, deleting, deleted, restoring, restored。事件允许你在一个指定模型类每次保存或更新的时候执行代码。

基本使用

一个新模型被首次保存的时候, creating和 created事件会被触发。如果一个模型已经在数据库中存在并调用 save方法, updating/updated事件会被触发,无论是创建还是更新,saving/saved事件都会被调用。

举个例子,我们在服务提供者中定义一个Eloquent事件监听器,在事件监听器中,我们会调用给定模型的 isValid方法,如果模型无效会返回 false。如果从Eloquent事件监听器中返回 false则取消 save/update操作:

<?phpnamespace App\Providers;use App\User;use Illuminate\Support\ServiceProvider;class AppServiceProvider extends ServiceProvider{    /**     * 启动所有应用服务     *     * @return void     */    public function boot()    {        User::creating(function ($user) {            if ( ! $user->isValid()) {                return false;            }        });    }    /**     * 注册服务提供者.     *     * @return void     */    public function register()    {        //    }}


성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
PHP vs. Python : 차이점 이해PHP vs. Python : 차이점 이해Apr 11, 2025 am 12:15 AM

PHP와 Python은 각각 고유 한 장점이 있으며 선택은 프로젝트 요구 사항을 기반으로해야합니다. 1.PHP는 간단한 구문과 높은 실행 효율로 웹 개발에 적합합니다. 2. Python은 간결한 구문 및 풍부한 라이브러리를 갖춘 데이터 과학 및 기계 학습에 적합합니다.

PHP : 죽어 가거나 단순히 적응하고 있습니까?PHP : 죽어 가거나 단순히 적응하고 있습니까?Apr 11, 2025 am 12:13 AM

PHP는 죽지 않고 끊임없이 적응하고 진화합니다. 1) PHP는 1994 년부터 새로운 기술 트렌드에 적응하기 위해 여러 버전 반복을 겪었습니다. 2) 현재 전자 상거래, 컨텐츠 관리 시스템 및 기타 분야에서 널리 사용됩니다. 3) PHP8은 성능과 현대화를 개선하기 위해 JIT 컴파일러 및 기타 기능을 소개합니다. 4) Opcache를 사용하고 PSR-12 표준을 따라 성능 및 코드 품질을 최적화하십시오.

PHP의 미래 : 적응 및 혁신PHP의 미래 : 적응 및 혁신Apr 11, 2025 am 12:01 AM

PHP의 미래는 새로운 기술 트렌드에 적응하고 혁신적인 기능을 도입함으로써 달성 될 것입니다. 1) 클라우드 컴퓨팅, 컨테이너화 및 마이크로 서비스 아키텍처에 적응, Docker 및 Kubernetes 지원; 2) 성능 및 데이터 처리 효율을 향상시키기 위해 JIT 컴파일러 및 열거 유형을 도입합니다. 3) 지속적으로 성능을 최적화하고 모범 사례를 홍보합니다.

PHP의 초록 클래스 또는 인터페이스에 대한 특성과 언제 특성을 사용 하시겠습니까?PHP의 초록 클래스 또는 인터페이스에 대한 특성과 언제 특성을 사용 하시겠습니까?Apr 10, 2025 am 09:39 AM

PHP에서, 특성은 방법 재사용이 필요하지만 상속에 적합하지 않은 상황에 적합합니다. 1) 특성은 클래스에서 다중 상속의 복잡성을 피할 수 있도록 수많은 방법을 허용합니다. 2) 특성을 사용할 때는 대안과 키워드를 통해 해결할 수있는 방법 충돌에주의를 기울여야합니다. 3) 성능을 최적화하고 코드 유지 보수성을 향상시키기 위해 특성을 과도하게 사용해야하며 단일 책임을 유지해야합니다.

DIC (Dependency Injection Container) 란 무엇이며 PHP에서 사용하는 이유는 무엇입니까?DIC (Dependency Injection Container) 란 무엇이며 PHP에서 사용하는 이유는 무엇입니까?Apr 10, 2025 am 09:38 AM

의존성 주입 컨테이너 (DIC)는 PHP 프로젝트에 사용하기위한 객체 종속성을 관리하고 제공하는 도구입니다. DIC의 주요 이점에는 다음이 포함됩니다. 1. 디커플링, 구성 요소 독립적 인 코드는 유지 관리 및 테스트가 쉽습니다. 2. 유연성, 의존성을 교체 또는 수정하기 쉽습니다. 3. 테스트 가능성, 단위 테스트를 위해 모의 객체를 주입하기에 편리합니다.

SPL SplfixedArray 및 일반 PHP 어레이에 비해 성능 특성을 설명하십시오.SPL SplfixedArray 및 일반 PHP 어레이에 비해 성능 특성을 설명하십시오.Apr 10, 2025 am 09:37 AM

SplfixedArray는 PHP의 고정 크기 배열로, 고성능 및 메모리 사용이 필요한 시나리오에 적합합니다. 1) 동적 조정으로 인한 오버 헤드를 피하기 위해 생성 할 때 크기를 지정해야합니다. 2) C 언어 배열을 기반으로 메모리 및 빠른 액세스 속도를 직접 작동합니다. 3) 대규모 데이터 처리 및 메모리에 민감한 환경에 적합하지만 크기가 고정되어 있으므로주의해서 사용해야합니다.

PHP는 파일 업로드를 어떻게 단단히 처리합니까?PHP는 파일 업로드를 어떻게 단단히 처리합니까?Apr 10, 2025 am 09:37 AM

PHP는 $ \ _ 파일 변수를 통해 파일 업로드를 처리합니다. 보안을 보장하는 방법에는 다음이 포함됩니다. 1. 오류 확인 확인, 2. 파일 유형 및 크기 확인, 3 파일 덮어 쓰기 방지, 4. 파일을 영구 저장소 위치로 이동하십시오.

Null Coalescing 연산자 (??) 및 Null Coalescing 할당 연산자 (?? =)은 무엇입니까?Null Coalescing 연산자 (??) 및 Null Coalescing 할당 연산자 (?? =)은 무엇입니까?Apr 10, 2025 am 09:33 AM

JavaScript에서는 NullCoalescingOperator (??) 및 NullCoalescingAssignmentOperator (?? =)를 사용할 수 있습니다. 1. 2. ??= 변수를 오른쪽 피연산자의 값에 할당하지만 변수가 무효 또는 정의되지 않은 경우에만. 이 연산자는 코드 로직을 단순화하고 가독성과 성능을 향상시킵니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

SublimeText3 Linux 새 버전

SublimeText3 Linux 새 버전

SublimeText3 Linux 최신 버전

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

VSCode Windows 64비트 다운로드

VSCode Windows 64비트 다운로드

Microsoft에서 출시한 강력한 무료 IDE 편집기

mPDF

mPDF

mPDF는 UTF-8로 인코딩된 HTML에서 PDF 파일을 생성할 수 있는 PHP 라이브러리입니다. 원저자인 Ian Back은 자신의 웹 사이트에서 "즉시" PDF 파일을 출력하고 다양한 언어를 처리하기 위해 mPDF를 작성했습니다. HTML2FPDF와 같은 원본 스크립트보다 유니코드 글꼴을 사용할 때 속도가 느리고 더 큰 파일을 생성하지만 CSS 스타일 등을 지원하고 많은 개선 사항이 있습니다. RTL(아랍어, 히브리어), CJK(중국어, 일본어, 한국어)를 포함한 거의 모든 언어를 지원합니다. 중첩된 블록 수준 요소(예: P, DIV)를 지원합니다.