0

我目前正在将标准 PHP 项目迁移到 CakePHP 框架项目中,但我经常遇到此错误消息:致命错误:在 /source/code/file.php 中的非对象上调用成员函数 FunctionName() 在线二十。旧的应用程序类文件在 CakePHP 之外的完全相同的 Web 服务器上运行良好,但是当复制到 CakePHP 应用程序库文件夹并包含时,我收到此错误消息。似乎有些东西正在影响全局变量的范围,但我尝试设置 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 文件/控制器/视图等,例如test.php(通常 define 和 require_once 行将在 bootstrap/config 文件中):

<?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 下的函数。当然,这一定是相对简单的解决方法?请帮帮我!谢谢你。

4

1 回答 1

0

您是否将文件包含在全局范围内?

从您的一条评论中:

我是...从查看 ctp 文件或从 app/config 文件夹中的 bootstrap.php 文件中包含它们

问题中的此类假定它包含在全局范围内,即这将起作用:

<?php
include 'debug.php';
echo Debug::Output();

这不会:

<?php
includeStuff() {
    include 'debug.php';
}

includeStuff();
echo Debug::Output();

在 CakePHP 中,只要您离开index.php文件 - 您就不再处于全局范围内,并且推断的全局变量(例如问题中的代码示例)将不起作用。

一个解决方案是在你的文件中加载蛋糕之前包含你遗留的依赖全局代码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));
}
于 2013-07-04T13:41:28.550 回答