在PHP中将对象分配给对象/数组

在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

长期阅读,第一次询问。我对Java/C之类的东西很有经验,但PHP对我来说是新事物

我遇到了一个问题,作业没有分配到我期望的位置

我通过雄辩的方法从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”: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