我目前正在将一个标准PHP项目迁移到CakePHP框架项目中,但经常遇到以下错误消息:致命错误:在第XX行/source/code/file.PHP中的非对象上调用成员函数FunctionName()。旧的应用程序类文件在CakePHP之外的完全相同的web服务器上运行良好,但当复制到CakePHP应用程序libs文件夹并包含时,我会收到此错误消息。似乎有一些东西影响了全局变量的范围,但我已经尝试设置ini_set('register_globals',1);这根本没有什么区别。
示例测试场景(这发生在所有像这样的应用程序类上)如下。
调试类文件内部,例如debug.php:
<?php
class DebugObject {
var $aDebugLog;
var $aTemplate;
function DebugObject( $aTemplate ) {
$this->aDebugLog = array();
$this->aTemplate = $aTemplate;
}
function AddEntry( $aEntry ) {
if( DEBUG == true ) $this->aDebugLog[] = $aEntry;
}
function OutputHtml() {
if( DEBUG == true ) {
$sHtml = '<table style="border: 1px solid #ccc;"><tr>';
foreach( $this->aTemplate as $rTemplate ) {
$sHtml .= '<th style="text-align: left; font-family: Mensch; font-size: 8pt;">' . $rTemplate['name'] . '</th>';
}
$sHtml .= '</tr>';
foreach( $this->aDebugLog as $aEntry ) {
$sHtml .= '<tr>';
$iTemplate = 0;
foreach( $aEntry as $rEntry ) {
$sHtml .= '<td style="border: 1px solid #ccc; padding-right: 10px; font-family: Mensch; font-size: 8pt;">' . sprintf( $this->aTemplate[$iTemplate]['format'], $rEntry ) . '</td>';
$iTemplate++;
}
}
$sHtml .= '</table>';
return $sHtml;
} else {
return '';
}
}
}
$aTemplate = array(
array( 'name' => 'Time', 'format' => "%-10s" ),
array( 'name' => 'Parameter', 'format' => "%-35s" ),
array( 'name' => 'Value', 'format' => "%-80s" )
);
$oDebugObj = new DebugObject( $aTemplate );
class Debug {
function Add( $sName, $sValue ) {
global $oDebugObj;
$oDebugObj->AddEntry( array( date( 'H:i:s' ), $sName, $sValue ));
}
function Output() { global $oDebugObj; return $oDebugObj->OutputHtml(); }
}
在其他地方的应用程序文件中,可以是任何包含的.php文件/controller/view等,例如test.php(通常define和require_one行将在引导程序/配置文件中):
<?php
define( 'DEBUG', true );
require_once( 'debug.php' );
Debug::Add( 'Testing', 123 );
echo Debug::Output();
当我完全作为一个独立的PHP web应用程序运行上面的代码时,我会得到一个打印得很好的HTML表,其中包含一个调试条目。但是,例如,如果我将debug.php放在libs文件夹中,并使用layout.ctp文件中的应用程序文件代码,我会立即收到错误消息Fatal error: Call to a member function AddEntry() on a non-object in /var/www/domain.com/cakephp/website/libs/debug.php on line 55
,即$oDebugObj->AddEntry( array( date( 'H:i:s' ), $sName, $sValue ));
行
如果有人能帮忙,我将不胜感激。如果它只是调试函数,我可以很容易地修改它来解决这个问题,方法是让它一直使用Debug->
objcet,而不是Debug::
类。然而,整个旧项目都遵循这种方法,我不明白为什么需要重写CakePHP下的函数。这肯定是一个相对简单的问题吗?请帮帮我!!非常感谢。
是否将文件包括在全局范围内
来自您的一条评论:
我。。。从视图ctp文件或从app/config文件夹中的bootstrap.php文件中包括它们
问题中的这一类假设它包含在全球范围内,即这将起作用:
<?php
include 'debug.php';
echo Debug::Output();
但这不会:
<?php
includeStuff() {
include 'debug.php';
}
includeStuff();
echo Debug::Output();
在CakePHP中,一旦你离开index.php文件,你就不在全局范围内了,像问题中的代码示例中那样推断的全局将不起作用。
解决方案是在加载cake之前,在webroot/index.php
文件中包含遗留的依赖全局代码。
或者更正/调整代码
这依赖于全局$oDebugObj
的存在,很明显,当你调用它时,全局并不存在:
function Add( $sName, $sValue ) {
global $oDebugObj;
$oDebugObj->AddEntry( array( date( 'H:i:s' ), $sName, $sValue ));
}
它可以在不假设全球已经存在的情况下工作:
function Add( $sName, $sValue ) {
global $oDebugObj;
if (!$oDebugObj) {
$aTemplate = array(
array( 'name' => 'Time', 'format' => "%-10s" ),
array( 'name' => 'Parameter', 'format' => "%-35s" ),
array( 'name' => 'Value', 'format' => "%-80s" )
);
$oDebugObj = new DebugObject( $aTemplate );
}
$oDebugObj->AddEntry( array( date( 'H:i:s' ), $sName, $sValue ));
}
或者只使用调试功能
问题中的类看起来没有那么多功能,所以你也可以将其更改为日志数据:
function Add( $sName, $sValue ) {
CakeLog::write(LOG_DEBUG, json_encode(array($sName => $sValue)));
}
或者直接转储到屏幕:
function Add( $sName, $sValue ) {
debug(array($sName => $sValue));
}