这把我逼疯了。我有一个写日志文件的标准例程,它运行得非常好,以至于我几乎忘记了代码中的内容。把它转移到一个新的项目,做了一个改变,它的行为非常怪异。错误消息说fopen()无法打开日志文件,但条目仍在日志文件中写入。我不喜欢有任何描述的错误或警告,所以我不打算忽略这个错误,因为尽管有错误,它似乎仍在工作。
我所做的更改是以设置$_session['base_dir_prefix']的方式进行的。在以前的项目中,这是在主页上下文中设置的,并设置为该目录的绝对路径。这有一个弱点,你不能直接进入一个页面,而不必通过索引。在这个项目中,我不能这样做,所以我把它设置为相对路径——例如$ySale[ [ BaseXDILYPROFECTION] ] =“..”;就我所见,前缀设置正确。事实上,就我所见,一切都是正确的,但显然有一根针在那里的某个地方,将需要另一双眼睛看到!
我最大的问题之一是,如果fopen()无法打开文件,那么为什么要写入?
附件1-实际writeLog函数的源代码。注意,回音语句纯粹用于调试目的,而不是正常执行的一部分。

function writelog($str=" ")
{
    if (isset($_SESSION['base_dir_prefix']))
    {
        $prepend = $_SESSION['base_dir_prefix'] ;
    }
    else
    {
        $prepend = $_SERVER['DOCUMENT_ROOT'] ;
    }

    if ( substr($prepend, -1, 1) <>  DIRECTORY_SEPARATOR )
    {
        $prepend .= DIRECTORY_SEPARATOR ;
    }
    $fname = $prepend."log/log.txt" ;
    $mode = "a" ;

    echo getcwd(). "\n" ;           // debug code
    echo $fname." Files exists?:".file_exists($fname) ."\n";
    echo $str."\n" ;

    $fp = fopen($fname, $mode) ;

    fwrite( $fp, date("Y-m-d H:i:s").": " ) ;
    fwrite( $fp, $str."\n" ) ;
    fclose( $fp ) ;
}

图表2-调用函数的代码
    $u->writelog ("SA OLU entering Option List Users function") ;
    $u->writelog ("Current dir:".getcwd()." ") ;

    $usr_list = array(array( "None", "None") );
    $sc->user_list($usr_list) ;
    $i = 0 ;
    $res = "" ;
    $actv_flag = strtoupper($active) ;

    if ($usr_list[0][0] != "None" )
    {
        while ($i < count($usr_list))
        {
            if ((bool)$usr_list[$i][2] == true && $actv_flag == "YES")   //only active users
            {
                $i++ ;
                continue ;
            }
            $res .= sprintf( "<option value=\"%s\"> %s (%s) </option> \n",
                             $usr_list[$i][0],
                             $usr_list[$i][1],
                             $usr_list[$i][0]
                           );
            $i++ ;
        }
     } else
     {
            $res = sprintf( "<option value=\"no_recs\"> No Program Records </option> \n" ) ;
     }
     $u->writelog ("SA OLU leaving Option List Users function") ;

展示3 -日志文件本身。由附件1创建的条目。注意,这个文件上的时间戳比实际时间晚1小时。不知道为什么,因为我是唯一一个看这个文件的人,我并没有过分担心。
2014-11-21 16:29:58: SA OLU entering Option List Users function
2014-11-21 16:29:58: Current dir:/srv/www/dev/gillies/security
2014-11-21 16:29:58: SA OLU leaving Option List Users function
2014-11-21 16:29:58: SA OLU entering Option List Users function
2014-11-21 16:29:58: Current dir:/srv/www/dev/gillies/security
2014-11-21 16:29:58: SA OLU leaving Option List Users function
2014-11-21 16:29:58: SA OLU entering Option List Users function
2014-11-21 16:29:58: Current dir:/srv/www/dev/gillies/security
2014-11-21 16:29:58: SA OLU leaving Option List Users function

图表4-apache错误日志文件
[Fri Nov 21 15:29:25.047732 2014] [:error] [pid 20588] [client 192.168.0.19:62116] PHP Warning:  fwrite() expects parameter 1 to be resource, boolean given in /srv/www/dev/gillies/php/utilities.php on line 72
[Fri Nov 21 15:29:25.047746 2014] [:error] [pid 20588] [client 192.168.0.19:62116] PHP Warning:  fclose() expects parameter 1 to be resource, boolean given in /srv/www/dev/gillies/php/utilities.php on line 73
[Fri Nov 21 15:29:58.721627 2014] [:error] [pid 17084] [client 192.168.0.19:62141] PHP Warning:  fopen(../log/log.txt): failed to open stream: No such file or directory in /srv/www/dev/gillies/php/utilities.php on line 69
[Fri Nov 21 15:29:58.721698 2014] [:error] [pid 17084] [client 192.168.0.19:62141] PHP Warning:  fwrite() expects parameter 1 to be resource, boolean given in /srv/www/dev/gillies/php/utilities.php on line 71
[Fri Nov 21 15:29:58.721711 2014] [:error] [pid 17084] [client 192.168.0.19:62141] PHP Warning:  fwrite() expects parameter 1 to be resource, boolean given in /srv/www/dev/gillies/php/utilities.php on line 72
[Fri Nov 21 15:29:58.721720 2014] [:error] [pid 17084] [client 192.168.0.19:62141] PHP Warning:  fclose() expects parameter 1 to be resource, boolean given in /srv/www/dev/gillies/php/utilities.php on line 73

图表5-显示回声结果的生成的HTML代码片段。由附件2创建的条目。再次,这只是为了诊断的目的,而不是生产文件的一部分。
                    </h4><select name="users" size="5">
                      /srv/www/dev/gillies/security
../log/log.txt Files exists?:1
SA OLU entering Option List Users function
/srv/www/dev/gillies/security
../log/log.txt Files exists?:1
Current dir:/srv/www/dev/gillies/security
/srv/www/dev/gillies/security
../log/log.txt Files exists?:1
SA OLU leaving Option List Users function
        <option value="loginid"> name (loginid) </option>

图表6-日志文件的目录结构
darryl@thedoctor:/srv/www/dev/gillies/log$ pwd
/srv/www/dev/gillies/log
darryl@thedoctor:/srv/www/dev/gillies/log$ ls -l
total 8
-rw-rw-rw- 1 www-data www-data 4743 Nov 21 15:33 log.txt

有线索吗?
谢谢。

最佳答案

我找到了答案,它在提供给fOpen-()的相对路径中。我重新编写代码来创建一个绝对的而不是相对的前缀,所有的错误都消失了。我需要做一些字符串操作来获得正确的目录,现在新代码如下所示:

$here = getcwd() ;
$posn = strrpos($here, "/") ;
if($posn === false) {
    $_SESSION['base_dir_prefix'] = "../" ;
}
else {
    $_SESSION['base_dir_prefix'] = substr($here, 0, $posn) ;
}

谢谢你的建议,达伦。我绕着圈子想弄清楚还能做什么。
新代码获得目录的绝对路径,该目录位于层次结构中的第二级,并将路径修整回一个级别,以便指向文档根目录。
对于那些可能想知道为什么在获取目录时会遇到这些麻烦的人来说,这使得代码完全可以重新定位。在网站经过开发、测试、验收和生产阶段时,不能保证文档根目录相对于web服务器文档根目录处于相同的级别。这允许网站放置在目录层次结构内的任何地方,而不必更改对文件的引用等。

10-06 05:10
查看更多