2

私は知っています、グローバルではありません(;

私はOOPを初めて使用し、作成したいくつかの関数をクラスにリファクタリングしていますが、問題が発生します。一部のクラスは、ユーザーが入力したページ自体から呼び出されます(例:) $Link->create('page/to/go');。これはクラス外なので問題ありません。リンクが作成されます。

しかし、作成時にユーザーにログインしようとするクラスがあり、入力された電子メールがデータベースにない場合は、ユーザーを登録ページにリダイレクトします。明らかに、header ('Location '.$Link->create('page/to/go'))を実行するだけでは機能しません。

私がすることは、createメソッドを静的に設定してから、どこからでも呼び出すことです。しかし、これはグローバルを使用することに似ていると思います。私は悪い習慣を修正しようとしています。では、これをどのように行う必要がありますか?

これがクラスのコードの一部で、ここで説明Linkした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()をクラスに実装すると、同様の問題が発生します。

私が今考えたオプションの1つは、エラーを返し、Userクラスの__construct()の外部からエラーを解析したい場合があるということです。しかし、これはyes / notであるため、これでのみ機能します。他の場合には、エラーコードを作成することは適切ではないと思います。

では、あるクラスから別のクラスにプロパティとメソッドを渡すための提案は何ですか?staticこのコンテキストで使用しても大丈夫ですか?

編集。私の質問の難しさは、私が見たほとんどすべての本、チュートリアル、ページなどが、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
    }
  }
4

2 に答える 2

1

シングルトンとスタティックは良い選択ではありません。結局、すべてがグローバル問題に分類されます。

link helperコンストラクターまたはセッター(@jasirが言ったようにDI)によってクラスに自分を注入する必要があります。

ユーザーをリダイレクトする場合は、redirector helper:を挿入することもできます。

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

ヒント:これも悪いConfiguration::get()です。代わりに構成を挿入します。
そして常に覚えておいてください:物事を探してはいけません!

于 2012-09-06T13:22:18.973 に答える
1

Linkクラスのインスタンスを作成し、必要な場所に渡します(setterまたはコンストラクターを使用)。間違いなくDI(依存性注入)について何かを読んでから、DIコンテナを読んでください。

NetteFrameworkの素晴らしい紹介-依存性注入

于 2012-09-06T13:20:00.483 に答える