奇怪的 PHP Scandir 或数组拆分错误
Strange PHP Scandir or Split error with array
首先,请原谅我,我对这个还很陌生,现在有点累了。
我对此束手无策。我编写了一些 PHP 代码,以便我正在处理的网站可以快速轻松地更新其时事通讯。目标是将第一个时事通讯显示为嵌入的 pdf,然后将所有其他时事通讯显示为下方的链接,因此撰写时事通讯的人需要做的就是将它们放在文件夹中并使用正确的命名格式。
我正在使用 scandir 扫描目录和 return 所有文件,按降序排列,如果命名正确 (YYYY/MM),这将首先给出最新的文件。然后它将文件名拆分并将月份传递给一个函数,该函数 return 是月份的实际名称,并将所有这些插入 html 并生成页面。
除了一件事,它工作得很好。 一个 文件不会显示月份。您可以在 screenshot 中看到 2014 年 8 月的文件不会显示月份,我根本无法弄清楚。 (对不起底部的东西,我不能post超过两个链接,因为我没有足够的代表所以我不得不把我所有的图像合二为一,忽略下半部分)
这是我的主程序的代码(抱歉格式问题,由于这些愚蠢的限制,我不得不合并一些东西)
//sort in descending order so the most recent date is first
$newsletterarray=scandir("../docs/newsletter", SCANDIR_SORT_DESCENDING);
//print_r($newsletterarray); //shows all the values
//Splits the selected newsletter array into another array, [1] will be the month which can be passed into month.php
$month = split("_", $newsletterarray[0]);
$filenameSplit = split("_", $newsletterarray[0]);
//The most recent newsletter is embedded
echo('<p>
<a href="../docs/newsletter/' . $newsletterarray[0] . '"><h4 align="justify">' . getMonth($filenameSplit[1]) . ' ' . $filenameSplit[0] . ' Newsletter</h4></a>
</p>
<p>
<object width="50%" height="500px" data="../docs/newsletter/' . $newsletterarray[0] . '" type="application/pdf"></object>
</p><br> <h4>Older Newsletters</h4>');
//starts at 1 so it skips the most recent newsletter
//increments until it reaches 3 less than max, otherwise it shows directory stuff
for( $i = 1; $i <= (count($newsletterarray) - 3); $i++) {
$filenameSplit = split("_", $newsletterarray[$i]);
echo('<a href="../docs/newsletter/' . $newsletterarray[$i] . '">' . getMonth($filenameSplit[1]) . ' ' . $filenameSplit[0] . ' Newsletter</a><br>');
}
function getMonth($nummonth) {
switch ($nummonth) {
case 01:
return "January";
break;
case 02;
return "February";
break;
case 03:
return "March";
break;
case 04:
return "April";
break;
case 05:
return "May";
break;
case 06:
return "June";
break;
case 07:
return "July";
break;
case 08:
return "August";
break;
case 09:
return "September";
break;
case 10:
return "October";
break;
case 11:
return "November";
break;
case 12:
return "December";
break;
default:
return "";
break;
}
}
在屏幕截图中,您可以看到我所做的一些故障排除。您可以看到拆分表明 1 应该是 08 的正确值,但是当我将它传递给 getMonth 函数时它不起作用。您还会看到传入 08 工作正常,因此错误似乎不在 getMonth 函数中。
除此之外,我尝试将文件添加到实际目录,这根本没有改变错误,但预期的功能确实有效。我也尝试删除有问题的文件并重命名另一个文件以具有相同的名称,但发生了同样的错误。
我真的希望这只是一个愚蠢的错误,因为我写了一些东西阻止了这个特定文件的工作,这真的让我很伤心。谢谢。
你最大的问题是类型混合。您的 split() 调用将 return 一个 字符串 的数组('01'、'02' 等),但是您的 getMonth() 函数定义为它打开值作为 整数 (01、02 等)。
现在,PHP 将允许这样做,因为它会为您做一些 type juggling。但是您 运行 在解释开关中的数字时遇到了更多麻烦。具体来说,您的前导零导致它们被解释为八进制(base-8)数字而不是您期望的十进制(base-10)数字。
我们可以深入研究血淋淋的细节,但它们在这里真的不重要,因为您应该通过始终如一地表示您的数字来解决这个问题。最快的方法是将 getMonth() 中的每个开关值替换为带引号的值:
function getMonth($nummonth) {
switch ($nummonth) {
case '01':
return "January";
break;
case 02;
return "February";
break;
case '03':
return "March";
break;
case '04':
return "April";
break;
case '05':
return "May";
break;
case '06':
return "June";
break;
case '07':
return "July";
break;
case '08':
return "August";
break;
case '09':
return "September";
break;
case '10':
return "October";
break;
case '11':
return "November";
break;
case '12':
return "December";
break;
default:
return "";
break;
}
}
这应该会让事情为你工作。它的工作原理是将这些值视为字符串,这将使它们与您为 $nummonth 传递的值相匹配,而不会破坏任何类型。
除此之外,请允许我提供一些其他提示:
- split() 函数已失效,甚至在最近的 PHP 版本中也不可用。如果需要通过正则表达式拆分字符串,请使用 preg_split()。在这种情况下,您只是按字符串常量 ('_') 进行拆分,因此您可以使用 explode(),这正是您在这里需要的。只需将 split() 调用切换为 explode() 调用,无需更改参数。
- 当你使用 echo 吐出 HTML 时,你真的应该转义它。请参阅 PHP 的 htmlentities() 函数。使用您显示的特定文件名数据,您不会 运行 遇到问题,但其他数据可能会导致页面行为异常或存在安全漏洞。
- 可以删除 $month 变量行。您不使用该变量,紧随其后的是 $filenameSplit 变量,它是同一事物,但命名更好。
- getMonth() 函数本身可以简化。对于像这样的简单映射,我通常喜欢使用数组。使用这种技术,您的函数可能类似于下面的 getMonth2()。请参阅 PHP's docs on arrays to learn how this works. However, in this specific case of converting a month number to a name, you can reduce it to a one-liner like in getMonth3(), below. See the docs on date() and strtotime() 了解此方法。
备选方案 1:使用数组作为映射:
function getMonth2($nummonth) {
$months = array(
'01' => 'January',
'02' => 'February',
'03' => 'March',
'04' => 'April',
'05' => 'May',
'06' => 'June',
'07' => 'July',
'08' => 'August',
'09' => 'September',
'10' => 'October',
'11' => 'November',
'12' => 'December',
); //$months
return $months[$nummonth];
} //getMonth2
备选方案 2:使用 PHP 的 date-related 函数
function getMonth3($nummonth) {
return date('F', strtotime("2017-$nummonth"));
} //getMonth3
首先,请原谅我,我对这个还很陌生,现在有点累了。
我对此束手无策。我编写了一些 PHP 代码,以便我正在处理的网站可以快速轻松地更新其时事通讯。目标是将第一个时事通讯显示为嵌入的 pdf,然后将所有其他时事通讯显示为下方的链接,因此撰写时事通讯的人需要做的就是将它们放在文件夹中并使用正确的命名格式。
我正在使用 scandir 扫描目录和 return 所有文件,按降序排列,如果命名正确 (YYYY/MM),这将首先给出最新的文件。然后它将文件名拆分并将月份传递给一个函数,该函数 return 是月份的实际名称,并将所有这些插入 html 并生成页面。
除了一件事,它工作得很好。 一个 文件不会显示月份。您可以在 screenshot 中看到 2014 年 8 月的文件不会显示月份,我根本无法弄清楚。 (对不起底部的东西,我不能post超过两个链接,因为我没有足够的代表所以我不得不把我所有的图像合二为一,忽略下半部分)
这是我的主程序的代码(抱歉格式问题,由于这些愚蠢的限制,我不得不合并一些东西)
//sort in descending order so the most recent date is first
$newsletterarray=scandir("../docs/newsletter", SCANDIR_SORT_DESCENDING);
//print_r($newsletterarray); //shows all the values
//Splits the selected newsletter array into another array, [1] will be the month which can be passed into month.php
$month = split("_", $newsletterarray[0]);
$filenameSplit = split("_", $newsletterarray[0]);
//The most recent newsletter is embedded
echo('<p>
<a href="../docs/newsletter/' . $newsletterarray[0] . '"><h4 align="justify">' . getMonth($filenameSplit[1]) . ' ' . $filenameSplit[0] . ' Newsletter</h4></a>
</p>
<p>
<object width="50%" height="500px" data="../docs/newsletter/' . $newsletterarray[0] . '" type="application/pdf"></object>
</p><br> <h4>Older Newsletters</h4>');
//starts at 1 so it skips the most recent newsletter
//increments until it reaches 3 less than max, otherwise it shows directory stuff
for( $i = 1; $i <= (count($newsletterarray) - 3); $i++) {
$filenameSplit = split("_", $newsletterarray[$i]);
echo('<a href="../docs/newsletter/' . $newsletterarray[$i] . '">' . getMonth($filenameSplit[1]) . ' ' . $filenameSplit[0] . ' Newsletter</a><br>');
}
function getMonth($nummonth) {
switch ($nummonth) {
case 01:
return "January";
break;
case 02;
return "February";
break;
case 03:
return "March";
break;
case 04:
return "April";
break;
case 05:
return "May";
break;
case 06:
return "June";
break;
case 07:
return "July";
break;
case 08:
return "August";
break;
case 09:
return "September";
break;
case 10:
return "October";
break;
case 11:
return "November";
break;
case 12:
return "December";
break;
default:
return "";
break;
}
}
在屏幕截图中,您可以看到我所做的一些故障排除。您可以看到拆分表明 1 应该是 08 的正确值,但是当我将它传递给 getMonth 函数时它不起作用。您还会看到传入 08 工作正常,因此错误似乎不在 getMonth 函数中。 除此之外,我尝试将文件添加到实际目录,这根本没有改变错误,但预期的功能确实有效。我也尝试删除有问题的文件并重命名另一个文件以具有相同的名称,但发生了同样的错误。
我真的希望这只是一个愚蠢的错误,因为我写了一些东西阻止了这个特定文件的工作,这真的让我很伤心。谢谢。
你最大的问题是类型混合。您的 split() 调用将 return 一个 字符串 的数组('01'、'02' 等),但是您的 getMonth() 函数定义为它打开值作为 整数 (01、02 等)。
现在,PHP 将允许这样做,因为它会为您做一些 type juggling。但是您 运行 在解释开关中的数字时遇到了更多麻烦。具体来说,您的前导零导致它们被解释为八进制(base-8)数字而不是您期望的十进制(base-10)数字。
我们可以深入研究血淋淋的细节,但它们在这里真的不重要,因为您应该通过始终如一地表示您的数字来解决这个问题。最快的方法是将 getMonth() 中的每个开关值替换为带引号的值:
function getMonth($nummonth) {
switch ($nummonth) {
case '01':
return "January";
break;
case 02;
return "February";
break;
case '03':
return "March";
break;
case '04':
return "April";
break;
case '05':
return "May";
break;
case '06':
return "June";
break;
case '07':
return "July";
break;
case '08':
return "August";
break;
case '09':
return "September";
break;
case '10':
return "October";
break;
case '11':
return "November";
break;
case '12':
return "December";
break;
default:
return "";
break;
}
}
这应该会让事情为你工作。它的工作原理是将这些值视为字符串,这将使它们与您为 $nummonth 传递的值相匹配,而不会破坏任何类型。
除此之外,请允许我提供一些其他提示:
- split() 函数已失效,甚至在最近的 PHP 版本中也不可用。如果需要通过正则表达式拆分字符串,请使用 preg_split()。在这种情况下,您只是按字符串常量 ('_') 进行拆分,因此您可以使用 explode(),这正是您在这里需要的。只需将 split() 调用切换为 explode() 调用,无需更改参数。
- 当你使用 echo 吐出 HTML 时,你真的应该转义它。请参阅 PHP 的 htmlentities() 函数。使用您显示的特定文件名数据,您不会 运行 遇到问题,但其他数据可能会导致页面行为异常或存在安全漏洞。
- 可以删除 $month 变量行。您不使用该变量,紧随其后的是 $filenameSplit 变量,它是同一事物,但命名更好。
- getMonth() 函数本身可以简化。对于像这样的简单映射,我通常喜欢使用数组。使用这种技术,您的函数可能类似于下面的 getMonth2()。请参阅 PHP's docs on arrays to learn how this works. However, in this specific case of converting a month number to a name, you can reduce it to a one-liner like in getMonth3(), below. See the docs on date() and strtotime() 了解此方法。
备选方案 1:使用数组作为映射:
function getMonth2($nummonth) {
$months = array(
'01' => 'January',
'02' => 'February',
'03' => 'March',
'04' => 'April',
'05' => 'May',
'06' => 'June',
'07' => 'July',
'08' => 'August',
'09' => 'September',
'10' => 'October',
'11' => 'November',
'12' => 'December',
); //$months
return $months[$nummonth];
} //getMonth2
备选方案 2:使用 PHP 的 date-related 函数
function getMonth3($nummonth) {
return date('F', strtotime("2017-$nummonth"));
} //getMonth3