单例,传递对象,使用静态,返回错误或全局变量?

时间:2012-09-06 13:02:56

标签: php oop static singleton global-variables

我知道,全局不是(;

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

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

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

以下是类Link的一些代码,实现了我在here解释的404检测:

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

EDIT。我的问题很难解决,几乎所有的书籍,教程,页面等我都看过如何创建一个SINGLE类。我没有看到任何课程应该如何相互交谈。

编辑2.根据评论中的要求,这里有更多代码。用户访问他的课程仅输入电子邮件(获得级别1),而用户只有在设置页面中获得级别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
    }
  }

2 个答案:

答案 0 :(得分:1)

创建Link类的实例并将其传递到需要的位置(使用setter或constructor)。 Definitelly读取了DI(依赖注入)和DI容器的内容。

Nette Framework - Dependency Injection

中的精彩介绍

答案 1 :(得分:1)

Singletons和Static不是一个好选择。最终一切都落在了全局问题上。

你应该通过构造函数或setter将你的link helper注入类中(DI为@jasir所说的。)

如果您要重定向用户,还可以注入redirector helper

$redirector->redirect('controller','action', array('my','params'));

  

提示:这也很糟糕Configuration::get()。请改为注入配置   永远记住:Don't look for things!