长时间读者,第一次问问。我对Java / C这样的东西很有经验,但PHP对我来说是新的。
我遇到的问题是作业没有分配到我期望的位置。
我通过Eloquent方法从MySQL数据库中获取数组,特别是:
$result= TableA::where('tableA.id', '=', $id)
->with('tableB.tableC')
->get();
作为参考,打印$ result out看起来像这样:
[{"id":105, /*TableA fields*/, "tableB":null},
{"id":106, /*TableA fields*/, "tableB":null},
{"id":107, /*TableA fields*/, "tableB":{/*tableB fields*/, "tableC":
{"id":104, /*TableC fields*/}}},
{"id":108, /*TableA fields*/, "tableB":{/*tableB fields*/, "tableC":
{"id":105, /*TableC fields*/}}}]
在某些情况下,TableA元组将在tableB中具有关联记录,因此tableC中具有关联记录,其他时候tableB中没有关联记录。如果没有相关记录我想要通过并使临时“虚拟”记录通过而不是通过null。我用来做的代码是:
for ($i=0; $i < count($result); $i++)
{
if($result[$i]["tableB"] == null)
{
Log:info($result); //Print line A
$result[$i]["tableB"] = OtherController::makeDummyTableB(); //Assignment line
Log::info($result); //Print line B
Log::info($result[$i]["tableB"]); //Print line C
}
}
问题是赋值行没有分配给$ result中返回的对象/数组中的“tableB”字段。在打印行A和B上打印$ result会得到相同的结果,前两个记录的“tableB”为空。然而,打印行C给出了我期望的输出,这是我正在创建的虚拟记录
{"tableC":{/*TableC fields*/}}
所以赋值正在做某事,但它并没有分配给已经存在的$ result中的字段,而是将其分配给其他地方(当我尝试将其分配时)显示它)
如果有人能让我知道我当前的代码实际在做什么,以及如何让它做我期望的事情(用"tableB":null
替换"tableB":{"tableC":{/*TableC fields*/}}
),我们将非常感激
答案 0 :(得分:2)
雄辩的模特有很多&#34;魔法&#34;在后台继续。表中的字段将加载到attributes
属性中,并且关系将加载到relations
属性中。
您遇到的问题是tableB
是关系字段,而不是表字段。其数据存储在relations
属性中。但是,relations
属性不能像您尝试的那样直接修改。当您尝试使用$result[$i]["tableB"]
对其进行修改时,该代码实际上正在修改tableB
属性中的attributes
字段。
然后是获取数据的问题。当您尝试使用$result[$i]["tableB"]
直接读取数据时,它会先查看attributes
属性,如果找不到,那么它会查看relations
属性。
但是,使用Log::info($result);
转储整个对象时,relations
属性中的任何数据都会覆盖attributes
属性中的数据。因此,在使用$result[$i]["tableB"] = 'asdf'
进行直接分配后,Log::info($result)
将不会显示更改(因为relations
会覆盖attributes
),而Log::info($result[$i]["tableB"])
将显示更改(从它首先查看attributes
。
因此,分析您的代码,我们有:
for ($i=0; $i < count($result); $i++) {
if($result[$i]["tableB"] == null) {
// At this point:
// - tableB relation is null
// - tableB attribute does not exist
// This is a full dump, so the relations overwrites the attributes.
// tableB will show null
Log:info($result);
// After this assignment executes:
// - tableB relation will be null
// - tableB attribute will be the dummy object
$result[$i]["tableB"] = OtherController::makeDummyTableB();
// This is a full dump, so relations (null) overwrites the attributes (dummy object).
// tableB will show null
Log::info($result); //Print line B
// This is direct access, which accesses attributes (dummy object) before relations (null).
// tableB will show dummy object
Log::info($result[$i]["tableB"]); //Print line C
}
}
如果你真的想这样做,你应该使用setRelation()
方法:
$result[$i]->setRelation('tableB', OtherController::makeDummyTableB());
这将在tableB
属性上专门设置relations
,这是您尝试做的事情。这应该让一切都适合你。
话虽如此,你或许可以用不同的方式解决这个问题。如果您使用Laravel&gt; = 5.3且您的tableB
关系是HasOne(5.3+)或BelongsTo(5.4+)关系,则可以在关系上使用withDefault()
功能,当数据库中不存在默认模型时,它将自动生成默认模型。您可以阅读有关此in the documentation here的更多信息。
因此,您的关系定义类似于:
public function tableB()
{
return $this->hasOne('App\TableB')->withDefault();
}
现在,如果不存在tableB
条记录,则系统会使用新的空TableB
对象加载关系,而不是null
。
如果您需要的不仅仅是空TableB
个对象,您可以将函数传递给withDefault()
方法,该函数将用于生成默认对象。
答案 1 :(得分:0)
Eloquent不返回普通的PHP数组,当使用get
方法时,它将返回Illuminate\Support\Collection
的实例,你不能简单地将这样的对象分配到Collection
。为此,您必须首先将集合转换为数组:
$result = TableA::where('tableA.id', '=', $id)
->with('tableB.tableC')
->get();
// Convert collection to array
$result = $result->toArray();
for ($i=0; $i < count($result); $i++)
{
if($result[$i]["tableB"] == null)
{
Log:info($result); //Print line A
$result[$i]["tableB"] = OtherController::makeDummyTableB(); //Assignment line
Log::info($result); //Print line B
Log::info($result[$i]["tableB"]); //Print line C
}
}
现在你应该正确分配你的价值了。
答案 2 :(得分:0)
尝试
foreach ($result as $whatever)
{
if($whatever->tableB == null)
{
$whatever->tableB = OtherController::makeDummyTableB();
}
}
问题是你不能将tableB对象分配给tableA模型的数组字段...... 您的tableB模型最有可能(我假设,取决于您如何构建它)通过&#34; tableB_id&#34;与您的tableA模型相关。领域。因此,如果您使用作业,最终会使用
$tableA["tableB_id"] //id of the related tableB, in your case null
$tableA["tableB"] //your newly assigned model, which has nothing to do with your relationship, because that should work on tableB_id
不要使用奇怪的数组语法进行关系