Eloquent关系基本可以分为:一对一、一对多及多对多。比如我们一个用户可以发表多篇文章,就是一对多的关系。这一节就是介绍 Laravel 5 中的Eloquent关系。
打开 app\User.php 用户模型,在 User
类中添加如下代码:
public function articles(){ return $this->hasMany('App\Article'); }
这样就可以通过 $user->articles
来获取用户的所有文章了。现在来实现通过 $article->user
来获取文章所属的用户,打开 app\Article.php,在 Article
类中添加:
public function user(){ return $this->belongsTo('App\User'); }
其中方法 user()
的名称可以自己随便定义,比如还可以叫 owner()
或者 writer()
等等。
现在还需要考虑我们的表结构,我们在表中还没有涉及到文章与用户的关联关系。现在打开之前我们创建的 migrations 文件 database\migrations\***_create_articles_table.php ,修改其中的 up()
方法:
public function up() { Schema::create('articles', function(Blueprint $table) { $table->increments('id'); // 指定文章所属用户ID $table->integer('user_id')->unsigned(); $table->string('title'); $table->text('body'); $table->timestamps(); $table->timestamp('published_at'); // 生成外键,并且指定在删除用户时同时删除该用户的所有文章 $table->foreign('user_id') ->references('id') ->on('users') ->onDelete('cascade'); }); }
上面的方法中,添加了指定文章所属用户的字段 user_id
,指定其为用户表 users
的外键,并且当用户表中该用户被删除的时候,同时删除该用户的所有文章。
因为是本地开发环境,所以我们直接执行回滚操作,更新数据表结构。切记在线上的环境一定不要这么做,可以创建一个新的 migration
来完成该操作。
在命令行执行下面的命令:
D:\wamp\www\laravel5>php artisan migrate:refresh Rolled back: 2015_05_11_142009_add_excerpt_to_articles_table Rolled back: 2015_05_11_140813_create_articles_table Rolled back: 2014_10_12_100000_create_password_resets_table Rolled back: 2014_10_12_000000_create_users_table Nothing to rollback. Migrated: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_100000_create_password_resets_table Migrated: 2015_05_11_140813_create_articles_table Migrated: 2015_05_11_142009_add_excerpt_to_articles_table
现在来创建用户,虽然Laravel 5为我们提供了一套现成的用户系统,但是我们这里还是使用命令行 tinker 来完成。
D:\wamp\www\laravel5>php artisan tinker Psy Shell v0.4.1 (PHP 5.5.12 ΓÇö cli) by Justin Hileman >>> $user = new App\User; => <App\User #000000003bd871c8000000000acd1f5b> {} >>> $user->name = 'Specs'; => "Specs" >>> $user->email = '[email protected]'; => "[email protected]" >>> $user->password = bcrypt('password'); => "$2y$10$psEuDj9D81ZnNs083E7W9.SqvcEuLoAk4V5NuuDPC/xc.fU.1NMFq" >>> $user->save(); => true >>> App\User::first()->toArray(); => [ "id" => 1, "name" => "Specs", "email" => "[email protected]", "created_at" => "2015-06-07 12:41:37", "updated_at" => "2015-06-07 12:41:37" ]
用户密码必须要进行加密操作,bcrypt()
方法也可以用 Hash::make()
来替代。现成已经成功创建了一个新的用户。
现在来完成添加文章时与用户的关联操作。我们可以在控制器的 store()
方法中实现,但是现在我们先直接通过表单的一个隐藏域来完成,这样做是不安全的,实际环境中不可以使用该方法,下一节再来修复此问题。
打开 resources\views\articles\_form.blade.php ,在最上面添加:
{!! Form::hidden('user_id', 1) !!}
接着修改文章模型 Article.php,修改可填充字段:
protected $fillable = [ 'title', 'body', 'published_at', 'user_id' ];
这时浏览器中发布一篇新的文章试试。发布之后到命令行执行:
D:\wamp\www\laravel5>php artisan tinker Psy Shell v0.4.1 (PHP 5.5.12 ΓÇö cli) by Justin Hileman >>> App\Article::first()->toArray(); => [ "id" => 1, "user_id" => 1, "title" => "New Article", "body" => "This is a new article", "created_at" => "2015-06-07 12:52:02", "updated_at" => "2015-06-07 12:52:02", "published_at" => "2015-06-07 00:00:00", "excerpt" => null ] // 获取第一个用户所有文章 >>> $user = App\User::first(); => <App\User #0000000070d8f2d5000000001310ee1c> { id: 1, name: "Specs", email: "[email protected]", created_at: "2015-06-07 12:41:37", updated_at: "2015-06-07 12:41:37" } >>> $user->articles->toArray(); => [ [ "id" => 1, "user_id" => 1, "title" => "New Article", "body" => "This is a new article", "created_at" => "2015-06-07 12:52:02", "updated_at" => "2015-06-07 12:52:02", "published_at" => "2015-06-07 00:00:00", "excerpt" => null ] ]
此外:
>>> $user->articles(); // 返回一个一对多的Object => <Illuminate\Database\Eloquent\Relations\HasMany #0000000070d8f2ca000000001310ee1c> {} >>> $user->articles->toArray(); // 返回的是一个 collection => [ [ "id" => 1, "user_id" => 1, "title" => "New Article", "body" => "This is a new article", "created_at" => "2015-06-07 12:52:02", "updated_at" => "2015-06-07 12:52:02", "published_at" => "2015-06-07 00:00:00", "excerpt" => null ] ] //注意 使用 $user->articles 与 $user->articles() 的区别 >>> $user->articles()->get()->toArray(); => [ [ "id" => 1, "user_id" => 1, "title" => "New Article", "body" => "This is a new article", "created_at" => "2015-06-07 12:52:02", "updated_at" => "2015-06-07 12:52:02", "published_at" => "2015-06-07 00:00:00", "excerpt" => null ] ] // $user->articles() 可以添加查询条件,而$user->articles 则不能这么使用 >>> $user->articles()->where('title', 'New Article')->get()->toArray(); => [ [ "id" => 1, "user_id" => 1, "title" => "New Article", "body" => "This is a new article", "created_at" => "2015-06-07 12:52:02", "updated_at" => "2015-06-07 12:52:02", "published_at" => "2015-06-07 00:00:00", "excerpt" => null ] ]
上面通过用户获取了用户的所有文章,下面我们完成相反的操作,根据文章来获取用户信息。
>>> $article = App\Article::first(); => <App\Article #0000000073aaf26b000000001e78f0ec> { id: 1, user_id: 1, title: "New Article", body: "This is a new article", created_at: "2015-06-07 12:52:02", updated_at: "2015-06-07 12:52:02", published_at: "2015-06-07 00:00:00", excerpt: null } >>> $article->user->toArray(); => [ "id" => 1, "name" => "Specs", "email" => "[email protected]", "created_at" => "2015-06-07 12:41:37", "updated_at" => "2015-06-07 12:41:37" ]
现在假设我们的显示某个用户所有文章的 URL 为 http://laravel.dev/user/Specs/articles,在命令行演示则为:
>>> $user = App\User::where('name', 'Specs')->first(); => <App\User #0000000073aaf264000000001e78f0ec> { id: 1, name: "Specs", email: "[email protected]", created_at: "2015-06-07 12:41:37", updated_at: "2015-06-07 12:41:37" } >>> $articles = $user->articles->toArray(); => [ [ "id" => 1, "user_id" => 1, "title" => "New Article", "body" => "This is a new article", "created_at" => "2015-06-07 12:52:02", "updated_at" => "2015-06-07 12:52:02", "published_at" => "2015-06-07 00:00:00", "excerpt" => null ] ] // 把获取的数据返回给视图:return view('articles.index', compact('articles'));
本节关于Eloquent关系就到这里。
该篇属于专题:《Laravel 5 基础视频教程学习笔记》
hi_tp 2015/07/14 16:20
非常感谢能发布这一系列的教程
菲克李 2016/06/08 18:05
为什么没有删除操作呢?
Specs 2016/06/13 09:20
@ 删除很简单啊
菲克李 2016/06/16 10:55
@ 新人求教删除