PHP: сделать объект доступным для нескольких функций - PullRequest
1 голос
/ 23 февраля 2012

Вопрос новичка: я не знаю, как лучше структурировать этот бит кода, но в основном это выглядит так (время псевдокода):

 if (form = submitted) {
     submitted();
 }
 else {
     printForm();
 }

 function submitted() {
     process data from form;
     if(errors = found) {
         print warnings;
         printForm();
     } else {
         submit to database;
     }
 }

 function printForm() {
     print form with databound elements;
 }

Я использую следующий бит кода длясоздайте объект User, но кажется странным вызывать его дважды - один раз в submitted() и один раз в printForm(), тем более что submitted() вызывает printForm() в случае обнаружения ошибок.

К сожалению, доступ к базе данных необходим для обработки данных из формы (проверка на существующий адрес электронной почты и т. Д.), Поэтому мне нужно вызвать следующий бит кода как в submitted(), так и в printForm() ...

try {
    $db = new Database();
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);  
    $user = new User($db);
}
catch (PDOException $e) {
    echo "<p>Error connecting to database: </p>".$e->getMessage();
}    

Но мои инстинкты говорят мне, что это плохо.Это?Если да, то как мне это исправить?

Ответы [ 3 ]

3 голосов
/ 23 февраля 2012

Использовать внедрение зависимостей :

function submitted(Database $db, User $user) {
    // ...
}

function printForm(Database $db, User $user) {
    // ...
}

try {
    $db = new Database();
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);  
    $user = new User($db);
}
catch (PDOException $e) {
    echo "<p>Error connecting to database: </p>".$e->getMessage();
}

submitted($db, $user);
printForm($db, $user);

Конечно, лучше использовать ООП, так как тогда вам не придется вводить зависимости в каждую отдельную функцию:

class Foo {
    protected $db;
    protected $user;

    public function __construct(Database $db, User $user) {
        $this->db = $db;
        $this->user = $user;
    }

    public function submitted() {
        // use $this->db and $this->user here
    }

    public function printForm() {
        // use $this->db and $this->user here
    }
}

try {
    $db = new Database();
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);  
    $user = new User($db);
    $foo = new Foo($db, $user);
}
catch (PDOException $e) {
    echo "<p>Error connecting to database: </p>".$e->getMessage();
}

$foo->submitted();
$foo->printForm();
2 голосов
/ 23 февраля 2012

Есть несколько способов сделать это лучше ...

Можно было бы инициализировать $ user перед вызовом функции и внедрить его в каждую функцию (внедрение зависимостей).

Другой способбыло бы сделать единичный экземпляр пользовательского экземпляра (хотя я мог видеть, что это приводит к проблемам в будущем) и извлечь экземпляр в функции, используя что-то вроде User::instance().

Внедрение зависимости лучше, на мой взглядпотому что это облегчает тестирование ваших функций.


Теперь перейдем к остальной части кода:

  1. Обычно не рекомендуется выводить что-либо внутри функции или классаметод.Вместо этого вы должны возвращать данные и обрабатывать их вне функции.
  2. Ваше создание экземпляра базы данных, вероятно, должно идти в файле начальной загрузки, который включен в начало каждого скрипта.Также, вероятно, будет лучше, если ваш скрипт корректно обрабатывает ошибку соединения (сообщите пользователю, что что-то пошло не так, отправьте себе электронное письмо, остановите выполнение остального скрипта), если соединение не будет установлено, а не просто отобразит сообщение об ошибке.*
0 голосов
/ 23 февраля 2012

Хотя шаблон Singleton считается в некоторых случаях злым, кажется, что в PHP (с отдельным рабочим процессом для каждого запроса) и в вашем случае это самый простой способ реализовать то, что вы хочу.

Таким образом, у вас есть экземпляр User, который инициировал запрос, доступный в любом сценарии на любой странице, и вам нужно инициализировать объект $user только в одном месте для проекта (не в одном для сценария, как вы желая сделать).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...