Я работал над собственным классом фабрики, который создает экземпляры зависимостей и проходит через конструкции, когда зависимость установлена / запрошена. Если зависимость кэшируется (уже был создан другим классом), я передаю этот экземпляр класса вместо того, чтобы создавать его заново (в основном используется для соединения с БД). Проблема, с которой я столкнулся на данный момент, заключается в следующем.
** Чтобы избежать большого вопроса & сэкономить время на чтение Я пытаюсь проиллюстрировать проблему как можно проще, если нужен реальный код, который я могу вставить.
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
Модель пользователя. Я не использую статические переменные, поэтому я не понимаю, почему изменения сделаны в 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
Крайне важно понять, что и View, и Controller ссылаются на один и тот же объект, поэтому манипулирование объектом в одном классе приведет также к манипулированию им в другом классе (технически это неверно, поскольку оба указывают только на один и тот же объект) ,
Теперь давайте используем ключевое слово clone в представлении:
public function __construct( User $user )
{
$this->user = clone $user;
}
Теперь $user
Свойство представления будет содержать «указатель» на копию объекта пользователя. Изменения, внесенные в этот объект, не влияют на исходный объект, который был передан.
Таким образом, результат будет: JeffreyThomas
Я хочу потерять несколько слов предостережения:
Других решений пока нет …