Laravel 获取相关数据
我正在学习拉威尔,非常初级。因此,我们的想法是实现Laravel 获取相关数据,laravel,eloquent,Laravel,Eloquent,我正在学习拉威尔,非常初级。因此,我们的想法是实现slugurl。有类别型号。该模型可以有无限多个段塞。如果我要求最后一页,我会得到合适的一页。如果我请求另一个slug(oblolete),我将获得301重定向到最后一个slug 类别是父子层次结构模型。我需要与CategorySlugmodel建立一对一的关系,因为我不关心以前所有的slug值 迁移: 类createCategateStable扩展了迁移 { 公共职能 { Schema::create('categories',函数(Bluep
slug
url。有类别
型号。该模型可以有无限多个段塞。如果我要求最后一页,我会得到合适的一页。如果我请求另一个slug(oblolete),我将获得301重定向到最后一个slug
类别是父子层次结构模型。我需要与CategorySlug
model建立一对一的关系,因为我不关心以前所有的slug值
迁移:
类createCategateStable扩展了迁移
{
公共职能
{
Schema::create('categories',函数(Blueprint$表){
$table->bigIncrements('id');
$table->string('title');
});
Schema::table('categories',函数(Blueprint$table){
$table->unsignedBigInteger('parent_id')->nullable()->after('id');;
$table->foreign('parent_id')->references('id')->on('categories')->onUpdate('cascade')->onDelete('cascade');
});
}
}
class CreateCategoriesLugtable扩展了迁移
{
公共职能
{
Schema::create('categories_slug',函数(Blueprint$table){
$table->bigIncrements('id');
$table->string('value')->unique()->index()->nullable(false);
$table->timestamp('created_at')->useCurrent();
});
Schema::table('categories_slug',函数(Blueprint$table){
$table->unsignedBigInteger('category_id')->nullable()->after('id');
$table->foreign('category_id')->references('id')->on('categories')->onUpdate('cascade')->onDelete('cascade');
});
}
}
型号:
类类别扩展模型
{
公共职能儿童(){
return$this->hasMany('App\Category','parent\u id','id')->
orderBy('order')->
与(‘儿童’);
}
公共函数slug(){
返回$this->hasOne('App\CategorySlug','category\u id','id')->
orderBy('created_at','desc')->limit(1);
}
}
class CategorySlug扩展了模型
{
/**
*@return App\Category
*/
公共职能类别(){
返回$this->belongsTo('App\Category','Category\u id','id')->带('slug');
}
}
当我在控制器中运行下一个代码时,我希望每个类别
都会填充slug
属性
$categories = Category::where('parent_id', null)->with('children', 'slug')->get();
但事实上,只有第一个具有适当的slug
。其他的slug属性等于null。所有子属性
都加载良好
我将源代码放入存储库。除此之外,还有种子文件
更新:
感谢@marlon ferreira,我做了一些改变:
类类别扩展模型
{
...
公共函数slug(){
返回$this->hasOne('App\CategorySlug','category_id','id')->latest();
}
}
现在,一切正常!我更喜欢使用hasOne
,因为我不喜欢写$category->slug[0]->value
而不是$category->slug->value
。可以吗
为什么我不能将latest()
替换为limit(1)+orderBy('created_at')
?只返回所有类别树(根目录和子目录)的最后一个类别
这是我的建议:
关于类别模型:
public function slug() {
return $this->hasMany('App\CategorySlug', 'category_id', 'id')->latest();
}
public function children() {
return $this->hasMany('App\Category', 'parent_id', 'id')->
orderBy('order')->
with('children', 'slug');
}
latest()
方法只提供最新的slugslug()
relationship时,它将只检索最新的CategorySlug记录
关于类别模型:
public function slug() {
return $this->hasMany('App\CategorySlug', 'category_id', 'id')->latest();
}
public function children() {
return $this->hasMany('App\Category', 'parent_id', 'id')->
orderBy('order')->
with('children', 'slug');
}
所以,这个控制器调用
$categories = Category::where('parent_id', null)->with('children', 'slug')->get();
…将只返回主类别(parent_id=null)以及所有子类别的最新slug
警告-无限渴望加载
在我向您提供了我的解决方案之后,我想谈谈一些通常很多Laravel/有口才的开发人员都不知道的事情
基本上,您正在创建一个无限的渴望加载。让我向你解释一下:
这是您的类别模型及其关系:
Categories => Categories (children)
=> CategorySlug (slug)
这是您的CategorySlug模型及其关系:
CategorySlug => Category
Category::find(1)->slug();
这里将发生的是:
category will load slug -> slug will load category -> category will load slug -> ...
这是一种无限的渴望。它将导致数据库超时异常
要避免这种情况,只需删除CategorySlug模型上的和
在我看来,这是没有必要的
如果您的需求发生变化,并且您确实需要这种反向关系,请告诉我
技巧和额外知识
- 最古老和最新的方法
有两种方法允许您仅检索最旧或最新的记录。例如:
$categories = Category::where('is_active', true); // we have many categories here
$last_created_category = $categories->latest(); // latest category created
$old_updated_category = $categories->oldest('updated_at'); // oldest category updated
这两种方法都接受字符串作为参数,以确定必须对哪个字段进行排序
默认值是在
处创建的
- 范围策略使用
作用域是创建自定义可重用实现的好方法
假设您的控制器实现,我们可以在以下情况下应用范围:
关于范畴模型-
class Category extends Model
{
...
public function scopeWithoutParent($query) {
return $query->whereNull('parent_id');
}
}
class Category extends Model
{
...
protected $with = [ 'children', 'slug' ];
public function children() {
return $this->hasMany('App\Category', 'parent_id', 'id')->orderBy('order');
}
public function slug() {
return $this->hasMany('App\CategorySlug', 'category_id', 'id')->latest();
}
在控制器上-
$categories = Category::withoutParent()->with('children', 'slug')->get();
$categories = Category::withoutParent()->get();
- 总是渴望加载你的关系
这是一个可能在你的项目中使用的技巧
基本上,您可以强制Elount加载关系,而无需显式调用它
关于范畴模型-
class Category extends Model
{
...
public function scopeWithoutParent($query) {
return $query->whereNull('parent_id');
}
}
class Category extends Model
{
...
protected $with = [ 'children', 'slug' ];
public function children() {
return $this->hasMany('App\Category', 'parent_id', 'id')->orderBy('order');
}
public function slug() {
return $this->hasMany('App\CategorySlug', 'category_id', 'id')->latest();
}
在控制器上-
$categories = Category::withoutParent()->with('children', 'slug')->get();
$categories = Category::withoutParent()->get();
正如你所看到的,你不必再显式地调用关系
希望这会有帮助
祝你度过愉快的一天。你能详细说明一下吗