首页 > PHP编程 > Laravel Eloquent Orm 使用指南

Laravel Eloquent Orm 使用指南

2015年10月11日

Laravel Eloquent Orm 使用指南

http://blog.ja168.net/laravel-eloquent-orm-guide-902.html

Laravel Eloquent ORM组件让数据库交互变的极其简单,在今天这个教程中我们将学习如何使用它,主要搞定以下内容:
  • 基本的CRUD方法
  • 建立一对一关系
  • 建立一对多关系
  • 建立多对多关系

Eloquent如何工作?

Eloquent Orm使用ActiveRecord模式与数据库进行交互,这意味着在你的MVC框架中所有的模型都对应着数据库中的某个表。

Bear模型对应着数据库Bears表,模型与表的这种对应关系可以使我们非常方便的查询数据库。

举个例子来说,如果你想从Bear模型中获得全部的bears,你只需简单的使用Bear:all()方法,它会生成真实的SQL语句并从数据库查询全部的结果集

下面是一些简单的示例:

介绍                           方法

查询所有的熊               Bear::all()

查询一条记录               Bear::find(id)

删除一条记录               Bear::delete(id)

So easy! 非常的简单!(神奇的是所有的模型都具有以上的方法)过一会我们就会用到它们。

示例应用程序

让我们一起来创建一个示例应用程序,首先要了解一下以下内容:

熊: 这个世界上有非常多的熊,他们有不同的种类(北极熊、灰熊……)、不同的体重甚至不同的危险等级。

鱼:每一只熊只能吃一条鱼(至少在这个例子中是这样)熊和鱼的这种关系我们称之为一对一关系

树:任何一只熊都非常喜欢爬树,他们会经常光顾很多棵树,熊和树的这种关系我们称之为一对多关系

野餐:熊可以搭帮结伙的一起野餐,这种关系是多对多关系

安装Laravel

开始使用Eloquent我们需要先设置数据库与应用程序,下边是简单的流程

  • 安装Laravel: composer install –prefer-dist
  • 修改我们的数据库配置app/config/database.php
  • 使用artisan创建数据库迁移
  • 创建Eloquent模型
  • 填充测试数据

作者说前两项都非常的简单就不浪费时间去说了,可是我却在安装Laravel时就浪费了大把时间……

创建数据迁移

我们需要创建三个数据表:bears,fish,picnics 关于数据迁移的更多内容请参考migrations

创建Bears的数据迁移:

1
php artisan migrate:make create_bears_table --create=bears

create_bears_table 会转化为类名CreateBearsTable–create后边的参数指表名

该命令执行之后会在app/database/migrations中生成一个文件create_bears-table.php(该文件会有前缀)修改该文件增加一些列:

1
2
3
4
5
6
7
8
9
10
Schema::create('bears', function(Blueprint $table)
{
    $table->increments('id');
    $table->string('name');
    $table->string('type');
    $table->integer('danger_level');
    $table->timestamps();
});

默认情况下,这些数据迁移都会包含自增列id,它也会同时创建时间戳用来记录创建与修改时间(created_at,updated_at),当修改记录时updated_at字段会自动更新

创建Fish的数据迁移

1
2
3
4
5
6
7
8
9
10
php artisan migrate:make create_fish_table --create=fish
        Schema::create('fish', function(Blueprint $table)
        {
            $table->increments('id');
            $table->integer('weight');
            $table->integer('bear_id');
            $table->timestamps();
        });

Eloquent模型中可以重新指定表的名称,起个有意义的表名(除非你想给自己找麻烦)

创建Tree的数据迁移

1
2
3
4
5
6
7
8
9
10
11
php artisan migrate:make create_trees_table --create=trees
        Schema::create('trees', function(Blueprint $table)
        {
            $table->increments('id');
            $table->string('type');
            $table->integer('age');
            $table->integer('bear_id');
            $table->timestamps();
        });

创建Picnic的数据迁移

1
2
3
4
5
6
7
8
9
10
php artisan migrate:make create_picnics_table --create=picnics
        Schema::create('picnics', function(Blueprint $table)
        {
            $table->increments('id');
            $table->string('name');
            $table->integer('taste_level');//好吃的程度
            $table->timestamps();
        });

创建关联表

我们需要将bears与picnic两者的关系用一个新表来保存用以定义多对多关系

1
2
3
4
5
6
7
8
9
10
php artisan migrate:make create_bears_picnics_table --create=bears_picnics
        Schema::create('bears_picnics', function(Blueprint $table)
        {
            $table->increments('id');
            $table->integer('bear_id');
            $table->integer('picnic_id');
            $table->timestamps();
        });

