Проблема наследования классов PHP Factory

0

Я работал над своим собственным классом фабрики, который создает зависимости от зависимостей и проходит через конструкции, когда задана/запрошена зависимость. Если зависимость кэширована (уже была создана другим классом), я передаю этот экземпляр класса вместо создания экземпляра снова и снова (в основном используется для соединения 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, чтобы вместо этого создать новую пользовательскую модель для профиля пользователя. Все отлично работает, но мне все еще интересно, почему у меня была эта проблема.

  • 0
    Я не уверен, какой вопрос ты пытаешься задать. Вы можете опубликовать класс модели пользователя и добавить комментарий, где происходит это непреднамеренное изменение?
Теги:
factory

1 ответ

0

В PHP5 переменные, которые хранят объекты, не содержат самого фактического объекта, а идентификатор для ссылки на фактический объект.

Поэтому, когда вы передаете объекты вокруг, вы фактически передаете копию идентификатора объекту, который, конечно, указывает на тот же объект.

Документы PHP по объектам и ссылкам

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

<?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

Я хочу потерять несколько слов предостережения:

  • Вместо клонирования объекта вы должны убедиться, что у вас есть чистый путь потока ваших объектов. Ваш Вид не должен управлять состоянием Пользователя после его передачи.
  • Использование клона может привести к нежелательному поведению. Если кто-то передает объект одному из ваших классов и ожидает, что класс изменит состояние объектов (здесь мы не говорим о "Представлениях"), хотя это не может дать им очень трудное время для отладки.
  • 0
    Я думал, что у var есть свой экземпляр объекта, спасибо за помощь. Я не клонирую классы, я просто пропускаю их и назначаю так, как вы это делали в своем примере. Чтобы решить эту проблему, я должен передать новый экземпляр пользовательской модели в контроллер профиля? Представление не изменяет модель пользователя, оно запрашивает идентификатор пользователя, чтобы определить, вошел ли пользователь в систему, и если да, то создается меню вне холста с зарегистрированными данными пользователя. На страницах, подобных профилю, где я использую модель пользователя для определения просматриваемого профиля, данные изменяются контроллером, изменяющим идентификатор пользователя в представлении.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню