[英]PHP - Calling a class function from another class
我试图创建一个可以从其他类调用的错误处理类,但是当我从另一个类的错误处理类中调用一个函数时,出现以下错误:
致命错误:在第361行的(filepath_here)中的null上调用成员函数fetch_error_text()
这是我到目前为止的代码:
global $errhandle_func_call;
class ERR_HANDLE
{
public function __construct()
{
}
public function fetch_error_text($err_text)
{
$err_text_display = $return_msg[$err_text];
return "<h4>" . $err_text_display . "</h4>";
}
}
$errhandle_func_call = new ERR_HANDLE();
class BASKET
{
public function view_basket()
{
//some_code_here
if($query->num_rows < 1)
{
echo $errhandle_func_call->fetch_error_text("basket_empty");
}
}
}
谢谢。
我不建议使用全局变量...但这应该可以解决... global
变量必须位于使用它的每个函数中。 看起来你还需要global
为您$return_msg
。
global $errhandle_func_call;
class ERR_HANDLE
{
public function __construct()
{
}
public function fetch_error_text($err_text)
{
global $return_msg;
$err_text_display = $return_msg[$err_text];
return "<h4>" . $err_text_display . "</h4>";
}
}
$errhandle_func_call = new ERR_HANDLE();
class BASKET
{
public function view_basket()
{
global $errhandle_func_call;
//some_code_here
if($query->num_rows < 1)
{
echo $errhandle_func_call->fetch_error_text("basket_empty");
}
}
}
[UPDATE 2015-04-29]简而言之,快速,粗略地介绍我的建议...从最简单到最困难...我也将更改您的大小写,因为ALL_UPPERCASE通常用于表示常量,我有点强迫症。
静态错误类别:
class ErrorType {
const UserError = 1;
const NotFoundError = 2;
public static function getMessage( $messageId ) {
switch( $messageId ) {
case self::UserError: return "user error";
case self::NotFoundError: return "not found error";
}
}
}
class ErrorHandler {
public static function fetchErrorText( $errorType) {
return "<h4>".ErrorType::getMessage($errorType)."</h4>";
}
}
ErrorHandler::fetchErrorText( ErrorType::UserError );
这绝对是最简单的方法,可让您远离全局。 我添加了ErrorType类,通过为您提供常量值以传递到函数中来减少代码中的“魔术字符串”。 这将有助于避免输入错误,因为您的IDE可以为您提供智能感知。
但是,静态类对单元测试不友好。 因此,这就是“依赖反转”可以发挥作用的地方。 反转依赖关系的最简单方法是服务定位器,因为您不必修改构造函数就可以传递对象的实例。 有人认为这是一种反模式,但是在正确的情况下(例如,约定优于配置等)非常有用。
依赖倒置:服务定位器
//first thing you need for inversion is an interface
interface IHandleError {
public function getErrorMessage( $errorType );
}
//imaginary ServiceLocator class, defining instance of interface to use
ServiceLocator::define( array(
'IHandleError' => 'SomeNamespace\ErrorHandler'
) );
class Basket {
public function viewBasket() {
//grab it when you need it
$errorHandler = ServiceLocator::get('IHandleError');
if( query->num_rows < 1 ) {
echo $errorHandler->getErrorMessage( ErrorType::BasketEmpty );
}
}
}
ServiceLocator对象是虚构的...但是以最简单的形式,它只是一个键=> value的数组,其中值指向一个类...,而:: get()方法实例化该类的实例或单例。 我在这里做更多的“魔术弦”,但不想让它太复杂。
依赖倒置:依赖注入
另一方面,从概念上讲,依赖注入比ServiceLocator更简单...但是有时在实现上会更困难,因为您需要访问以修改类的构造函数并能够修改其实例以传递给对象。
class Basket {
private $_errorHandler;
public function __construct( IHandleError $errorHandler ) {
$this->_errorHandler = $errorHandler;
}
}
$basket = new Basket( $errorHandler );
这3种方法中的任何一种都会使您远离全局变量,并稍微提高代码的可维护性。
为什么不使用遗产? 您的班级BASKET可以从ERR_HANDLE扩展:
class BASKET extends ERR_HANDLE {
public function view_basket() {
//some_code_here
if($query->num_rows < 1) {
echo parent::fetch_error_text("basket_empty");
}
}
}
根据天气的不同,您的课程需要依赖项,或者它是否可选,取决于您如何“注入”它。 请注意,“依赖项”可以是对象(实例化的类)或属性 (类成员变量)。
看起来,您的“ BASKET”类需要 “ ERR_HANDLE”类才能正常工作,因此使用“构造函数注入”是“最佳实践”。构造函数注入意味着将其“注入”到“ construct”方法中班上的
这种(依赖注入)可以将许多其他问题分开。
<?php
class ERR_HANDLE
{
public function fetch_error_text($err_text)
{
$err_text_display = $return_msg[$err_text];
return "<h4>" . $err_text_display . "</h4>";
}
}
<?php
class BASKET
{
private $err_handle;
public function __construct($err_handle)
{
$this->err_handle = $err_handle;
}
public function view_basket()
{
//some_code_here
if($query->num_rows < 1)
{
// The next line is where you use the injected objects method.
return $this->err_handle->fetch_error_text("basket_empty");
}
}
}
<?php
// Instantiate the error handle class.
$err_handle = new ERR_HANDLE();
// Whilst instantiating the BASKET class, inject the ERR_HANDLE object.
$basket = new Basket($err_handle);
// View the basket.
echo $basket->view_basket();
现在,您应该能够解决的最后一个问题是如何将变量“ $ return_msg”放入您的“ ERR_HANDLE”类。 PS:注入它。
我建议阅读命名空间 ,对类和对象更加熟悉,并阅读有关依赖项注入的知识。
从未停止学习...
看起来您实际上不是在尝试从中运行ERR_HANDLE实例的作用域内实例化该实例。
$ errhandle_func_call是在BASKET类范围之外创建的,但是该对象需要在BASKET类的公共函数中可用
您可以使用自动加载文件,通过使用此代码来加载目录内的所有“ .class.php”文件。
<?
function __autoload($classname)
{
require_once(strtolower($classname).'.class.php');
}
$first_class = new first_class();
$second_class = new second_class();
?>
因此,您将所有类文件放在与此文件相同的目录中。 并且您只需将此文件包含在要使用任何类的所有页面中
您可以使用另一种方法。
<?php
class error {
public function hes_dead() {
// deal with error
}
}
class needs_error_class {
private $err;
public function __construct() {
// This is called dependency injection.
$this->err = new Error;
}
public function some_function() {
// need that error handing now
$this->err->hes_dead();
}
}
另外,您可以尝试这种方式来调用您的课程。
class ERR_HANDLE
{
public function empty_basket_error_text($err_text)
{
return "<h4>".$err_text."</h4>";
}
}
class BASKET
{
public function view_basket()
{
//some_code_here
//if($query->num_rows < 1)
// {
$this->errhandle = new ERR_HANDLE();
return $this->errhandle->empty_basket_error_text("Empty basket");
// }
}
}
$basket = new BASKET();
echo $basket->view_basket();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.