通过这个关系表我们就可以实现多对多关系【多个熊 vs 多个野餐】

迁移数据库

上边的那些迁移代码搞定之后执行以下命令就可以在数据库中创建表

1
php artisan migrate

Eloquent模型

现在我们已经搞定了迁移的工作,接下来我们需要增加一些演示数据,这时Eloquent可以闪亮登场了!在我们进行数据填充之前我们先创建模型,在模型中我们需要定义模型之间的关系。

Bear模型

让我们先看一看Bear的模型是什么样子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Bear extends Eloquent {
    // 以下字段可以被集体赋值
    protected $fillable = array('name', 'type', 'danger_level');
    // 定义模型关系
    // 每只熊有一条鱼可以吃
    //一对一
    public function fish() {
        return $this->hasOne('Fish'); // this matches the Eloquent model
    }
    // 每只熊都可以攀爬很多的树
    //一对多
    public function trees() {
        return $this->hasMany('Tree');
    }
    // 每只熊都可以吃很多野餐,随便造...
    // 多对多
    public function picnics() {
        return $this->belongsToMany('Picnic', 'bears_picnics', 'bear_id', 'picnic_id');
    }
}

集体赋值

当创建一个新的模型时您可以传递属性的数组到模型的构造函数。这些属性将通过集体赋值分配给模型。这是很方便的,但把用户的输入盲目地传给模型可能是一个严重的安全问题。如果把用户输入盲目地传递给模型,用户可以自由地修改任何或者全部模型的属性。基于这个原因,默认情况下所有 Eloquent 模型将防止集体赋值(参见手册解释)

定义关系

当定义关系时方法的名称可以根据你的需要进行定义。当想知道熊吃了哪条鱼时定义这个关系的方法就开始变的有意义。

return $this->hasOne(‘Fish’); 这一行代码的参数名称要匹配Fish这个模型(类名),我们可以通过以下方法定义不同的模型关系:hasOne,hasMany,belongsTo,belongsToMany等,更多详细请参考手册。

Eloquent模型与表的名称转换规则

默认情况下,当你定义一个模型名称时,应该使用单数型式,例如我们的Bear模型。Eloquent会使用小写的复数单词在查找数据库中查找表,在这个例子中Bear模型对应着bears表。

Fish模型

1
2
3
4
5
6
7
8
9
10
class Fish extends Eloquent {
    //weight,bear_id属性允许被集体赋值
    protected $fillable = array('weight', 'bear_id');
    //表名
    protected $table = 'fish';
    // 定义关联
    public function bear() {
        return $this->belongsTo('Bear');
    }
}

我们使用protected $table明确的为这个模型指定表的名称

如同定义Bear模型关系一样,我们需要定义一个逆向关联将Fish模型与Bear模型关联起来。

TreeModel模型

1
2
3
4
5
6
class Tree extends Eloquent {
    protected $fillable = array('type', 'age', 'bear_id');
    public function bear() {
        return $this->belongsTo('Bear');
    }
}

Picnic模型

1
2
3
4
5
6
class Picnic extends Eloquent {
    protected $fillable = array('name', 'taste_level');
    public function bears() {
        return $this->belongsToMany('Bear', 'bears_picnics', 'picnic_id', 'bear_id');
    }
}

像其他模型一样我们定义了集体赋值和模型关系。当定义多对多关系时我们应当使用belongsToMany而非hasMany,hasMany用以定义一对多关系

现在我们已经有了迁移类与模型类,可以使用Eloquent填充数据了,关于更多Eloquent的概念例如创建模型、CRUD优化、定义关系的信息请阅读Laravel Eloquent docs

数据填充

