Я работал над своим собственным классом фабрики, который создает зависимости от зависимостей и проходит через конструкции, когда задана/запрошена зависимость. Если зависимость кэширована (уже была создана другим классом), я передаю этот экземпляр класса вместо создания экземпляра снова и снова (в основном используется для соединения db). Вопрос, который у меня сейчас есть, заключается в следующем.
** Чтобы избежать большого вопроса и сохранить время чтения, я пытаюсь как можно проще проиллюстрировать проблему, если необходим реальный код, я могу вставить его.
Class View {
// Construct Requests User Model
}
Class Controller {
// Construct Requests User Model & Class View
$this->user->set($newuserid);
$this->view->display('file');
}
Таким образом, экземпляр Controller
создается, поскольку View
задается как созданные им зависимости и передается Controller
через __construct
. Все в порядке, но для таких вещей, как страница профиля. Где я установил новый пользователь (проиллюстрированную выше) устанавливающее новый идентификатор пользователя и изменяет идентификатор пользователя, который содержится в View
User Model. Я не использую статические vars, поэтому я смущен тем, почему изменения, сделанные в controller
влияют на модель пользователя view
. Это вызывает проблему для меня, потому что зарегистрированный идентификатор пользователя устанавливается через точку входа сайта (бутстрап) и ошибки возникают, когда страница профиля перезаписывает зарегистрированный идентификатор пользователей. Я добавил на свой завод параметр newInstance
, чтобы вместо этого создать новую пользовательскую модель для профиля пользователя. Все отлично работает, но мне все еще интересно, почему у меня была эта проблема.
В PHP5 переменные, которые хранят объекты, не содержат самого фактического объекта, а идентификатор для ссылки на фактический объект.
Поэтому, когда вы передаете объекты вокруг, вы фактически передаете копию идентификатора объекту, который, конечно, указывает на тот же объект.
Поэтому, когда вы используете один и тот же пользовательский объект как в своем контроллере, так и в вашем представлении и управляете им, фактический Пользовательский объект будет изменен. Поскольку обе переменные объекта по-прежнему содержат один и тот же идентификатор объекта, состояние объектов будет таким же, как в вашем контроллере, так и в вашем представлении.
<?php
class User {
protected $name;
public function __construct($name)
{
$this->setName($name);
}
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
}
class View {
protected $user;
public function __construct( User $user )
{
$this->user = $user;
}
public function render()
{
echo $this->user->getName();
$this->user->setName('Tony');
}
}
class Controller {
protected $user;
protected $view;
public function __construct( User $user, View $view )
{
$this->user = $user;
$this->view = $view;
}
public function someAction()
{
$this->user->setName('Thomas');
$this->view->render();
echo $this->user->getName();
}
}
$user = new User('Jeffrey');
$view = new View($user);
$controller = new Controller($user, $view);
$controller->someAction(); // Output: ThomasTony
Существенным для понимания является то, что оба: вид и контроллер ссылаются на один и тот же объект, поэтому манипулирование объектом в одном классе приведет к тому, что он будет манипулировать им в другом классе (технически это неправильно, потому что оба указывают на один и тот же объект),
Теперь позвольте использовать ключевое слово clone в представлении:
public function __construct( User $user )
{
$this->user = clone $user;
}
Теперь $user
свойство представления будет содержать "указатель" на копию пользовательского объекта. Изменения, внесенные в этот объект, не будут влиять на исходный объект, который был передан.
Таким образом, выход будет: JeffreyThomas
Я хочу потерять несколько слов предостережения: