Laravel Eloquent ORM 教程:Eloquent 之旅第一部分
Laravel 是优雅的 PHP Web 开发框架。具有高效、简洁、富于表达力等优点。采用 MVC 设计,是崇尚开发效率的全栈框架。是最受关注的 PHP 框架。
Eloquent ORM 内置在 Laravel 中,用于应用程序与数据库的交互。当你需要操作多种类型的数据库的时候,他提供了一种简单的封装,让你可以更简单的操作多种数据库,你只需要把你的查询语句写好,剩下的就交给 Eloquent ORM 吧!
我来举个例子解释一下我之前谈到的。假设你现在已经创建好一个laravel项目了,并且项目的config/database.php
中数据库类型也是正确的,在开箱即用的情况下,laravel默认使用MySQL,因此我们将在这篇文章中使用Mysql。
'default' => env('DB_CONNECTION', 'mysql')
数据库连接的数组配置中:
'mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
假设我们要创建一个博客平台,我们希望在数据库中有以下表(实体):
1.用户
2.岗位
3.评论
4.回复
Laravel开箱即用为我们提供了用户模型和create_users_table迁移文件,该文件位于我们项目的database/migrations
文件夹下(迁移是Laravel用于创建我们的数据库结构的PHP文件)。这里的用户模型表示我们项目的用户表中的一个实体。让我们看看app/
文件夹中的用户模型是什么样的。
//User.php
<?php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
/**
* 字段白名单,设置该属性后,不在白名单的字段无法写入。
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* 隐藏字段,设置该属性后,属性中的值将不会出现在你的查询结果中。
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* 类型的转换,属性中的值将被自动转换为目标类型,支持的类型 integer, real, float, double, decimal:<digits>, string, boolean, object, array, collection, date, datetime, 和 timestamp
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
通过代码可以看到 User 模型继承了 Authenticatable(Illuminate\Foundation\Auth\User
)类,该类继承了 Model 类,并实现了一系列接口。下面是 Authenticatable(Illuminate\Foundation\Auth\User
)类代码:
//Illuminate\Foundation\Auth\User.php
<?php
namespace Illuminate\Foundation\Auth;
use Illuminate\Auth\Authenticatable;
use Illuminate\Auth\MustVerifyEmail;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\Access\Authorizable;
class User extends Model implements
AuthenticatableContract,
AuthorizableContract,
CanResetPasswordContract
{
use Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail;
}
现在让我们把重点放到 Model 类的核心 Eloquent ORM 上来。
想要使用 Eloquent ORM 你需要继承 Illuminate\Database\Eloquent\Model
类,该类封装了一些数据库交互的基础操作。你可以通过以下命令创建 模型(model) 和 迁移(migration)。
$ php artisan make:model Post -m
Model created successfully.
Created Migration: 2020_01_07_015353_create_posts_table
此处参数 -m
的作用是在创建 Post 模型(model)的时候同时创建迁移(migration)。下面是我们通过上面命令创建的模型(model)。
//Post.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
//
}
可以看到该模型继承了 Illuminate\Database\Eloquent\Model
类, 这样你就可以使用 Eloquent ORM 的所有操作了!
属性 Protected $table
如果你的数据表名字和模型名称不一样,你可以通过设置该属性来自定义该模型关联的数据表;
protected $table = 'app_posts'; // 此处填写你的实际数据表名称
属性 Protected $primaryKey
Eloquent ORM 的默认主键是 id
,如果你的主键并非 id
你可以通过 $primaryKey
属性来自定义你的主键。
protected $primaryKey = 'post_id'; // 此处填写你的实际数据表主键
提示: 关于更多自定属性我们将在稍后陆续说明。
下面我们可以通过以下命令来执行迁移(migration),迁移是 Eloquent ORM 用来创建数据表的命令,以后你就可以通过代码创建数据表,这样做的好处是方便多人本地开发而造成的数据库同步问题。
$ php artisan migrate
在我们程序 database/migrations
中,我们可以找到名为 xxxx_xx_xx_xxxxxx_create_user_table.php 的文件,我们可以看到该文件中是一个继承了 Illuminate\Database\Migrations\Migration
名为 CreateUserTable
的类,该类中你可以在 up 方法中看到我们数据表中的列, Eloquent ORM 就是根据他来创建你的表的。
save() 方法
Laravel 框架提供了一系列快捷命令可以使用,然后运行以下命令:
$ php artisan tinker
然后我们就可以通过命令行交互的形式创建用户了。
>>> $user = new \App\User;
>>> $user->name = “Samfield Hawb”;
>>> $user->email = “samfield4sure@gmail.com”;
>>> $user->password = bcrypt(“secret”);
>>> $user->save(); //eloquent save() method
>>> exit
$ Exit: Goodbye
Eloquent ORM 的 save()
方法帮助我们将这里的的 User 实例($user)转化为相应操作的 Sql 语句,这样我们就不用再担心 Sql 问题了。
create() 方法
同样的 Eloquent ORM 提供了create()
静态方法,接受一个数组作为参数,数组 key 对应数据表列名。
$user = \App\User::create([
'name' => 'Samfield Hawb',
'email' => 'samfield4sure@gmail.com',
'password' => bcrypt('secret')//create an encrypted password
]);
create()
方法将返回一个 $user
实例。
属性 Protected $fillable
该命令会在数据表中插入一条新的数据。当然前提是我们已经将我们需要填充的字段写到 $fillable
白名单,Eloquent ORM 是默认保护所有字段的,这样做是为了避免 批量注入 安全问题,所以当你遇到字段未按你的预期填充相应字段问题的时候,请先检查该字段下是否已经在 $fillable
。
根据Laravel 文档可以看到:
当 Http 请求中携带大量的非约定字段的时候就会发生 批量注入 安全问题, 这将会影响你一些你预期之外的字段。例如,你表字段中存在 is_admin,如果恶意用户通过 Http 请求传递了 is_admin 参数,在你未做好足够判定的时候,他将会被提升为管理员。
所以,默认将全部字段加入保护属性是很有必要的,不要嫌麻烦,这是为了安全考虑。
/**
* 字段白名单
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',
];
属性 Protected $guarded
既然有白名单,那肯定会有相应的’黑名单’,属性 $guarded
就是为了这个产生的,guarded 意为守卫,添加在此属性中的字段将会受到保护。
/**
* 添加需要保护的字段
*
* @var array
*/
protected $gaurded = [
'password',
];
方法 all() method
我们可以通过 all()
方法来获取某个数据表中的全部数据,接上面的例子,现在获取我们的全部用户数据:
$users = App\User::all();
通过 all()
方法,Eloquent ORM 通过生成相应的 Sql 语句,查询并返回 User 表中所有数据的 集合。下面是生成的 sql 预览,(这里以 mysql 为例)
SELECT * from users
通过返回的数据 集合 我们可以轻松地操作数据,下面我们打印全部用户姓名:
foreach ($users as $user)
{
echo $user->name;
}
//Samfield Hawb
find()
Laravel Eloquent为我们提供了find()
方法,一种可用于获取一个或多个模型记录实例的方法。当你向find方法传递一个主键时,它返回与主键匹配的一条记录,如果找不到该记录,Eloquent就返回一个null。
$user = App\User::find(1);
在这里我们使用Eloquent查询一个id为1的用户模型
SELECT * FROM users WHERE id=1
find()
也可以接受数组
$users = App\User::find([1,2,3]);
完成此操作后,Eloquent底层会获取并返回传递给它的主键的记录集合。
findOrFail() 方法
大多数情况下,我们可能想在按主键查询不到模型时抛出错误。这里可以在我们的模型上通过调用 findOrFail()
方法来达成目的
$user = App\User::findOrFail(1);
当模型查询不到时,一个 Illuminate\Database\Eloquent\ModelNotFoundException
异常会被抛出。若不处理该异常,一个 404 超文本传输协议 响应会被自动返回给用户,这是 Laravel 处理 ModelNotFoundExeption
错误的方法。
结论
至此你已基本了解 eloquent 如何让查询变得简单。留意我的下一篇文章,我们将用行动继续了解 Eloquent ORM 超级力量的旅程。
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
推荐文章: