简体   繁体   English

数组出现奇怪的PHP Scandir或Split错误

[英]Strange PHP Scandir or Split error with array

First, please forgive me, I'm still very new to this and I'm a little tired right now. 首先,请原谅我,我对此还很陌生,现在有点累。

I'm at my wits end over this. 我为此不知所措。 I've written a little PHP code so that a site I'm working on can update it's newsletters quickly and easily. 我写了一些PHP代码,以便我正在工作的网站可以快速,轻松地更新新闻稿。 The goal is to show the first newsletter as an embedded pdf and then show all the rest as links below it, so all the person who writes the newsletters needs to do is place them in the folder and use the proper naming format. 目的是将第一个新闻通讯显示为嵌入式pdf,然后将所有其余新闻显示为其下方的链接,因此,编写新闻通讯的所有人员需要做的就是将它们放在文件夹中并使用正确的命名格式。

I'm using scandir to scan the directory and return all the files in descending order, which will give the most recent file first provided they are named correctly (YYYY/MM). 我正在使用scandir扫描目录并以降序返回所有文件,如果文件的命名正确(YYYY / MM),它将首先提供最新文件。 It then splits that filename up and passes the month into a function that returns the actual name of the month, and plugs all of that into the html and generates the page. 然后,它拆分该文件名,并将月份传递到一个函数中,该函数返回月份的实际名称,并将所有名称插入html并生成页面。

It works perfectly, except for one thing. 除了一件事,它完美地工作。 One file won't show the month. 一个文件不会显示月份。 You can see in the screenshot that the file from August 2014 won't show the month, and I simply cannot figure it out. 您可以在屏幕截图中看到,2014年8月的文件不会显示月份,我根本无法弄清楚。 (Sorry about the stuff on the bottom, I can't post more than two links because I don't have enough rep so I had to make all my images into one, disregard the bottom half) (对于底部的内容,很抱歉,我不能发布两个以上的链接,因为我没有足够的代表,所以我不得不将所有图像都合而为一,而不必考虑底部的一半)

Here's the code for my main program (sorry about the formatting, I had to combine things because of these stupid restrictions) 这是我的主程序的代码(对格式感到抱歉,由于这些愚蠢的限制,我不得不组合东西)

//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;
    }
}

In the screenshot you can see some of the troubleshooting I did. 在屏幕截图中,您可以看到我进行的一些故障排除。 You can see that the split says that 1 should be the correct value for 08, but when I pass it into the getMonth function it doesn't work. 您可以看到split表示1应该是08的正确值,但是当我将其传递给getMonth函数时,它将不起作用。 You'll also see that passing in 08 works just fine, so the error doesn't seem to be in the getMonth function. 您还将看到传递08很好,所以该错误似乎不在getMonth函数中。 In addition to this, I tried adding a file to the actual directory, which did not change the error at all, but the intended functionality did work. 除此之外,我尝试将文件添加到实际目录中,该文件根本没有更改错误,但是预期的功能确实起作用。 I also tried removing the problematic file and renaming another file to have the same name, but the same error occurred. 我也尝试删除有问题的文件并重命名另一个文件以具有相同的名称,但是发生了相同的错误。

I'm really hoping this is just a stupid error where I wrote something that's preventing this specific file from working, it's really causing me some grief. 我真的希望这只是一个愚蠢的错误,我在其中写了一些阻止该特定文件正常工作的内容,这确实使我有些悲痛。 Thank you. 谢谢。

Your biggest problem is mixing of types. 您最大的问题是类型的混合。 Your split() calls will return an array of strings for the month ('01', '02', etc.), but your getMonth() function is defined so that it switches on values as integers (01, 02, etc.). 您的split()调用将返回月份的字符串数组(“ 01”,“ 02”等),但是您定义了getMonth()函数,以便将其值切换为整数 (01、02等)。 )。

Now, PHP will permit this because it will do some type juggling for you. 现在,PHP将允许这样做,因为它将为您做一些类型处理。 But you're running into further trouble with how the numbers inside your switch are being interpreted. 但是您在如何解释交换机内部的数字方面遇到了进一步的麻烦。 Specifically, your leading zeros are causing them to be interpreted as octal (base-8) numbers rather than the decimal (base-10) numbers that you're expected. 具体来说,您的前导零会导致它们被解释为八进制(基数8)数字,而不是您期望的十进制(基数10)数字。

We could delve into the gory details, but they're really not important here because you should fix this by representing your numbers consistently. 我们可以深入研究血腥的细节,但是在这里它们实际上并不重要,因为您应该通过始终如一地表示您的数字来解决此问题。 The quickest way to do this is to replace each of the switch values inside getMonth() with quoted values: 最快的方法是用引用的值替换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;
    }
}

That should get things working for you. 那应该为您工作。 It works by looking at those values as strings, which will make them match the values you're passing in for $nummonth without any type juggling to breaking things. 它通过将这些值视为字符串来工作,这将使它们与您为$ nummonth传入的值匹配,而不会发生任何类型的折衷事情。

Beyond that, though, allow me a few other tips: 不过,除此之外,我还可以提供其他一些提示:

  1. The split() function is dead, not even available in recent PHP versions. split()函数已失效,甚至在最新的PHP版本中也不可用。 If you need to split a string by regular expression, use preg_split(). 如果需要按正则表达式拆分字符串,请使用preg_split()。 In this case, you are just splitting by a string constant ('_'), so you can use explode(), which does exactly what you need here. 在这种情况下,您只是用字符串常量('_')进行拆分,因此可以使用explode()来完成您在此所需的操作。 Simply switch your split() calls to explode() calls, without changing the parameters. 只需将您的split()调用切换为explode()调用,而无需更改参数。
  2. When you're using echo to spit out the HTML, you should really be escaping it. 当您使用echo吐出HTML时,您实际上应该将其转义。 See PHP's htmlentities() function. 参见PHP的htmlentities()函数。 With the specific filename data you've shown, you won't run into a problem, but other data could cause the page to misbehave or present a security vulnerability. 使用显示的特定文件名数据,您不会遇到问题,但是其他数据可能会导致页面行为异常或出现安全漏洞。
  3. The $month variable line can be removed. $ month变量行可以删除。 You don't use that variable, and right after it, you have the $filenameSplit variable that is the same thing but much better named. 您无需使用该变量,紧随其后的是$ filenameSplit变量,它是相同的东西,但命名更好。
  4. The getMonth() function itself could be simplified. getMonth()函数本身可以简化。 For a simple mapping like this, I often like to use an array. 对于这样的简单映射,我经常喜欢使用数组。 With this technique, your function might look like getMonth2(), below. 使用此技术,您的函数可能类似于下面的getMonth2()。 See PHP's docs on arrays to learn how this works. 有关数组的工作原理,请参见PHP的有关数组的文档 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. 但是,在这种将月份数字转换为名称的特定情况下,可以将其减少为单行格式,如下面的getMonth3()所示。 See the docs on date() and strtotime() to learn about this approach. 有关此方法,请参阅有关date()strtotime()的文档。

Alternative 1: using an array as a map: 备选方案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

Alternative 2: using PHP's date-related functions 备选方案2:使用PHP的日期相关功能

function getMonth3($nummonth) {
    return date('F', strtotime("2017-$nummonth"));
} //getMonth3

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM