PHP - 我可以创建一个除了通过另一个类之外无法实例化的类吗?

时间:2012-07-08 01:39:07

标签: php class exception exception-handling instantiation

我正在尝试从Exception类中创建一个子类来处理错误并在给定错误代码时发出正确的错误消息。我改变了我的原始代码并使其更简单,只是为了说明我的问题。

也许这是不可能的,但我不希望脚本实例化InvalidEmailException类。如果有必要,我只希望它由Subscribe类使用(发现错误)。为什么我还想要这样做呢?无关紧要我只是想了解班级是如何运作的。

/* Child class from the parent Exception class to handle errors 
 * pertinent to users being subscribed
 */
class InvalidEmailException extends Exception{
   private $error_code;
   private $email;
   function __construct($error_code, $email){
      $this->error_code = $error_code;
      $this->email = $email;
      $this->notifyUser();
   }
   function notifyUser(){
        if($this->error_code == 2):
         echo "<p>Invalid email: <em>{$this->email}</em></p>";
      endif;
   }
}

// Initial class to subscribe a user with the try catch checks
class Subscribe{
   private $email;
   private $error_code = 0;
   function __construct($email){
      $this->email = $email;
      $this->validateEmail();
   }

   private function validateEmail(){
      try{
         if($this->email == ''):
            throw new Exception('<p>Error: empty email address.</p>');
         else:
            if($this->email == 'invalid test'){
                    $this->error_code = 2;
               throw new InvalidEmailException($this->error_code, $this->email);
            }elseif($this->error_code == 0){
               // Go to method to subscribe a user if the error code remains zero
               $this->subscribeUser();
            }
         endif;
      }catch(Exception $e){
         echo $e->getMessage();
      }
   }

   private function subscribeUser(){
      echo $this->email.' added to the database!';
   }
}

/* 
 * Script to use the Subscribe class, which would call 
 * the InvalidEmailException class if needed
 */
$email = 'invalid test'; // This could later on be used through the $_POST array to take an email from a form
$subscribe = new Subscribe($email); // Works well.
$test = new InvalidEmailException('2', 'a@b.c'); // Also works.  I want this to throw an error.

3 个答案:

答案 0 :(得分:2)

不,除了PHP中的“一切都可见”之外,你实际上不能拥有任何类别的可见性。您可以使用人们告诉过的各种黑客来部分地近似它,但它们是毫无意义的浪费时间,因为它们无法强制执行可见性约束(如果程序员想要违反您的伪约束,所有这些都会受到琐碎的解决方法)如果没有强制执行,你也可以在程序员级别实现它(即如果你认为不应该这样做,那就不要这样做了。)

如果您关注的是使用非常有限的使用异常类来污染全局类命名空间(这将是我鼓掌的有效问题),那就是namespaces的用途;典型的专业PHP 5.3架构将您的课程设为YourApp\Email\SubscribeYourApp\Email\InvalidAddressException。 (顺便允许Subscribe内的代码抛出new InvalidAddressException而不需要use语句或完整的命名空间规范。)

答案 1 :(得分:1)

我认为您最好的选择是使用依赖注入http://en.wikipedia.org/wiki/Dependency_injection。它有点先进但我认为从长远来看会有所帮助..

基本上,您可以使用获取所需数据的方法创建公共接口,并使异常类的构造函数具有接口类型的参数。然后让subscribe类实现接口,这将允许它传递给异常的构造函数。

您也可以直接将subscribe对象作为参数传递给异常类的构造函数,并绕过接口使用。但是,该接口允许您让多个类都使用该接口和那些常用方法,如果您使用该模式,它们都可以构建您的异常类。而且你也会知道如何与这些类进行交互,因为它们使用相同的通用设计。

这并不能完全阻止你从类外部和脚本中构造异常,但是你需要先构造实现接口的类(或者只是类本身,这取决于你走哪条路) ),这是限制行为的好方法。

答案 2 :(得分:-1)

这是一个想法。

使用define设置“全球化”变量。

所以在你的订阅类__construct函数中设置一个像define( 'IN_USE', 1 );这样的变量然后如果/当调用InvalidEmailException时只检查:

if( !IN_USE ) { exit; }