Laravel教程 九:Eloquent Relationship

JellyBool

JellyBool

前奏

在开始正文之前,我们首先来说说在实际的开发中,经常会接触到几种常见的对应关系模式:

One-To-One //一对一

One-To-Many //一对多

Many-To-Many //多对多

不知道你对这些概念是一种什么样的感受,如果是不太理解的。你可以将这些概念应用到生活中,理解起来就很简单了,就举一个与我们在网上经常见到的例子:

User-To-Profile // One-To-One

User-To-Articles // One-To-Many

Article-To-Comments // One-To-Many

Articles-To-Tags // Many-To-Many

翻译过来就是:

  1. 一个用户对应一个用户档案

  2. 一个用户可以发表多篇文章

  3. 一篇文章可以有多个评论

  4. 而文章和标签确实多对多的关系,一篇文章可以有多个标签;一个标签可以属于多篇文章

在这些关系模型中,最难实现的就是Many-To-Many这种多对多的关系,但是我们这个简单地博客并没有用户管理,也就是并没有开放让用户注册,所以我们在这里还是要挑战一下难度,实现Articles-To-Tags这种Many-To-Many关系,借助Laravel的强大的Eloquent,实现这个功能还是比较顺心的。至于一对一和一对多这两种关系,可以触类旁通。

创建tags表

要实现Articles-To-Tags这种Many-To-Many关系,我们需要tags表和Tag模型,所以我们分别来创建之。

php artisan make:migration create_tags_table --create=tags

打开生成的migration文件,为up()方法增加一行代码:

public function up()
{
Schema::create('tags', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->timestamps();
});
}

这里我们增加了$table->string('name');这一行,这个字段表示为tags table添加一个name字段,代表标签的名字。

接下来,我们为tags表创建一个Tag模型:

php artisan make:model Tag

生成了Tag模型之后,我们先不用去管Tag.php文件,因为我们还需要一张关系表article_tag,这个表只存tag_idarticle_id,所以我们来创建之:

php artisan make:migration create_article_tag_table --create=article_tag

打开migration文件来为之加上tag_idarticle_id这两个字段:

public function up()
{
    Schema::create('article_tag', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('article_id')->unsigned()->index();
        $table->foreign('article_id')->references('id')->on('articles')->onDelete('cascade');
        $table->integer('tag_id')->unsigned()->index();
        $table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade');
        $table->timestamps();
    });
}

这里貌似就添加tag_idarticle_id这两个字段,但是用了很多行代码,我们只要是理解下面这个:

$table->foreign('article_id')->references('id')->on('articles')->onDelete('cascade');

foreign():外键
references():参照字段
on():参照表
onDelete():删除时的执行动作
这里是跟着删除,比如删除了某篇文章,我们将article_tag中包含article_id一样的记录也删除

最后,执行migration生成article_tag表:

php artisan migrate

OK,生成这两个表之后,我们就可以正式开始我们的工作了。

声明Eloquent的关系

Articles 和 Tags 是多对多的关系,所以我们需要在Article.php中声明下面的关系:

public function tags()
{
    return $this->belongsToMany('App\Tag');
}

Tag.php,也同样:

public function articles()
{
    return $this->belongsToMany('App\Article');
}

我们使用$this->belongsToMany()来表明Eloquent的关系,这里需要注意的是如果你的外键并不是article_idtag_id,你需要在第三个参数进行设置,写成类似下面这样:

public function articles()
{
    return $this->belongsToMany('App\Article','conversation_id');
}

OK,这样,我们的多对多关系就声明完毕了。

使用Select2

在开始之前,我们使用tinker生成几个tag,过程就不演示了,最后是这样的:

替代文字

然后,为了更好地用户体验,我们引入Select2,这个对选择多个选项的时候表现得异常完美。

Select2 用法:https://select2.github.io/examples.html

我们在app.blade.php引入Select2的css文件和js文件:

<link rel='stylesheet' href="/css/select2.css" type='text/css' media='all'/>
<script src="/js/jquery-2.1.0.min.js"></script>
<script src="/js/select2.full.min.js"></script>

<head></head>标签内,我们还引入了jquery,因为select2依赖于jquery,所以。注意文件的下载或来源,请自行获取。

