Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用「;“魔法班”;为了避免PHP致命错误,好主意?_Php_Oop_Design Patterns_Singleton_Magic Methods - Fatal编程技术网

使用「;“魔法班”;为了避免PHP致命错误,好主意?

使用「;“魔法班”;为了避免PHP致命错误,好主意?,php,oop,design-patterns,singleton,magic-methods,Php,Oop,Design Patterns,Singleton,Magic Methods,在我的许多网站上,我使用自制的PHP类“Logger”(基本上,它用于将信息记录到日志文件中,并按日期自动组织这些文件:年/月) 我通过在我的引导文件中创建一个Logger实例来使用它(包括在任何地方): 这迫使我在需要记录某些内容的每个函数中设置$mainLogger全局,并在调用任何方法之前检查记录器是否实例化: function foo($bar){ global $mainLogger; if( !is_null($mainLogger) ){ // If

在我的许多网站上,我使用自制的PHP类“Logger”(基本上,它用于将信息记录到日志文件中,并按日期自动组织这些文件:年/月)

我通过在我的引导文件中创建一个Logger实例来使用它(包括在任何地方):

这迫使我在需要记录某些内容的每个函数中设置
$mainLogger
全局,并在调用任何方法之前检查记录器是否实例化:

function foo($bar){
    global $mainLogger;
    if( !is_null($mainLogger) ){
        // If the logger is instanciated, I can log my message
        $mainLogger->log('error', 'mysql-errors', "My error message lorem ipsum dolor sit amet", Logger::GRAN_MONTH);
    }
}
为了使这个工具更易于使用和编写更少的代码,我正在考虑创建一个函数(在Logger类之外),用于处理
$mainLogger
(类似于单例设计模式)的实例化和检索:

MagicalClass旨在避免致命错误(致命错误:调用未定义的方法…),例如通过调用它(不包括Logger.class.php)可能引发的致命错误:

多亏了\u call\u get,任何尝试使用Logger类的属性或方法都不会导致任何错误(错误记录是可选功能,如果Logger不存在,它不应该简单地使应用程序崩溃)

你怎么看这种方法,这是个坏主意吗? 这会给我带来麻烦吗?什么样的麻烦

谢谢


PS:如果你想看Logger类,你可以在我的网站上下载。

你在这里描述的“问题”可以通过多种方式解决。最常见的三种是:

  • 使用
    工厂级
    。工厂类是一个对象生成工厂。工厂本身是一个静态类或单例类,在类中全局使用

  • 使用依赖项注入。使用此技术,logger类被注入类的构造函数中。该类保留对记录器的引用以供以后使用

  • 使用控制反转(IoC)容器。这是1和2的组合。容器是一个创建对象的列表,当需要一个新对象时,它会被创建,并且依赖对象会自动注入构造函数中

  • 示例:

    工厂级

    class Foo
    {
      public function Bar()
      {
        $logger = ClassFactory::CreateLogger();
    
        $logger->log('error', 'mysql-errors', 
          "My error message lorem ipsum dolor sit amet", Logger::GRAN_MONTH);
      }
    }
    
    依赖注入

    class Foo
    {
      private $logger;
    
      public function __construct($logger)
      {
        $this->logger = $logger;
      }
    
      public function Bar()
      {
        $this->logger->log('error', 'mysql-errors', 
          "My error message lorem ipsum dolor sit amet", Logger::GRAN_MONTH);
      }
    }
    

    你在这里描述的“问题”可以通过多种方式解决。最常见的三种是:

  • 使用
    工厂级
    。工厂类是一个对象生成工厂。工厂本身是一个静态类或单例类,在类中全局使用

  • 使用依赖项注入。使用此技术,logger类被注入类的构造函数中。该类保留对记录器的引用以供以后使用

  • 使用控制反转(IoC)容器。这是1和2的组合。容器是一个创建对象的列表,当需要一个新对象时,它会被创建,并且依赖对象会自动注入构造函数中

  • 示例:

    工厂级

    class Foo
    {
      public function Bar()
      {
        $logger = ClassFactory::CreateLogger();
    
        $logger->log('error', 'mysql-errors', 
          "My error message lorem ipsum dolor sit amet", Logger::GRAN_MONTH);
      }
    }
    
    依赖注入

    class Foo
    {
      private $logger;
    
      public function __construct($logger)
      {
        $this->logger = $logger;
      }
    
      public function Bar()
      {
        $this->logger->log('error', 'mysql-errors', 
          "My error message lorem ipsum dolor sit amet", Logger::GRAN_MONTH);
      }
    }
    

    我相信你不需要这门魔法课

    首先,这个magic类没有实现
    记录器
    ,因此类型提示(这是一件好事)将不起作用。其次,由于您的magic类没有实现或扩展
    Logger
    ,因此任何IDE也不会在magic类上显示自动完成。的确是件坏事

    如果以前未加载
    记录器
    ,则只需要magic类。这是非常基本的故障,应该很容易检测到。最简单的方法是将
    记录器
    包含在现在具有magic类的文件中

    另一方面,如何保证函数
    getLogger()
    可用?如果
    记录器
    可能不可用,则功能可能相同,您的代码也会同样失败

    代码改进:不要使用此选项:

    function getLogger(){
        global $mainLogger;
    
    您不需要全局变量,只需要存储记录器以供以后检索的变量。请改用静态变量:

    function getLogger(){
        static $mainLogger;
    

    如果您使用它,这个函数可以直接进入工厂类并被静态调用。变量
    $mainLogger
    将成为类的静态属性,可能在私有范围内。

    我认为您不需要这个神奇的类

    首先,这个magic类没有实现
    记录器
    ,因此类型提示(这是一件好事)将不起作用。其次,由于您的magic类没有实现或扩展
    Logger
    ,因此任何IDE也不会在magic类上显示自动完成。的确是件坏事

    如果以前未加载
    记录器
    ,则只需要magic类。这是非常基本的故障,应该很容易检测到。最简单的方法是将
    记录器
    包含在现在具有magic类的文件中

    另一方面,如何保证函数
    getLogger()
    可用?如果
    记录器
    可能不可用,则功能可能相同,您的代码也会同样失败

    代码改进:不要使用此选项:

    function getLogger(){
        global $mainLogger;
    
    您不需要全局变量,只需要存储记录器以供以后检索的变量。请改用静态变量:

    function getLogger(){
        static $mainLogger;
    

    如果您使用它,这个函数可以直接进入工厂类并被静态调用。变量
    $mainLogger
    将成为类的静态属性,可能在私有范围内。

    生产代码中不应出现致命错误。致命错误通常是非常严重的运行时错误,或者更糟的是语法错误(语法错误是编译时的,它们不能通过任何编程方式记录,并且总是致命的)。我认为JvdBerg的答案是正确的。使用包含日志功能的公共基类可能是一个快速修复方法?你可以帮助我们