php - PHP - 访问关系以避免嵌套 foreach
问题描述
我有一个 Web 应用程序,我的用户可以在其中:
- 上传文本文件
- 将电子邮件发送到我的应用程序。
现在两者都Document
将Email
包含某种文本。然后,我的用户可以根据他们将能够应用于文本的一组自定义解析规则来解析此文本。
现在所有文件和电子邮件最终都将属于我所说的Stream
. 考虑这些关系:
Stream.php
// A stream can have many documents
public function documents()
{
return $this->hasMany(Document::class);
}
//A stream can have many e-mails
public function emails()
{
return $this->hasMany(Email::class);
}
//A stream can have many fields
public function fields()
{
return $this->hasMany(Field::class);
}
//A stream can have many field rules.
public function fieldrules()
{
return $this->hasManyThrough(FieldRule::class, Field::class);
}
此外,我还声明了Document.php
和Email.php
- 的逆关系,这两者都belongsTo
与Stream
.
现在我在下面,我需要访问特定流的字段规则。为此,我在下面使用:
$stream = $document->stream()->first();
$fields = $stream->fields()->with('rules')->get();
foreach ($fields as $field) {
foreach ($field->rules as $rule) {
//Rule method.
$rule->method;
}
}
如您所见,我必须创建嵌套的 foreach 循环,才能开始使用$field->rules
.
如果我dd($fields)
看到它包含关系,例如:
#relations: array:1 [▼
"rules" => Collection {#536 ▼
#items: array:2 [▼
0 => FieldRule {#554 ▶}
1 => FieldRule {#552 ▶}
]
}
]
但我不能像这样直接访问它:
foreach ($fields->rules as $rule){}
如果我尝试,它会给我这个错误:
Property [rules] does not exist on this collection instance.
解决方案
使用()
执行另一个新的数据库查询。另外,您需要在使用时添加一个闭包()
。
例如,$stream->fieldrules
应该返回 a Collection
(基于您的关系),但$stream->fieldrules()
会返回 a Builder
(数据库查询后面的类),然后->get()
返回 a Collection
(与 相同的东西$stream->fieldrules
,但有额外的开销)
请注意,()
如果关系不是预先加载的,则不使用将执行另一个查询,因此有时使用()
和不使用()
是同一回事。->with()
请参阅下面答案中的用法。
总而言之,可以使用以下代码简化代码:
$document = Document::with([
"stream",
"stream.fields",
"stream.fields.rules",
"stream.fieldrules"
])->first(); // or ->where("id", "=", $id)->first(), etc.
->with()
请注意在单个查询中预先加载所需关系的用法。stream.fields
并且stream.fields.rules
可能不需要此示例,但我不确定引擎盖下的逻辑hasManyThrough
然后为了减轻对嵌套的需求foreach()
,您可以简单地访问所需的关系:
$rules = $document->stream->fieldrules;
如果您需要访问单个字段及其规则,您仍然需要循环,但由于您已经hasManyThrough
为 a和定义了stream
a ,您可以简单地访问它。fields
rules
推荐阅读
- javascript - 如何为 Bootstrap 滚动间谍添加平滑的滚动过渡
- elixir - 在 Gossip GenServer 进程在退出条件之前死亡
- ios - iOS 12 特定问题:Core Data External Storage Binary Data 损坏
- sql-server - SqlDependency 没有触发
- sql - 如何使用 ON 子句从日期时间列中选择日期和时间
- javascript - 招摇错误 swaggerDocument = require('./swagger.yaml');
- python - 在 auto-sklearn 中使用 refit() 进行增量学习
- ios - 如何同时更改我的导航标题字体和颜色?
- javascript - 正则表达式查找 css 块
- angular - 在 app.module.ts 中包含 FormsModule 时,我可以在每个组件中使用 [(ngModel)]