引入之后,我们就可以在文件创建的页面依旧使用我们的Form来生成我们的选择框了,来到

articles/create.blade.php文件,在published_at下面添加一个输入表单:

<div class="form-group">
{!! Form::label('tag_list','选择标签') !!}
{!! Form::select('tag_list[]',$tags,null,['class'=>'form-control js-example-basic-multiple','multiple'=>'multiple']) !!}
</div>

这里需要注意的是tag_list[],如果我们只是使用tag_list,就只能选到一个标签,如果我们需要选择多个,我们需要已数组的形式来储存我们的标签,还有一个就是指定一下'multiple'=>'multiple',就是开启支持多选模式。然后$tags就是我们需要从数据库获tags表取到得数据,所以自然而然,我们到ArticleController中的create()方法中,稍微修改一下代码:

public function create()
{
    $tags = Tag::lists('name', 'id');
    //为了在界面中显示标签name,id为了在保存文章的时候使用。
    return view('articles.create',compact('tags'));
}

这里我们使用lists()方法将Tag中(tags数据表)nameid以一个Eluqoent的方式返回,你可以使用dd($tags),来看看。恩,这个时候来看看我们的create页面:

替代文字

这时候我们发现,样式并没有Select2那么好看,那是因为我们还没有初始化Select2,所以我们在create.blade.php写几行简单地js代码:

<script type="text/javascript">
$(function() {
    $(".js-example-basic-multiple").select2({
        placeholder: "添加标签"
    });
});
</script>

@endsection紧接着的上一行加上上面的代码,这里我们使用jquery的选择器,然后调用select2();来初始化我们的选择框,再来看看效果:

替代文字

很完美,我们将整个UI完善得还不错,我们用dd();来看看我们表单提交过来的是什么,在ArticleController中的store()方法中添加一行代码:

dd($request->all());

我们来看看效果:

替代文字

我们看到得tag_list是一个数组,里面的值并不是我们选择的标签的name,而是标签的id,这样我们就可以使用laravel提供的attach()来添加我们的标签了,这个attach()接受一个id的数组,这里正好!,所以我们来稍微来修改一下store()方法:

public function store(Requests\StoreArticleRequest $request)
{
    $input = $request->all();
    $input['intro'] = mb_substr($request->get('content'),0,64);
    $article = Article::create($input);
    $article->tags()->attach($request->input('tag_list'));
    return redirect('/');
}

我们这里首先将Article::create($input)赋予$article变量(Eloquent对象),然后使用$article->tags()->attach()来添加标签,并将我们的标签数组传给attach()方法,我们来看看有没有成功:

替代文字

这里的文章是发表成功了,我们再来看看我们的标签是否添加成功,来看看我们的article_tag表:

替代文字

是添加了三个标签,但是我们发现这个created_atupdated_at貌似有点问题,我们来修复一下,在Article.php中的tags()方法中:

public function tags()
{
    return $this->belongsToMany('App\Tag')->withTimestamps();
}

我们在后面直接使用withTimestamps()来同步我们的时间,我们再来试一试:

替代文字

再来看看我们的数据库:

替代文字

看到最后的两个记录,很完美。

在视图中显示我们的tags

我们既然有了标签,我们为什么不来将它展示出来呢?在articles/index.blade.php中,我们来将文件的标签输出一下:

<h2 class="post-title pad">
<a href="/articles/{{ $article->id }}"> {{ $article->title }}</a>
</h2>
<ul class="post-meta pad group">
<li><i class="fa fa-clock-o"></i>{{ $article->published_at->diffForHumans() }}</li>
@if($article->tags)
    @foreach($article->tags as $tag)
        <li><i class="fa fa-tag"></i>{{ $tag->name }}</li>
    @endforeach
@endif
</ul>

我们在<h2>标签下面增加一个<ul>列表,然后是首先将发表日期published_at输出了,这里我们使用了Carbon的diffForHumans()方法,这个方法就会产生几分钟之前,几个小时之前的效果,这里也可以体会我们之前需要将published_at这个对象作为Carbon对象来对待了,如果是简单地字符串,是不能调用Carbon的diffForHumans()方法的。

