[英]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.