seed就是用来做数据初始化的,我们将在app/database/seeds/DatabaseSeeder.php中创建seed,通常情况下你可能希望创建多个seed文件,但为了更简单一些这个例子中我们只使用一个文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
class DatabaseSeeder extends Seeder {
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        Eloquent::unguard();
        $this->call('BearAppSeeder');
        $this->command->info("Bear app seeds finished.");
    }
}
class BearAppSeeder extends Seeder {
    public function run() {
        // 清空所有表数据
        DB::table('bears')->delete();
        DB::table('fish')->delete();
        DB::table('picnics')->delete();
        DB::table('trees')->delete();
        DB::table('bears_picnics')->delete();
        // 填充bears表
        // 我们将创建三个不同的熊
        // 第一只熊名为 Lawl,它非常的危险,由其是在它饥饿时
        $bearLawly = Bear::create(array(
                        'name'         => 'Lawly',
                        'type'         => 'Grizzly',
                        'danger_level' => 8
        ));
        // 第二只熊名为Cerms. 他可以大声吼叫,但至少不会伤人。
        $bearCerms = Bear::create(array(
                        'name'         => 'Cerms',
                        'type'         => 'Black',
                        'danger_level' => 4
        ));
        // 第三只熊名为Adobot. 乖乖熊竟然还喝饮料,完全无害。
        $bearAdobot = Bear::create(array(
                        'name'         => 'Adobot',
                        'type'         => 'Polar',
                        'danger_level' => 3
        ));
        //命令行文字提示
        $this->command->info('The bears are alive!');
        // 填充fish表
        // 鱼没有名子,反正也会被熊吃掉......
        // 从三个熊中可以提取到ID
        Fish::create(array(
        'weight'  => 5,
        'bear_id' => $bearLawly->id
        ));
        Fish::create(array(
        'weight'  => 12,
        'bear_id' => $bearCerms->id
        ));
        Fish::create(array(
        'weight'  => 4,
        'bear_id' => $bearAdobot->id
        ));
        $this->command->info('They are eating fish!');
        // 填充trees表
        Tree::create(array(
        'type'    => 'Redwood',
        'age'     => 500,
        'bear_id' => $bearLawly->id
        ));
        Tree::create(array(
        'type'    => 'Oak',
        'age'     => 400,
        'bear_id' => $bearLawly->id
        ));
        $this->command->info('Climb bears! Be free!');
        // 填充picnics表
        // we will create one picnic and apply all bears to this one picnic
        $picnicYellowstone = Picnic::create(array(
                        'name'        => 'Yellowstone',
                        'taste_level' => 6
        ));
        $picnicGrandCanyon = Picnic::create(array(
                        'name'        => 'Grand Canyon',
                        'taste_level' => 5
        ));
        // 关联bears与picnics
        // 熊熊聚餐,所有的能都能参加。
        $bearLawly->picnics()->attach($picnicYellowstone->id);
        $bearLawly->picnics()->attach($picnicGrandCanyon->id);
        $bearCerms->picnics()->attach($picnicYellowstone->id);
        $bearCerms->picnics()->attach($picnicGrandCanyon->id);
        $bearAdobot->picnics()->attach($picnicYellowstone->id);
        $bearAdobot->picnics()->attach($picnicGrandCanyon->id);
        $this->command->info('They are terrorizing picnics!');
    }
}

我们需要获得新添加记录的ID,当需要使用ID时利用$bearLawly->id,这样就不用硬编码ID数据,也不用担心ID错误导致记录关联失败,万事俱备,我们已经完成了所有准备工作。接下来运行下面的命令就将完成数据的填充工作:

1
php artisan db:seed

一切都是这样简单,数据已经成功录入到数据库中,接下来可以开始我们最有趣的部份Eloquent !

使用Eloquent查询数据库

当完成迁移与数据填充的工作之后,我们将进行一些实际的例子,使用Eloquent可以非常简单进行CRUD操作。

创建新记录

在上述BearAppSeeder类中我们已经学会了如何用::create方法创建新记录:),尝试下边的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
//创建一条新的记录
Bear::create(array(
    'name'         => 'Super Cool',
    'type'         => 'Black',
    'danger_level' => 1
));
// 创建记录的另一种方法:通过为属性赋值然后调用save方法
$bear               = new Bear;
$bear->name         = 'Super Cool';
$bear->type         = 'Black';
$bear->danger_level = 1;
// 插入记录
$bear->save();

另一种创建记录的方法是使用firstOrCreate()与firstOrNew(),他会首先去查询相关记录如果不存在则会去创建。

1
2
3
4
5
// 查询或创建记录
Bear::firstOrCreate(array('name' => 'Lawly'));
// 查找并生成实例
$bear = Bear::firstOrNew(array('name' => 'Cerms'));

查询与获取记录

所有的查询都非常的简单,下边是一些简单的例子

1
2
3
4
5
6
7
8
// 获得所有记录
$bears = Bear::all();
// 通过ID查询记录
$bear = Bear::find(1);
// 通过指定字段名称查询
$bearLawly = Bear::where('name', '=', 'Lawly')->first();
//查询危险等级大于5的熊记录
$dangerousBears = Bear::where('danger_level', '>', 5)->get();

更新记录

要更新一条记录你只需要先查询到它,然后更改属性,最后调用save方法,超级简单!

1
2
3
4
5
6
7
// 将名为Lawly熊的危险等级设置为10
// 先找到它
$lawly = Bear::where('name', '=', 'Lawly')->first();
// 修改属性
$lawly->danger_level = 10;
// 保存
$lawly->save();

删除记录