接下来,我们使用$article->tags取得文章的标签,这个tags就是我们声明多对多关系的tags()方法。我们来看看效果:

替代文字

我们发现我们的多少分钟之前都是英文,那是因为我们没有设置Carbon,我们来修复一下,在app/Providers/AppServiceProvider.php中的boot()方法添加下面这一行:

\Carbon\Carbon::setLocale('zh');

然后刷新,见证一下奇迹吧:

替代文字

总结

到这里我们利用laravel提供的attach()方法将基本的多对多关系实现了,并且还稍微美化了一下输出,将published_at字段完美呈现。接下来我打算说一说怎么实现修改文章了,这是一个必走的流程嘛。所以。。。

最后,Happy Hacking

本文由 JellyBool 创作, 转载和引用遵循 署名-非商业性使用 2.5 中国大陆 进行许可。

共有 118 条评论

openwrtmail

be happy

shanyq1990 回复 openwrtmail

be happy

JellyBool

@openwrtmail 哈哈哈

lyon

话说,Laravel是自己开了缓存吗。折腾死哥哥了

JellyBool

@lyon 折腾什么?

lyon

@JellyBool 我在弄多对多,已选多个选项,然后提交后,数据库只选了一个。
折腾了半天,去别人宿舍浪了一圈回来,结果就好了。
内心几乎是崩溃的。

JellyBool

@lyon 这样啊,可能是跟机器有关,我貌似都没有遇到过

lyon

@JellyBool 应该是,今天又跑了5公里,回复帮你测试评论。我这边是可以的。

JellyBool

@lyon OK,刚刚上线,有bug就跟我说一下。。。

lyon

@JellyBool 对了,你有什么好点的laravel5的源码?分享几个,我看看。郁闷,英语太差了我。

JellyBool

@lyon 源码?是指项目源码么?还是?

lyon

就是别人放github上。让人看的那种。有好的推荐?

JellyBool

@lyon 是指做好的项目还是一个一个package?

Kirits
ErrorException in a5f9616cf474420fb858736d2834f686 line 27:
Undefined variable: tags (View: D:\laravel_v5\resources\views\articles\create.blade.php)

不知道为什么出现了上面的错误,数据库里面明明是有tags数据的。

<div class="form-group">
    {!! Form::label('tag_list','选择标签') !!}
    {!! Form::select('tag_list[]',$tags,null,['class'=>'form-control js-example-basic-multiple','multiple'=>'multiple']) !!}
</div>

我把

 {!! Form::select('tag_list[]',$tags,null,['class'=>'form-control js-example-basic-multiple','multiple'=>'multiple']) !!}

改成

{!! Form::select('tag_lis') !!}

后结果就变成一个没有下拉内容的小框框了

Kirits

我解决问题了,是由于我的create方法里面没有添加compact('tags'),所以报错了

public function create()
    {
        $tags = Tag::lists('name', 'id');
        //为了在界面中显示标签name,id为了在保存文章的时候使用。
        return view('articles.create');
    }
Kirits

在加入\Carbon\Carbon::setLocale('zh');出现了下面的错误,文件上面添加了

use Carbon\Carbon;

Call to undefined method Carbon\Carbon::setLocale()

JellyBool

@Kirits 这个头部不用使用use Carbon\Carbon;,直接写。

Kirits

没有使用use Carbon\Carbon;也是一样:
FatalErrorException in AppServiceProvider.php line 14:
Call to undefined method Carbon\Carbon::setLocale()

JellyBool

@Kirits 确定\Carbon\Carbon::setLocale('zh');这样写会报错?你把整个AppServiceProvider这个代码给我看看

Kirits
<?php namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider {

	/**
	 * Bootstrap any application services.
	 *
	 * @return void
	 */
	public function boot()
	{
		\Carbon\Carbon::setLocale('zh');
	}

	/**
	 * Register any application services.
	 *
	 * This service provider is a great spot to register your various container
	 * bindings with the application. As you can see, we are registering our
	 * "Registrar" implementation here. You can add your own bindings too!
	 *
	 * @return void
	 */
	public function register()
	{
		$this->app->bind(
			'Illuminate\Contracts\Auth\Registrar',
			'App\Services\Registrar'
		);
	}

}
Kirits

我也不明白哪里出错了

