我知道这似乎是一个简单的问题,但在查看了官方文档和2个教程后,我不清楚。有没有使用foreign_keys的冲突示例,以及在不同的位置使用类Model:all()以及与hasMany关系一起使用...这样做似乎很简单我很沮丧我无法轻易找到答案。我知道答案可能是有人,但有几个部分对于初学者来说并不明显,因为到处都有相互矛盾的例子,我甚至发现一些不起作用的命令(经其他帖子验证),但仍然有记录。那么请有人为我澄清这个简单的问题,这样事情就会变得不那么混乱了。
如何在我的视图中访问相关表格?我收到错误“试图获取非对象的属性(视图:”当我在我的视图中运行它
@foreach $programs as $program
{{{$program->program_segment->name}}}
@endforeach
程序是用于显示非相关数据的模型。 program_segment是我的程序模型中定义的函数,它与我想要访问的相关表具有has_One关系。
相关文件:
Model:
class ProgramEvent extends Eloquent {
protected $table = 'program_events';
public $timestamps = true;
public function program_segment()
{
return $this->hasOne('ProgramSegment');
}
}
class ProgramSegment extends Eloquent {
protected $table = 'program_segments';
public $timestamps = true;
}
Migrations:
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateProgramEventsTable extends Migration {
public function up()
{
Schema::create('program_events', function(Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('name', 32);
$table->date('date');
$table->time('start_time');
$table->time('end_time');
$table->string('location', 32);
});
}
public function down()
{
Schema::drop('program_events');
}
}
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateProgramSegmentsTable extends Migration {
public function up()
{
Schema::create('program_segments', function(Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('name', 32);
$table->text('description');
$table->decimal('cost', 3,2);
$table->integer('program_event_id')->unsigned()->nullable();
$table->foreign('program_event_id')->references('id')->on('program_events')->onDelete('cascade');
});
}
public function down()
{
Schema::drop('program_segments');
}
}
Controller:
public function index()
{
$programs = ProgramEvent::with('program_segment')->get();
return View::make('programs.index', compact('programs'));
}
答案 0 :(得分:1)
在查询模型时,您似乎需要加载关系。您可以使用"加载"加载它们。操作者:
控制器:
public function index()
{
$programs = ProgramEvent::with('program_segment')->get();
return View::make('programs.index', compact('programs'));
}
<强> UPD:强> 此外,直接指定用于关联表的列总是一个好主意。这里的文档说明了什么:
return $this->hasOne('Model', 'foreign_key', 'local_key');
另外,我认为你缺少program_segmet中用于保存父ID(program_event_id)的列。添加它可以很好地制作外键,但不是必需的。
答案 1 :(得分:1)
问题的根源在于缺少外键。 总是需要关系中的外键,否则您的数据库无法将一条记录连接到另一条记录。如果没有外键,ORM无法知道哪些数据是相关的。
如果您的外键被命名为遵循惯例model_id
,其中model
是您定义关系的模型的名称,那么您不需要指定 hasOne
语句中的外键名称...但外键仍然必须存在在数据库中。因此,如果您的外键名为program_event_id
,则您的hasOne
语句将按原样运行。 (在第二条错误消息中,您可以看到它期望列program_event_id
。)但是,如果您将外键命名为其他内容,则应将其添加到hasOne
定义中,即{ {1}});&#39;
在迁移中添加外键需要两个语句(按此顺序):
return $this->hasOne('ProgramSegment', 'my_foreign_key
(在第一行末尾添加$table->integer('program_event_id')->unsigned();
$table->foreign('program_event_id')->references('id')->on('progam_events');
不是必需的,但是->index()
是。)
除此之外,您的一些错误可能是由您姓名中的拼写错误引起的。您的原始&#39;非对象&#39;可能是因为您的控制器正在将unsigned()
传递给您的视图而导致错误,但在您的视图中,您引用了'programs'
。就您的观点而言,$program->program_segment->name
存在,但$programs
不存在。
您的外键约束错误也可能由拼写错误引起,因为您将表定义为$program
;如果这是故意的,那么迁移中的外键定义也必须引用progam_events
而不是progam_events
。
正确设置外键后,使用program_events
运算符with
。但是,如果您计划循环遍历$program->program_segment->name
的结果集并显示每个相关的$program
,那么这是一种很好的做法。使用program_segment->name
将仅使用2个查询带来所有相关记录,因此您不需要对每个相关记录进行1次查询。这避免了称为&#34; N + 1&#34;问题,并使您的查询更有效。
最后,所有这些都可能是不必要的......如果你的关系真正的是一对一的关系(所以只有一个事件只有一个段),你可以,大多数情况下在这种情况下,只需将两个表组合在一起即可完全消除::with
关系。在某些情况下,将一对一数据分成两个表是有意义的,但这些与性能有关,而不是数据结构。但我怀疑,你的两个表之间的关系应该是一对多的关系。
在正确设置关系后,请确保在hasOne
循环中添加一项检查,以确保在您尝试访问之前,某个foreach
存在program_segment
它;否则,如果您点击了一个没有相关program_segment的程序,您最终会得到一个&#34;尝试获取非对象的属性&#34;错误:
program_event