删除记录也许比修改记录还要简单,有两种方法可以实现:查找并调用delete删除你需要的记录或者使用destroy方法。

1
2
3
4
5
6
7
8
9
// 查找并删除记录
$bear = Bear::find(1);
$bear->delete();
// 删除记录
Bear::destroy(1);
// 删除多条记录
Bear::destroy(1, 2, 3);
// 危险等级大于5的熊全部干掉
Bear::where('danger_level', '>', 5)->delete();

暂时看来destroy属静态方法可以直接通过类名调用比较方便(通过索引删除记录),delete属于实力方法,删除比较灵活。

查询关系

这里是Eloquent最有趣的地方,在大多数应用程序中,你的数据库表之间都是有联系的,我们已经在模型中定义了这种关系:熊和鱼的1V1关系,熊与野餐的多V多关系。

一对一关系

开始让熊吃点鱼吧!通过模型之间的关系可以非常简单知道熊吃了哪一条鱼。

1
2
3
4
5
6
7
8
// 查找名为Adobot的能
$adobot = Bear::where('name', '=', 'Adobot')->first();
// Adobot 拥有哪一条鱼?
$fish = $adobot->fish;
// Adobot要吃的那条鱼重量是多少?
$fish->weight;
// 更快捷的方法来获得鱼的重量
$adobot->fish->weight;

一对多关系

这个例子我们看一下Lawly这头熊都爬了哪些树?

1
2
3
4
5
// 找到Lawly
$lawly = Bear::where('name', '=', 'Lawly')->first();
// 简单?
foreach ($lawly->trees as $tree)
    echo $tree->type . ' ' . $tree->age;

多对多关系

熊要去黄石公园野餐了 ^_^

1
2
3
4
5
6
7
8
9
10
// 先找到要去野餐的Cerms
$cerms = Bear::where('name', '=', 'Cerms')->first();
// 查看Cerms可以去哪里野餐?
foreach ($cerms->picnics as $picnic)
    echo $picnic->name . ' ' . $picnic->taste_level;
// 找到Grand Canyon这次野餐
$grandCanyon = Picnic::where('name', '=', 'Grand Canyon')->first();
// 都哪些熊去大峡谷野餐了?
foreach ($grandCanyon->bears as $bear)
    echo $bear->name . ' ' . $bear->type . ' ' . $bear->danger_level;

正如你所看到的,使用Eloquent模型可以非常方便的查询数据库

演示

我们来一个完整一点的例子,看看如何将数据传递给视图,我们需要创建一个路由与视图文件,检测一下我们已经学过的知识。
路由

1
2
3
4
5
Route::get('eloquent', function() {
    return View::make('eloquent')
    // 这里主要关注一下超牛的with,他可以将相关联的数据全部一并调出,短短一行代码其实内部作了许多事情……
    ->with('bears', Bear::all()->with('trees', 'picnics'));
});

视图

先创建视图文件:app/views/eloquent.blade.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Eloquent Bears</title>
    <!-- CSS -->
    <!-- BOOTSTRAP -->
    <link rel="stylesheet" href="blog.ja168.net">
    <style>
        body { padding-top:50px; } /* add some padding to the top of our site */
    </style>
</head>
<body class="container">
<div class="col-sm-8 col-sm-offset-2">
    <!-- BEARS -->
    <!-- loop over the bears and show off some things -->
    @foreach ($bears as $bear)
        <!-- GET OUR BASIC BEAR INFORMATION -->
        <h2>{{ $bear->name }} <small>{{ $bear->type }}: Level {{ $bear->danger_level }}</small></h2>
        <!-- SHOW OFF THE TREES -->
        <h4>Trees</h4>
        @foreach ($bear->trees as $tree)
            <p>{{ $tree->type }}</p>
        @endforeach
        <!-- SHOW OFF THE PICNICS -->
        <h4>Picnics</h4>
        @foreach ($bear->picnics as $picnic)
            <p>{{ $picnic->name }}: Taste Level {{ $picnic->taste_level }}</p>
        @endforeach
    @endforeach
</div>
</body>
</html>

结束语

这篇文章包含很多的信息,非常感谢你花这么长的时间来阅读希望它对你有所帮助吧啦吧啦…..看一下我们都研究了哪些东西?

  • 迁移
  • Eloquent模型
  • 数据填充
  • 定义关系
  • 数据库查询
  • 查询关系

我们已经研究了许多非常好的主题,但是还有非常多的地方需要去学习,更多的信息还是去查查文档吧!

原文:http://scotch.io/tutorials/php/a-guide-to-using-eloquent-orm-in-laravel

分类: PHP编程 标签: ,
本文的评论功能被关闭了.