2016-12-20 2 views
0

Я читал в ООП какое-то время, и это меня всегда смущает, но я пытаюсь улучшить свои навыки (хотя я все еще начинаю с этого так, пожалуйста, будь добрым).PHP OOP: Как объединить многоместные классы вместе

Я разрабатываю основное приложение, чей «основной» класс $App. Я думал, что в любом месте приложения вы можете делать все, начиная с $App.

Например, у меня есть класс $Db для запроса базы данных, $Mail класс для отправки электронной почты и т. Д. Все они автоматически загружаются с использованием spl_autoload_register.

Мой вопрос заключается в том, чтобы правильно их создать. Вот как я делаю это сейчас:

index.php

require_once('config.php'); // Autoloads classes and some other small stuff 

$App = new App; 

echo $App->Visitor->getIP(); 

App.class.php

class App { 

    public function __construct() { 
     $this->initialize();  
    } 

    private function initialize() { 

     $this->Visitor = new Visitor($this); 
     $this->Db = new Db($this); 
     $this->Mail = new Mail($this); 

    } 

    // Then some public methods... 
    // We are able to use $this->Visitor, $this->Db, etc... 

} 

Visitor.class.php

class Visitor { 

    private $App; 

    public function __construct($App) { 
     $this->App = $App; // I need access to all of App's methods 
    } 

    public function getIP() { 
     return $_SERVER['REMOTE_ADDR'];  
    } 

} 

Так короткий пример выше показывает, как я это делаю во всех своих классах. Класс App всегда создает экземпляр любого класса, который мы будем использовать во всем приложении в его конструкторе.

«Дети» классы все [зависимые инъекции?] $App экземпляр, чтобы они могли использовать его методы.

Я делаю это правильно? Это работает, но я не знаю, есть ли более эффективный/более эффективный способ сделать это.

+0

Интересно, что я опубликовал аналогичный вопрос в [Software Engineering] (http://softwareengineering.stackexchange.com/questions/337896/dividing-up-a-large-class-into-tasks-passing- this-when -creating-helper-class). Обратная связь, которую я получил для передачи «этого» вспомогательным классам, чтобы иметь доступ к ее свойствам, не была положительной. – mseifert

ответ

1

Проблема с инъекцией базового класса при создании экземпляра заключается в том, что он делает все ваши классы действительно двусмысленными. Ваш класс Visitor может полагаться на класс, который анализирует суперглобальный $_SERVER, но я не могу сказать, просто посмотрев на него, это только зависимость - это весь объект приложения.

Гораздо лучше определить конкретные зависимости, которые требуется классу (обычно в конструкторе), и создать что-то, чья работа заключается в том, чтобы должным образом обеспечить эти зависимости. Это «инъекция зависимостей», на которую вы намекали, и обычно они включают в себя Container, в котором хранятся все объекты, которые были созданы, готовые к внедрению в новые классы.

Так что ваше приложение будет иметь зависимость емкости:

$app = new App(new Container); 

И тогда вы можете задать контейнер для зависимостей

class App { 

    /** 
    * @return App\Visitor 
    */ 
    public function getVisitor() 
    { 
     if (!$this->visitor) { 
      $this->visitor = $this->container->get('App\Visitor'); 
     } 

     return $this->visitor; 
    } 
} 

При использовании третьей стороной библиотеки инъекции зависимостей (рекомендуется - даже если вы начинаете с разработки своего собственного, это немного касательная), тогда библиотека обычно предоставляет способ автоматического разрешения зависимостей. Он может смотреть на конструктор на вашем классе (это правильно введенный тип, например.__construct(Visitor $visitor)) и автоматически предоставлять аргументы конструктору - с помощью Reflection SPL

Я также рекомендовал бы, если вы начинаете с ООП, что вы первый ознакомиться с PSR-4 и Composer autoloading, в том числе всех ваших классов вручную собираемся становится довольно хлопот, и в этом случае «стандартный» способ облегчает жизнь в будущем, когда вы захотите переключиться;).

Смежные вопросы