JellyBool

@Kirits 以后是代码就尽量放到Markdown的代码块里面吧。

openwrtmail

@JellyBool
我建议
1、评论框可以做一个enable/disable的选项。默认disable markdown功能。因为很多人不会markdown语法,这样会显得非常乱
2、将评论放在一个固定高度的div里面。然后做一个分页。按时间倒序就行。这样能突出正文。

JellyBool

@openwrtmail 这个Markdown应该不会去考虑。至于评论分页,会是这一周实现的任务,倒叙估计不会,不然读起来实在太困难了。

JellyBool

@Kirits 你装的是最新的laravel吧?

openwrtmail

评论正序也没啥问题,默认显示最后一页即可
@JellyBool

JellyBool

@openwrtmail 这个分页问题我来好好想想吧

Kirits

Markdown代码块?这个不会用,我装的是laravel 5.0版本的

JellyBool

@Kirits 你在vebdor/目录下有没有nesbot/carbon/这个目录,或者说你有这个包没有,这个包得版本是多少啊?

JellyBool

@openwrtmail @Kirits 鉴于目前分页还没有很好地实现,有什么问题你们直接开一个新的帖子吧?这样不用那么麻烦,而且问题又清晰一点。

https://laravist.com/discussion/create

Kirits

创建了一个新帖子,就返回首页了,找不到在哪里,在vebdor/目录下有nesbot/carbon/这个目录,不知道怎样看版本号,但是在nesbot/carbon/下面的readme有一句{
“require”: {
“nesbot/carbon”: “~1.14”
}
}
不知道这个是不是版本号

JellyBool

试一试这个"nesbot/carbon": "~1.19",

Kirits

直接改吗,还是要下载,找了一圈没找到下载的

JellyBool

直接改,然后composer update,应该就可以了

Kirits
 <script type="text/javascript">
        $(function() {
            $(".js-example-basic-multiple").select2({
                placeholder: "添加标签"
            });
        });
    </script>

不知道为什么我的section2有时能看到效果,有时候看不到效果

Kirits

后台显示了一个错误:Uncaught TypeError: $(...).select2 is not a function

JellyBool

@Kirits 你有没有引入这两个文件?

<script src="/js/jquery-2.1.0.min.js"></script>
<script src="/js/select2.full.min.js"></script>
Kirits

引用了,不过我现在改成


<script type="text/javascript">
            $(".js-example-basic-multiple").select2({
                placeholder: "添加标签"
        });
    </script>

反而可以了,有一个奇怪的现象就是“添加便签”的那个框是另一个框,而且样式跟你的不太一样,可惜这里不能发图片,我用邮箱发给你吧,你查收一下

JellyBool

@Kirits 评论的代码放到代码块里面吧,看看一点点Markdown内容就知道了,这样看起来会好很多,关于邮箱,发什么?

JellyBool

@Kirits 你看一下Markdown就知道怎么发图片了,评论是可以发图片的,你是不是声明了两个这个js-example-basic-multiple

JellyBool

@Kirits 额,将图片传到网上吧,再把地址连接…

Kirits

不太会lol 我再学学

JellyBool

这基本的知识而已,你想想,你本地的图片,别人怎么访问的到。。。

JellyBool

@Kirits 你的CSS样式没给好吧。你改一下select2的CSS样式就可以了吧

JellyBool

@Kirits 就是CSS样式而已,跟后端没有关系

Kirits

好吧,这个后面再改一下

JellyBool

@Kirits 恩恩

zhengmin4516

选好标签后上传出错啦,看不懂这个错误,好像跟数据库表有关系

解决了,粗心呢,哈哈

inlofter

感谢。

这篇文章是目前我所学laravel中最难的一篇了,看了两篇,才基本明白。写的很好啊,文档我看了三遍了,list(), attach()在文档中是一点也不明白是怎么用的,有本文的例子后,懂得一些了。

我想知道的是

  1. 选择多个标签,每个标签不同颜色是如何实现的?如laravist.com
    个人思考:在从数据库中取出tags后,在blade中使用js对tags进行添加颜色属性。是这样吗?如果是,怎样才能随机添加颜色属性;如果不是,应该怎样做呢?

  2. 文章的例子是选择标签,实际上,很多情况都是需要自己填写新标签,这样用应该怎样做呢?
    个人思考:tag_list显示的id数组,在点击提交后,先进行insert tags操作,然后再返回insert id,这样tag_list的id值就有了,最后进行文章数据插入。是这样吗?感觉怪怪的。

