#php #oop #session #get #set
#php #ооп #сессия #получить #установить
Вопрос:
Я привык к java, objective c и немного к c . Теперь я хочу использовать PHP для создания веб-сайта. Я создал несколько классов, но для простоты: 3 класса.
Учетная запись — DataMapper — DataManager
Это означает, что я могу получить учетную запись из базы данных. В DataManager я отслеживаю все вещи. Например, идентификатор пользователя.
Дело в том, что обычно все заданные переменные остаются «установленными», но теперь, когда я использую php, мне, по-видимому, нужно сохранить их с помощью сеанса. DataManager:
<? php
class DataManager
{
// Hold an instance of the class
private static $dm;
private $dataMapper;
private $dictationView;
private $userId;
private function __construct()
{
$this->dataMapper = new DataMapper();
$this->dictationView = new DictationView();
}
// The singleton method
public static function singleton()
{
if (!isset(self::$dm)) {
$c = __CLASS__;
self::$dm = new $c;
}
return self::$dm;
}
// Prevent users to clone the instance
public function __clone()
{
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
function __get($prop) {
return $this->$prop;
}
function __set($prop, $val) {
$this->$prop = $val;
}
}
?>
Если я установлю идентификатор пользователя в классе singleton DataManager, в следующий раз, когда я
вызовите экземпляр класса DataManager, он не запомнит идентификатор пользователя. Где-то я должен иметь дело с сессией, я думаю. Как правильно использовать сеансы ООП в DataManager? Спасибо!
Комментарии:
1. Когда вы говорите «в следующий раз», вы имеете в виду в том же запросе или в последующем? Помните, PHP, по сути, такой же апатридный, как HTTP. Кроме того, используйте
self::$dm = new self;
вместо$c = __CLASS__; self::$dm = new $c;
2. @Phil Brown PHP не является апатридом, каждый язык будет апатридом между запросами в серверно-клиентской архитектуре, которая обрабатывает каждый запрос в другом процессе. PHP может иметь состояние, как и любой другой язык.
3. @Itay Я имел в виду, что в PHP нет контейнера, подобного Tomcat. Вы, конечно, можете поддерживать состояние, используя сеансы и другое внешнее хранилище, но если вы переходите с Java, эти вещи могут быть неочевидны.
Ответ №1:
При желании вы можете создать оболочку для сеансов на PHP. На самом деле это могло бы быть полезно, особенно если вашему приложению позже пришлось бы мигрировать на кластер серверов, а сеансы были бы перемещены в распределенный кэш. Затем, чтобы облегчить эту миграцию, вам нужно будет только предоставить другую реализацию, если тот же Session
интерфейс класса.
Тем не менее.
Этот код сам по себе не является хорошей ООП. Вам следует прекратить использовать синглтоны. И, если вашему классу требуются экземпляры DataMapper
и DictationView
, то они должны быть созданы вне класса и предоставлены в конструкторе. Вместо создания тесной связи, потому что ваш конструктор создает другие объекты.
Ответ №2:
Теперь то, на что вы ссылаетесь, — это не PHP, а скорее то, как обрабатывается архитектура клиент-сервер.
Вот изменение, которое предполагает, что вы правильно управляете сеансом (что касается session_start — должно быть в начальной загрузке вашего файла) Я также добавил некоторые исправления в ваш код, которые помогут вам в будущем:
private function __construct()
{
$this->dataMapper = new DataMapper();
$this->dictationView = new DictationView();
}
// The singleton method
public static function singleton()
{
if(isset($_SESSION[self::MY_UNIQUE_IDENTIFIER] amp;amp;
get_class($_SESSION[self::MY_UNIQUE_IDENTIFIER] == 'DataManager'){
self::$dm = $_SESSION[self::MY_UNIQUE_IDENTIFIER];
}
if (!self::$dm) {//LOOK HERE LOOK HERE!!!!!!!!!!!!!!!!!!!!
$_SESSION[self::MY_UNIQUE_IDENTIFIER] = self::$dm = new self;
}
return self::$dm;
}
// Prevent users to clone the instance
public function __clone()
{
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
function __get($prop) {
return $this->$prop;
}
function __set($prop, $val) {
$this->$prop = $val;
}
}
//LOOK HERE LOOK HERE no closing ?>
Некоторые ловушки, которые я здесь не рассматривал, поскольку они не являются предметом этого вопроса:
- Правильный способ управления сеансами
- Корректировка класса, позволяющая наследование без разрушения сеанса
Комментарии:
1. Большое спасибо, но, может быть, лучше всего избавиться от одноэлементного класса? Должен ли я просто хранить свои сеансы в __get и __set класса
2. @Oritm это сделает его оболочкой сеанса. Это не обязательно должен быть синглтон, и хотя многие люди против этого, всегда есть тихое большинство, которое все еще использует его без каких-либо проблем.