php - 单例、传递对象、使用静态、返回错误还是全局变量?

标签 php oop static singleton global-variables

我知道,全局变量不是 (;

我是 OOP 新手,我正在将创建的一些函数重构为类,但遇到了问题。我的一些类是从用户输入的页面本身调用的(例如:$Link->create('page/to/go');)。由于这在任何类之外,所以没有问题,链接将被创建。

但是,我有一个类在创建时尝试登录用户,如果输入的电子邮件不在数据库中,它会将用户重定向到注册页面。显然,只做 header('Location '.$Link->create('page/to/go')) 是行不通的。

我要做的是将create方法设置为静态,然后从任何地方调用它。但我认为这与使用全局变量类似,我正在努力纠正坏习惯。那么我该怎么做呢?

这里是 Link 类的一些代码,实现了我解释过的 404 检测 here :

class Link
  {
  private function valid($check)
    {
    $exceptions=array("help/report", "translate");  // More pages and rules to be added
    return in_array($check,$exceptions);
    }

  public function create($arg)
    {
      if (!file_exists("/path/to/".$arg) && !$this->valid($arg))
      {
      // Call a function to store the error in a database.
      error ("404 for ".$arg);

      // One way of handling it. Replace '/' for ' ' and google that string in this page.
      $arg=str_replace("/","%20",$arg);
      return "https://www.google.com/#q=site%3A".Configuration::get('BaseUrl')."%20".$arg;
      }
    else
      {
      // If the page exists or is an exception, create the normal link.
      if(empty($arg)) return Configuration::get('BaseUrl');
      else return Configuration::get('BaseUrl').$arg;
      }
    }
  }

正如您在代码中看到的,当我在类中实现 error() 时,我也会遇到类似的问题。

我刚刚想到的一个选择是我可能想返回一个错误并从 User 类的 __construct() 外部解析它。但它只适用于这种情况,因为它是/否,而且我认为编写错误代码不适用于其他情况。

那么,对于将属性和方法从一个类传递给其他类,您有何建议?可以在此上下文中使用 static 吗?

编辑。我的问题的难点在于,我见过的几乎所有书籍、教程、页面等都讨论了如何创建单个类。我还没有看到任何深入解释类应该如何相互通信的内容。

编辑2.根据评论中的要求,这里还有一些代码。用户仅输入电子邮件(获得级别 1)即可访问其类(class),而用户只有在设置页面中获得级别 2 时才能编辑其设置。未完成,我将添加更多方法。

class User
  {
  private $Email;
  private $Name;

  public function __construct()
    {
    if (!empty($_POST['logout'])) session_destroy();
    else if ( !empty($_POST['email']) )
      {
      $this->loginEmail($_POST['email']);
      }
    else if ( $_SESSION['level'] == 1 )
      {
      if (!empty($_POST['password']))
        {
        $this->loginFull($_SESSION['email'],$_POST['password']);
        }
      else
        {
        $this->loginEmail($_SESSION['email']);
        }
      }
    else if ( $_SESSION['level'] == 2 )
      {
      $this->loginFull($_SESSION['email'],$_SESSION['pass']);
      }
    else session_destroy();

    }

  private function loginEmail($Email)
    {
    $sql=mysql_query("SELECT * FROM users WHERE email='".mysql_real_escape_string($Email)."'");  //Retrieve the entries from the database
    $row=mysql_fetch_assoc($sql);
    if(mysql_num_rows($sql)==1)
      {
      $this->getData($row);
      $_SESSION['level']=1;
      }
    else header ('Location: http://example.org/new/student/');
    }

  private function loginFull($Email,$Pass)
    {
    $sql=mysql_query("SELECT * FROM users WHERE email='".mysql_real_escape_string($Email)."' AND pass='".md5($Pass)."'");  //Retrieve the entries from the database
    $row=mysql_fetch_assoc($sql);
    if(mysql_num_rows($sql)==1)
      {
      $this->getData($row);
      $_SESSION['pass']=$Pass;
      $_SESSION['level']=2;
      }
    else $this->loginEmail($Email);
    }

  private function getData($row)
    {
    $_SESSION['email']=$row['email'];
    $this->Email=$row['email'];
    $this->Name=$row['name'];
    }

  public function get($Var)
    {
    return $this->$Var;
    }
  }

现在是Error类。正如你所看到的,我已经执行了一些 DI,甚至不知道这里。

class Error
  {
  private $Page;
  private $Language;
  private $User;

  public function __construct($Page,$Language,$User="None")
    {
    $this->Page=$Page;
    $this->Language=$Language;
    $this->User=$User;

    if (!empty($_REQUEST['banner']))
      $this->Banner=$_REQUEST['banner'];
    }

  public function add($Kind)
    {
    if (!mysql_query("INSERT INTO error (kind, page, lang, user, version, date) VALUES ('".mysql_real_escape_string($Kind)."', '".mysql_real_escape_string($this->Page)."', '".mysql_real_escape_string($this->Language)."', '".mysql_real_escape_string($this->User)."', '".Configuration::get('Version')."',NOW() )"))

    mail(Configuration::get('ErrorEmail'), "Error '".$Kind."' that couldn't be stored.",
       "Full url: ".$FullUrl."\n Language: ".$this->Language->Lang."\n User: ".$Identif."\n Version: ".$Version);  // Inform of the error by email
    }
  }

最佳答案

创建 Link 类的实例并将其传递到需要的地方(使用 setter 或构造函数)。 一定要阅读有关 DI(依赖注入(inject))和 DI 容器的内容。

Nette Framework - Dependency Injection 中有很好的介绍

关于php - 单例、传递对象、使用静态、返回错误还是全局变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12300756/

相关文章:

php - 如何使用 PHP 从字符串中删除子字符串?

perl - 在 Perl 中重载 '='

c - 如何在不调用声明它的函数的情况下修改局部静态变量?

java - 注入(inject)静态EJB,废话?

php - 如何在 Yii2 中显示带有子类别的类别

php - 如何构建具有一定数量随机奖品的 'Click-to-Win' 类型竞赛

ruby-on-rails - 时间戳字段的 ActiveResource MassAssignmentSecurity 错误

android - 安卓代码分析工具

php - 基于两个不同因素在数据库中获取最新输入的算法

class - 如何从具有相同名称 IsTesting() 的类方法调用内置函数 IsTesting()?