inlofter

@JellyBool 请看上面

JellyBool

第一,标签的不太颜色都是css定义的,就是使用的是类似下面的css选择器:

.tag-sm.database {
    background-color: #48466D;
    border: 1px solid #48466D;
}

上面的就是database的标签颜色。而在在发布页面的插入标签是使用css是使用类似下面的选择器的:

.select2-container--default .select2-selection--multiple .select2-selection__choice[title=Lumen] {
    background-color: #FF8A0C;
}

这个是lumen的标签,主要是根据[title=Lumen]不同来设置颜色。所以总得来说,这个没有使用js。

第二,这里的标签都是从数据库获取的。点击提交并不会插入tag id,而是主要负责在文章和标签的关系表插入数据。 @inlofter

inlofter

嗯。根据[title=Lumen] 不同来设置颜色。也就是说,每增加一个不同的标题,就需要手动设置一个css。或者说,需要事先将所有可能的标签都设置一遍颜色。

木有自动的方法么?

比如我的方法,设置一个颜色数组,用js用随机数,取到几就取出颜色数组的id与值,再添加颜色属性。这样不比需要事先一个个设定颜色值方便么?虽然我也不想用js,但想不到其它方法了。
@JellyBool

JellyBool

理论上是可以使用js这样做的,只是我简单粗暴而已 @inlofter

xiaohan

@Kirits 你上面那个CSS问题改正了吗?我也遇到了,请问怎么修改?

Kirits

@xiaohan 你说的是选择标签那里吗?还是这样,暂时没有解决

xiaohan

@Kirits 你要是解决了,一定要告诉我,很急很关键

Kirits

@xiaohan 终于解决了,是因为没有导入正确的select2版本,一上select2的官网,直接引用

<link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" rel="stylesheet" />
<script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.min.js"></script>
xiaohan

@Kirits 非常感谢 ! 对了,你会做文章评论的功能吗,我今天做了一天还不是很清楚。

xueyunlong67

博主,您写的很好很详细,但是我对于attach()方法还是有点小不懂,你也没说该方法作用体现在哪(就因为返回的是数组id?)??我的理解是用attach()是不是因为有多个标签要存入article_tag表所以才要用的,那如果不用attach(),会怎样呢?博主,尽情蹂躏我吧,@JellyBool

xueyunlong67

tags = Tag::lists('name', 'id'); 这个不就是返回一个数组其中以id值为键,name为值吗?为什么你下边 dd(request->all());
其中提交标签部分 返 回的却是 标签 的 id为值的数组,你上边 $tags没有查id,你查的是name,请问id哪来的???@JellyBool

dudushuang

@Kirits @JellyBool 我也遇到这个问题了。撸了一下你们的评论,照做了,不管用,你是怎么解决的?

@Kirits

fix丶ed
@JellyBool     \Carbon\Carbon::setLocale('zh');  在lavarel 4.2怎么修改。
fix丶ed

@JellyBool \Carbon\Carbon::setLocale(‘zh’); 在lavarel 4.2怎么修改。

woailuosj

@JellyBool

  • 我想做成用户能手动输入的标签,select2已经做好了数据的输入工作,
  • 来到后端,应该是把标签表中还没有的标签插入,有的标签就跳过吧,
  • 然后还需要获取用户插入的标签在数据表中的ID,再与对应的文章进行关联吧,这怎么做?
  • 谢谢
JellyBool

直接结合select2的ajax就好了 @woailuosj

woailuosj

@JellyBool

  • 用ajax去获取标签数据以及对应的ID?
  • 还是不知道怎么解决添加用户输入的标签的问题
小蛋炒小饭

@JellyBool 评论的表的字段能分享一下么?想实现一个QQ说说的功能,但是想不通逻辑。能给一个回避的方法么?或者将就本网页的评论表设计的逻辑分享一下。谢谢啊!

cxccxc

happy hacking!

Anonymous

