在PHP中将对象分配给对象/数组
长期阅读,第一次询问。我对Java/C之类的东西很有经验,但PHP对我来说是新事物 我遇到了一个问题,作业没有分配到我期望的位置 我通过雄辩的方法从MySQL数据库中获取一个数组,特别是:在PHP中将对象分配给对象/数组,php,laravel,eloquent,Php,Laravel,Eloquent,长期阅读,第一次询问。我对Java/C之类的东西很有经验,但PHP对我来说是新事物 我遇到了一个问题,作业没有分配到我期望的位置 我通过雄辩的方法从MySQL数据库中获取一个数组,特别是: $result= TableA::where('tableA.id', '=', $id) ->with('tableB.tableC') ->get(); 为便于参考,打印$result out如下所示: [{"id":105, /*TableA
$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”:null
替换为“tableB”:{“tableC”:{/*tableC fields*/}
),我将不胜感激。表中的字段加载到属性
属性中,关系加载到关系
属性中
您遇到的问题是tableB
是一个关系字段,而不是表字段。其数据存储在关系
属性中。但是,关系
属性不能以您尝试的方式直接修改。当您尝试使用$result[$i][“tableB”]
修改它时,该代码实际上是在修改属性中的tableB
字段
然后是获取数据的问题。当您尝试使用$result[$i][“tableB”]
直接读取数据时,它将首先查找属性
属性,如果在那里找不到,则会查找关系
属性
但是,当您使用Log::info($result)转储整个对象时
,则关系
属性中的任何数据都会覆盖属性
属性中的数据。因此,在使用$result[$i][“tableB”]='asdf'
直接赋值之后,Log::info($result)
不会显示更改(因为关系
覆盖属性
),而Log::info($result[$i][“tableB”])
将显示更改(因为它首先查看属性
)
因此,分析您的代码,我们有:
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
}
}
这将在关系
属性上专门设置tableB
,这正是您要做的。那会让你的一切都好起来的
话虽如此,你或许可以用另一种方式解决这个问题。如果您使用的是Laravel>=5.3,并且您的tableB
关系是HasOne(5.3+)或BelongsTo(5.4+)关系,则可以在关系上使用withDefault()
功能,以便在数据库中不存在默认模型时自动生成默认模型。你可以阅读更多关于这方面的内容
因此,您的关系定义如下所示:
public function tableB()
{
return $this->hasOne('App\TableB')->withDefault();
}
现在,当不存在tableB
记录时,关系将加载一个新的空tableB
对象,而不是null
如果您需要的不仅仅是一个空的TableB
对象,您可以将一个函数传递给withDefault()
方法,该函数将用于生成默认对象。Eloquent不会返回普通PHP数组,使用get
方法时,它将返回illighted\Support\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
}
}
$result=TableA::where('TableA.id','=',$id)
->带('tableB.tableC')
->get();
//将集合转换为数组
$result=$result->toArray();
对于($i=0;$i
现在您应该已经正确分配了值。试试看
foreach ($result as $whatever)
{
if($whatever->tableB == null)
{
$whatever->tableB = OtherController::makeDummyTableB();
}
}
问题是无法将tableB对象指定给tableA模型的数组字段。。。
您的tableB模型很可能(我认为,这取决于您是如何构建的)通过“tableB_id”字段与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
只是不要对关系使用奇怪的数组语法tableB
和tableC
是您雄辩的模型中的关系。您只能通过使用方法正确分配给这些。看起来您是在使用数组而不是雄辩的实例来赋值。您的$result数组键中的$j是什么,您是否已将其初始化为“0”?@Rits这是一个输入错误,我刚刚编辑过它。应该是$iYou可以对tableA模型中的tableB关系使用访问器。请看答案是tableB
a有一个或属于关系,或者是其他什么?哎呀,是的,那是个打字错误。谢谢你发现它,我会编辑这篇文章的now@Blacklles我对这两部分都做了更多的解释。如果不深入源代码,它可能会非常混乱。很好,这解释了我自己调试时遇到的很多问题-非常感谢:)正如toArray()
方法所暗示的,这将把集合中的所有对象转换为数组。它们将不再是雄辩的模型,而是普通的数组
foreach ($result as $whatever)
{
if($whatever->tableB == null)
{
$whatever->tableB = OtherController::makeDummyTableB();
}
}
$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