>我有这个方法
function updateSessionVariable($objectId, $id, $file){
$fileName = basename($file);
// create the mapping for object ID to Doc info such as url
$format1 = array ($objectId => array("id" => $id, "file" => $file));
$_SESSION["objIdtoDoc"] = $_SESSION["objIdtoDoc"] + $format1;
// now create the mapping for section ID to Object Id
if(isset($_SESSION["sectionIdToObjId"][$id])){
$_SESSION["sectionIdToObjId"][$id][] = $_SESSION["sectionIdToObjId"][$id]+ array("objId" => $objectId, "fileName" => $fileName);
}else{
$format2 = array($id => array(array("objId" => $objectId, "fileName" => $fileName)));
$_SESSION["sectionIdToObjId"] = $_SESSION["sectionIdToObjId"] + $format2;
}
}
它本质上创建了 2 个不同的会话变量。
objIdtoDoc
基本上是一对一的映射,其中objId
是键,值是(id,file)
sectionIdToObjId
是一对多映射,其中id
是键,值是(objId, filename)
数组。
我只调用此方法 158次(意味着为每个会话变量添加 158 行),它导致 php 内存不足(超过 128M)。这不可能是对的。我有一种感觉,我在这种方法中复制数据或在这种方法中做错了事情
你能指教吗? 谢谢
编辑:
感谢您的所有评论,我能够指出问题所在,似乎在 IdToObjId 部分中正在进行递归操作。
我试图实现的是这个变量 sectionIdToObjId (在方法的第二部分)
[id1]=> {("objId" => $objectId, "fileName" => $fileName)}
[id2]=> {("objId" => $objectId1, "fileName" => $fileName1)
,("objId" => $objectId2, "fileName" => $fileName2)}
等等。每次调用该方法时,它都会不断更新数组。我上面说的明显是把事情搞砸了
当你组合数组时(特别是)
if(isset($_SESSION["sectionIdToObjId"][$id])){
$_SESSION["sectionIdToObjId"][$id][] = $_SESSION["sectionIdToObjId"][$id]+ array("objId" => $objectId, "fileName" => $fileName);
}else{
...
这部分:
$_SESSION["sectionIdToObjId"][$id][] =
创建一个新的数组项,其中包含上一项和新数组(位于分配的右侧)。
所以如果$id = 1
//iteration 1
$_SESSION["sectionIdToObjId"][1] = [
["objId" => $objectId, "fileName" => $fileName] //new data
];
//iteration 2
$_SESSION["sectionIdToObjId"][1] = [
0 => [["objId" => $objectId, "fileName" => $fileName]], //old data
1 => ["objId" => $objectId, "fileName" => $fileName] //new data
];
//iteration 3
$_SESSION["sectionIdToObjId"][1] = [
0 => [
0 => [["objId" => $objectId, "fileName" => $fileName]],
1 => ["objId" => $objectId, "fileName" => $fileName]
],1 => [
0 => [["objId" => $objectId, "fileName" => $fileName]],
1 => ["objId" => $objectId, "fileName" => $fileName] //old data
]
],1 => ["objId" => $objectId, "fileName" => $fileName] //new data
];
或者类似的东西,它基本上呈指数级增长。 将其乘以 158 次迭代,是的,您可能会在其中获得十亿个数组项目。
修复它的方法很简单:
$_SESSION["sectionIdToObjId"][$id][] = array("objId" => $objectId, "fileName" => $fileName);
那么那么
//iteration 1
$_SESSION["sectionIdToObjId"][1] = [
["objId" => $objectId, "fileName" => $fileName] //new data
];
//iteration 2
$_SESSION["sectionIdToObjId"][1] = [
["objId" => $objectId, "fileName" => $fileName], //new data
["objId" => $objectId, "fileName" => $fileName] //new data
];
//iteration 3
$_SESSION["sectionIdToObjId"][1] = [
["objId" => $objectId, "fileName" => $fileName], //new data
["objId" => $objectId, "fileName" => $fileName] //new data
["objId" => $objectId, "fileName" => $fileName] //new data
];
或者$objectId
应该是唯一的
$_SESSION["sectionIdToObjId"][$id][$objectId] = array("objId" => $objectId, "fileName" => $fileName);
那么那么
//iteration 1 - $objectId = 34
$_SESSION["sectionIdToObjId"][1] = [
34 => ["objId" => 34, "fileName" => $fileName] //new data
];
//iteration 2 - $objectId = 34 ( dupliate )
$_SESSION["sectionIdToObjId"][1] = [
34 => ["objId" => 34, "fileName" => $fileName] //new data replaces data from itteration 1
];
//iteration 3 - $objectId = 200
$_SESSION["sectionIdToObjId"][1] = [
34 => ["objId" => 34, "fileName" => $fileName] //new data
200 => ["objId" => 200, "fileName" => $fileName] //new data
];
专业提示您可能会遇到的一个问题是您可能会发现您的密钥被重置,有时在序列化它们时会使用数字密钥。我不确定会话序列化是否容易出现这种情况。 发生的情况是,当他们将数组融合到刺痛时,他们只是省略了数字键,如果我记得我在 JSON 上遇到了这个问题,像这样保存在哪里(可能有也可能没有涉及一些 MongoDB ......哈哈):
//php array
['data' => [1=>'foo', 64=>'bar']]
//json data
{"data" : [ "foo", "bar" ]}
这样当它取消编码时,编号的键就会丢失,你最终会得到
//php array
['data' => [0=>'foo', 1=>'bar']]
您可以通过将它们设置为字符串来防止这种情况
//casting using (string)
$_SESSION["sectionIdToObjId"][(string)$id][(string)$objectId] = array("objId" => $objectId, "fileName" => $fileName);
或者(我会做什么)
//just concatenating a string on them
$_SESSION["sectionIdToObjId"]["i".$id]["j".$objectId] = array("objId" => $objectId, "fileName" => $fileName);
如果您这样做,请不要以相同的方式检查密钥。在第一个例子(只是投射)中,PHP不在乎它是否1
或"1"
它以同样的方式看待它,松散的类型。
if(isset($_SESSION["sectionIdToObjId"]["i".$id])){
您的数据将如下所示
$_SESSION["sectionIdToObjId"]["i1"] = [
"j34" => ["objId" => 34, "fileName" => $fileName] //new data
"j200" => ["objId" => 200, "fileName" => $fileName] //new data
];
更新
对不起,我第一次错过了这个,你的方式你最终会得到这个:
//iteration 1 - $id was not set
$_SESSION["sectionIdToObjId"]["1"] = ["objId" => 1, "fileName" => $fileName];
//iteration 2 - $id is now set ( we overwrite the first pass ) so we lost ogjId = 1
$_SESSION["sectionIdToObjId"]["1"] = [
["objId" => 5, "fileName" => $fileName] //new data replaces data from itteration 1
];
//iteration 3
$_SESSION["sectionIdToObjId"]["1"] = [
["objId" => 5, "fileName" => $fileName], //new data
["objId" => 10, "fileName" => $fileName] //new data
];
同样在访问此内容时,
在第一次迭代中,您有一个数组,因此$_SESSION["sectionIdToObjId"]["1"]["objId"]
可以访问
foreach($_SESSION["sectionIdToObjId"]["1"] as $key=>$var )
//on first iteration key = objId, value = 1
在第二次迭代中,您具有嵌套数组$_SESSION["sectionIdToObjId"]["1"][0]["objId"]
因此可以访问,请注意那里的额外[0]
。
foreach($_SESSION["sectionIdToObjId"]["1"] as $key=>$var )
//on first iteration key = 0, value = ['objId' => 5, ... ]
这可能会导致数据结构未按您想要的方式构建的问题,循环时,在第一种情况下会有单独的项目,但第二种情况会给你一个完整的数组。 所以你以这种方式处理 2 个结构。
我只是假设它会有多个项目。 然后它将一直像第二种情况一样,嵌套数组。
if(isset($_SESSION["sectionIdToObjId"][(string)$id])){
//define our variable as an empty array
$_SESSION["sectionIdToObjId"][(string)$id] = [];
}
//add all day long
$_SESSION["sectionIdToObjId"][(string)$id][] = ["objId" => $objectId, "fileName" => $fileName];
然后你得到这个:
$_SESSION["sectionIdToObjId"]["1"] =[
["objId"=>1 ...]
];
//instead of
$_SESSION["sectionIdToObjId"]["1"] = ["objId"=>1 ...];
希望这是有道理的。
最后一件事PHP5.4
添加了短数组语法,而不是这样做
$a = array(...);
我们可以做
$a = [ ... ];
现在,如果你看到我这样做,这就是全部。我们PHP的人很懒,我的意思是高效。