重新打开:PHP array_shift(); VS 重置();未设置();数组拼接();

Posted

技术标签:

【中文标题】重新打开:PHP array_shift(); VS 重置();未设置();数组拼接();【英文标题】:Reopened: PHP array_shift(); VS reset(); unset(); array_splice(); 【发布时间】:2012-09-12 08:02:20 【问题描述】:

重新打开:

由于 php 是一种服务器端语言,我假设我使用什么浏览器并不重要,但显然并非如此。我一直在使用谷歌浏览器。

我在本地计算机上安装了 WAMP,因此我可以在本地对其进行测试,看看它是否与我的共享主机帐户一样。两种代码都按应有的方式工作(在 Chrome 中提醒您)。然后我查看了共享主机上完全相同的代码——一个有效,另一个无效。

我打电话给我的共享主机支持,他们试图复制问题并说他们没有找到它。因此,我在 Firefox 和 IE 中尝试了它,并且在 IE 中尝试了它,你瞧……它在两者中都能完美运行,就像在 WAMP 上一样。

这对我来说仍然没有多大意义。我在与一家知名托管公司的共享托管帐户上使用 PHP 5.3,但由于他们无法真正解决代码问题,因此无处可去。他们可以复制问题,但无法回答原因。我将在接下来的几周内尝试了解更多信息,并在我了解更多信息后发布更新。

我想做的是:

生成一系列数字 将它们随机排列 将随机排序的数字数组复制到会话数组中 获取数组的第一个值,删除该值,然后全部移位 值减一

这是我的问题:

我尝试使用array_shift();,它在第一次运行时运行良好,但每次我运行代码后它都会删除前两个元素。

为了测试发生了什么,我尝试先打印数组,执行array_shift();,然后再次打印数组以查看发生了什么。

预期结果:

运行#1:

[0]=>5 [1]=>2 [2]=>1 [3]=>4 [4]=>3  //print_r($array);
                                    //execute array_shift($array);
[0]=>2 [1]=>1 [2]=>4 [3]=>3         //print_r($array);

运行#2:

[0]=>2 [1]=>1 [2]=>4 [3]=>3         //print_r($array);
                                    //execute array_shift($array);
[0]=>1 [1]=>4 [2]=>3                //print_r($array);

实际结果:

运行#1:

[0]=>5 [1]=>2 [2]=>1 [3]=>4 [4]=>3  //print_r($array);
                                    //execute array_shift($array);
[0]=>2 [1]=>1 [2]=>4 [3]=>3         //print_r($array);

运行#2:

[0]=>1 [1]=>4 [2]=>3                //print_r($array);
                                    //execute array_shift($array);
[0]=>4 [1]=>3                       //print_r($array);

我的问题(续)

然后我尝试使用reset($array);unset($array[0]);array_splice($array,1,0); 作为array_shift($array) 的替代方案;它奏效了!然后我试着并排比较它们 并清理了代码,现在他们正在做相反的事情。有时reset、unset和array_shift;一次调用时甚至会跳过数组中的最多 7 个单元格。 array_shift(); 正在按照我现在想要的方式工作,但我想知道为什么。快把我逼疯了!如果有人可以帮助我,我将不胜感激。

代码转储:

取消、重置、拼接

<?php
session_start();
$min = A; 
$max = S;

if((!isset($_SESSION['image'])) || ($_SESSION['image'] == null))

$numbers = range($min, $max);  //set a range for all images 
shuffle($numbers); //shuffle the order for randomness

$_SESSION['image'] = $numbers;

echo "<br />Current value: " . $_SESSION['image'][0] . "<br />";
print_r($_SESSION['image']);

reset($_SESSION['image']);
unset($_SESSION['image'][0]);
array_splice($_SESSION['image'],1,0);
echo "<br />New value: " . $_SESSION['image'][0] . "<br />";
echo "<br />1st exec<br />";


else

echo "<br />Current value: " . $_SESSION['image'][0] . "<br />";
print_r($_SESSION['image']);



reset($_SESSION['image']);
unset($_SESSION['image'][0]);
array_splice($_SESSION['image'],1,0);
echo "<br />New value: " . $_SESSION['image'][0] . "<br />";
echo "<br />2nd exec<br />";


?>

班次

<?php
session_start();
$min = A; 
$max = S;

if((!isset($_SESSION['id2'])) || ($_SESSION['id2'] == null))

$numbers = range($min, $max);  //set a range for all images 
shuffle($numbers); //shuffle the order for randomness

$_SESSION['id2'] = $numbers;

echo "<br />Current value: " . $_SESSION['id2'][0] . "<br />";
print_r($_SESSION['id2']);

array_shift($_SESSION['id2']);
echo "<br />New value: " . $_SESSION['id2'][0] . "<br />";
echo "<br />1st execution<br />";


else

echo "<br />Current value: " . $_SESSION['id2'][0] . "<br />";

print_r($_SESSION['id2']);

array_shift($_SESSION['id2']);
echo "<br />New value: " . $_SESSION['id2'][0] . "<br />";
echo "<br />2nd execution<br />";


?>

【问题讨论】:

在您的第一次和第二次运行之间是否有任何机会(可能是一些 javascript)正在创建另一个请求? 这就是我想知道的。这些页面上没有其他内容。这些是完整的转储。您可以在以下位置查看它们的示例:[link]jeffbooru.com/test.php [link]jeffbooru.com/test2.php 在你的 $_SESSION 中设置一个计数器,这样你就知道代码被调用的频率(这是一种廉价的调试方法)。 我会完全关闭我的浏览器然后重新运行它,但我知道你的意思。我会在今晚晚些时候在家时实施它。想一想,在上面插入计数器的好方法是什么?它不会根据是否设置而变为真或假吗? test.php 执行了 2 个 array_shift 调用,而 test2.php 只执行了一个,您确定您正在运行您在此处编写的实际代码吗?您可以通过刷新每一页来查看我的结果。运行 test.php 时还会出现第二个 exec 文本,这意味着您可能错过了 else 那里。我怀疑您在编辑时忘记更新这两个文件,并且只有 test2 具有最新版本。 【参考方案1】:

为了最终了解发生了什么,我建议register a tick-function。滴答函数可以在每个 PHP 语句执行时执行

这是一个简单的,跟踪每个语句的行/文件(请随时添加更多详细信息):

// Execute at each single statement
declare(ticks=1);

// Function to get called at each executing statement    
function logEachStatement() 

  $traceInfo = debug_backtrace();
  $lastActivation = $traceInfo[ count( $traceInfo ) - 1 ];

  $info = "\n" 
        . $lastActivation[ 'line' ]  . '@' . $lastActivation[ 'file' ] 
        ;

  $targetFile = dirname( __FILE__ ) . '/stmnt.log' );

  file_put_contents( $targetFile, $info, FILE_APPEND );



// using a function as the callback
register_tick_function( 'logEachStatement', true );

虽然还有其他方法可以追踪问题,但此方法不需要外部基础架构

【讨论】:

【参考方案2】:

假设您粘贴了实际代码,发生这种情况的唯一方法是您发出了无意的中间请求。但是,仅凭给定的信息,我们不可能确定这种情况的发生方式或原因。

我的建议是使用您选择的浏览器开发工具(例如 Firebug)并监控网络选项卡以确保只有一个请求被发送到脚本。如果这没有出现您的问题,请添加一些简单的调试日志记录,例如:

$log = date('Y-m-d H:i:s')
     . ' :: Request received from '
     . $_SERVER['REMOTE_ADDR']
     . "\n";
file_put_contents('/path/to/your/log/file', $log, FILE_APPEND);

然后在测试后检查您的日志以确保只添加了一个条目。

【讨论】:

这是真正的代码。我正准备把自己扔出窗外试图弄清楚这一点。 array_shift 被分解,直到我尝试使用reset、unset 和array_splice 重写它。我很高兴看到我没有疯。

以上是关于重新打开:PHP array_shift(); VS 重置();未设置();数组拼接();的主要内容,如果未能解决你的问题,请参考以下文章

[PHP源码阅读]array_pop和array_shift函数

PHP - 删除数组头尾元素

php数组array_push()和array_pop()以及array_shift()函数

array_shift — 将数组开头的单元移出数组

[PHP]算法-队列结构的PHP实现

php输出数组第二个