“Laravel 5.1.11 版本新增了一个全新的“授权(Authorization)”模块,或者叫做 ACL(权限控制列表),这一功能能够帮开发者更容易地控制权限。为了配合这一模块,Laravel 中还新增了一个叫做 Gate 的 facade。”——来源于:http://www.golaravel.com/post/laravel-5-1-11-released/


楼主可以写一下上面这个怎么用吗?

Anonymous

这个系列可能不会涉及到,有必要后面再说吧

Anonymous

没有,更新了这个:

https://laravist.com/lesson/2

Anonymous

博主开学了,大家耐心等等吧。有什么问题可以发文章;一起讨论

Anonymous

这个实在不行。估计把这个写了更了之后,继续尝试录视频去

Anonymous

确实,事比较多。。也在完善laravist的功能

Anonymous

同为大三党,没你玩的6,

Anonymous

。。。。。为什么我一大串评论,变成了这几个字。

Anonymous

阿里云有个云翼计划,关于ECS服务器学生优惠的,今天下午刚入手了一台,你可以去看看。

Anonymous

这个没什么啊。。。其实本人还是比较水的,学习的地方还很多

Anonymous

暑假的时候我在用db在控制器里面写逻辑。现在想想。太傻。丢掉了优雅的部分。也一直没用Html包,就4.2刚学的时候用过一点。到现在我队列,邮件,缓存,都不会玩。[泪],意志不坚定,老是被其他编程语言绑架。

Anonymous

好嘛。。还好啦,刚开始都一样的吧

Anonymous

嗨,你好.,例子中使用的select2,怎样修改的样式?

Anonymous

这种封装不喜欢,还是喜欢自己写

Anonymous

感谢,对我帮助很大,看观望文档总是那么的让人想睡觉

hehorange

哎,博主中间省略了用tinker生成多条tags数据,我又绕了好多弯路。

用**create()**方法只能插入一条数据,不知道我的语法对不对?

App\Tag::create(
         array('name'=>'hehe'),
         array('name'=>'haha')
);

这样也是直插入一条:

App\Tag::create(['name'=>'haha'],['name'=>'again']);

DB::table插入了多行,但默认的created_at和updated_at字段却为0

DB::table('tags')->insert([['name'=>'he'],['name'=>'ha']]);

是语法错误还是什么问题?

cncici 回复 hehorange

App\Tag::create([[‘name’=>‘haha’],[‘name’=>‘again’]]);
应该是这样吧

hybridword

想咨询一下,这里面那个articles这张表需要有tag_list这个字段吗?

JellyBool 回复 hybridword

不是一定需要

hybridword

我现在提交的时候说这个tag_list这个字段不存在数据库当中

JellyBool 回复 hybridword

额。。你仔细看看文章。

tag_list 并不是直接保存到数据库,而是多对多写入第三张关联表的吧

hybridword 回复 JellyBool

头脑晕了,我在article里面可以获取的所属的专题
但是在专题下没有获取到相应的文章。

JellyBool 回复 hybridword

看看关系有没有声明对…获取的时候有写对代码?

hybridword 回复 JellyBool

这个是文章的model

public function columns()
   {
     return $this->belongsToMany('App\Http\Model\Column','article_column','art_id','column_id')->withTimestamps();
   }

这个是专题的model

public function articles()
   {
     return $this->belongsToMany('App\Http\Model\Article','article_column','art_id','column_id')->withTimestamps();
   }

这是控制器的

$columns=Column::find($request->id);
         $articles=$columns->articles()->get();
         
        return $articles;
        exit();

然而发现没有哪里不对

JellyBool 回复 hybridword

直接 $columns->articles 有数据么?

hybridword 回复 JellyBool

没有,吃了个饭,已经解决了哈!

JellyBool 回复 hybridword

OK……我在外边吃饭中

vartist

为什么上一篇没了?

18701297334

我用的是laravel5.1版本在ORM的一对多关系模型中(用户和文章)当删除用户的时候 用户发表的帖子却不能删除 文章表的迁移文件中已经设置了onDelete 两个模型从属关系也已经设置好

chinkiver

migrate 创建 $table->foreign(‘article_id’)->references(‘id’)->on(‘articles’)->onDelete(‘cascade’);
难道不需要单独创建一个叫“articles”的表吗?

JellyBool 回复 chinkiver

这个就是:

Schema::create('articles', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title', 100);
            $table->text('content');
            $table->timestamps();
        });
chinkiver

我的tags表

    public function up()
    {
        Schema::create('tags', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name', 50);
            $table->timestamps();
        });
    }

我的article_tag表

    public function up()
    {
        Schema::create('article_tag', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('article_id')->unsigned()->index();
            $table->foreign('article_id')->references('id')->on('articles')->onDelete('cascade');
            $table->integer('tag_id')->unsigned()->index();
            $table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade');
            $table->timestamps();
        });
    }

我的articles表

    public function up()
    {
        Schema::create('articles', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title', 100);
            $table->text('content');
            $table->timestamps();
        });
    }

执行php artisan migrate

Migration table created successfully.



  [Illuminate\Database\QueryException]

  SQLSTATE[HY000]: General error: 1005 Can't create table `laraveltest`.`#sql-111c_37` (errno: 150 "Foreign key cons
train
  t is incorrectly formed") (SQL: alter table `article_tag` add constraint article_tag_article_id_foreign foreign ke
y (`a
  rticle_id`) references `articles` (`id`) on delete cascade)






  [PDOException]

  SQLSTATE[HY000]: General error: 1005 Can't create table `laraveltest`.`#sql-111c_37` (errno: 150 "Foreign key cons
train
  t is incorrectly formed")




chinkiver

我的tags表

    public function up()
    {
        Schema::create('tags', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name', 50);
            $table->timestamps();
        });
    }

我的article_tag表

    public function up()
    {
        Schema::create('article_tag', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('article_id')->unsigned()->index();
            $table->foreign('article_id')->references('id')->on('articles')->onDelete('cascade');
            $table->integer('tag_id')->unsigned()->index();
            $table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade');
            $table->timestamps();
        });
    }

我的articles表

    public function up()
    {
        Schema::create('articles', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title', 100);
            $table->text('content');
            $table->timestamps();
        });
    }

执行php artisan migrate

Migration table created successfully.



  [Illuminate\Database\QueryException]

  SQLSTATE[HY000]: General error: 1005 Can't create table `laraveltest`.`#sql-111c_37` (errno: 150 "Foreign key cons
train
  t is incorrectly formed") (SQL: alter table `article_tag` add constraint article_tag_article_id_foreign foreign ke
y (`a
  rticle_id`) references `articles` (`id`) on delete cascade)






  [PDOException]

  SQLSTATE[HY000]: General error: 1005 Can't create table `laraveltest`.`#sql-111c_37` (errno: 150 "Foreign key cons
train
  t is incorrectly formed")




jayin 回复 chinkiver

看文章挺好的

xiangxihenli

请教一个问题 现在我有几张张表格 user aritcle user_follows tag article_tag user_tag

我想实现用户关注文章标签实现关注内容的功能

在我取用户关注的文章时候 User::find($id)->tags()->

我只能做到这一步 接下来不知道用怎么通过tag去取文章了

这里 应该是两个多对多的关系 想问一下 怎么取获得用户关注标签的文章呢?

lanuit

请求将创建tags表中的up方法中的代码缩进改一下,强迫症看起来着实不舒服…

jayin

@JellyBool,两个表我要怎么指定每个表之间不同字段查询,比如我一个表20个字段查出来就很慢了,这种关系不知道指定,查询构造器我知道select就行了

JellyBool 回复 jayin

我看了几遍,没看明白你的意思。。。

jayin 回复 JellyBool
$users = App\User::with(['posts' => function ($query) {
    $query->select(['user_id','title'])->where('title', 'like', '%first%');
}])->get();

@JellyBool 这样做,我模型关系posts表只要title字段,限制了没必要查询的字段

y7ut123

哪个 站长同志,修改文章的时候怎么使用laravelcollective 的Form 获取已经选定的标签呢,我目前是添加新文章没有问题但是,修改的时候虽然已经给$article->tags_list 插入了当前文章的标签数据,但是在视图中select标签中无法显示…

JellyBool 回复 y7ut123

记得使用 Form::model(),或者你直接传入 tag_list 就好了