[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Как копировать объекты? =)
Страницы: 1, 2, 3
Arh
Много букаф.

Проблема №1:
Есть допустим синглтон pdo, который возвращает готовый объект.
$db = db::connect();


Допустим на странице запускается несколько сервисов подряд, которые используют $db.
По умолчанию стоит настройка PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
Но какому то сервису, который запускается раньше остальных допустим захотелось сделать так:
$db = db::connect();
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);

Так как при копировании объекта, копируется не сам объект а типа ссылка на него, то все сервисы, которые использую $db = db::connect() рухнут, потому что думают что настройка стоит PDO::FETCH_ASSOC.
(под словом "рухнут" я имею ввиду любые баги)

Не делать же постоянно new pdo что бы избежать всяких неизвестных багов. Может надо както по другому подключение организовывать? clone то не работает.

Проблема №2:
Захотел я делать инъекции, начитался про DI, начал экспериментировать.
Пришел к выводу что не хочу каждый раз передавать в конструктор какие то зависимости, хочу передавать тогда, когда мне нужно что то подменить.
Что бы конструктор смотрел, если я что то ему пытаюсь подсунуть, то он это использует, иначе использует то, что ему нравится.
Передавать кучей аргументов не вариант, вдруг мне нужно поменять третий аргумент, а первые два не трогать, да и вообще каша получится.
Решил передавать массивом, если ключ существует, значит используем, иначе на усмотрение конструктора.
Но. Делать что то вроде:

$this->db = isset($di['db']) ? $di['db'] : new db();
$this->tpl = isset($di['tpl']) ? $di['tpl'] : new tpl();
//и так каждую зависимость

Тоже не вариант.
Во первых лень, во вторых по умолчанию будет постоянно new или в лучшем случае getInstance.
Решил передавать не массив, с ключами, а объект со свойствами.
Написал класс со всякой магией типа __call,__get,__set, что бы свойство создалось само, если его нет (в смысле если нет инъекции или точнее её подмены)
В конструкторе получилось типа того:

//это конструктор
$di = $di ? $di : new di();
$this->db = $di->db();
$this->tpl = $di->tpl();


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


//это в контроллере
$di = new di();
$di->tpl = new smarty();
$my_class = new my_class($di);


Вроде уже почти, класс di создаёт объекты или возвращает уже созданные, но опять будет куча new, так как я не хочу делать инъекции каждый раз, соответственно будут запускаться магические методы, которые делают new.
Решил всё это дело закэшировать.
Создал статическое свойство, которые хранит объекты. Сделал так, что бы туда сохранялись объекты, которые создаются с помощью __call и __get, а те, которые прописываются свойствами ($di->tpl = new smarty();) что бы так и оставались локальными свойствами.
Вроде хорошо, тесты в цикле показали бешеный прирос в скорости по сравнению с постоянным new.

Начал дальше всё это тестировать.
Понадобилось получать объект через di, но при этом в него тоже передавать зависимости.
function __construct ($di = '') {

$di = $di ? $di : new di();
$this->db = $di->db();
$this->config = $di->config($di); //допустим так

}


В итоге объект $config возвращался без зависимостей, потому что был вызван где то раньше вот так
$this->config = $di->config();
, после чего он сохранился в кэш и теперь достаётся от туда.
Решил я кэши объектов сохранять не по имени, а по имени и хэшу аргументов.
Cделал md5(serialize($args)) и всё вроде заработало, при очередном тесте.
А потом перестало работать при другом тесте. Дело в том, что в аргументом передаётся $di в котором есть $db (pdo), а pdo не разрешает себя сериализовать.
Ну ладно, вместо md5(serialize($args)) использовал md5(var_export($args, true)) и всё заработало.

А теперь возвращаемся к проблеме номер 1, потому что это всё одна и та же проблема.
Какой то сервис, который запускается раньше остальных, решил сделать так:
или как выше на примере базы данных

$di = new di();
$tpl = $di->tpl();
$tpl->path = 'templates_test/';


А потом другой сервис будет делать так:

$di = new di();
$tpl = $di->tpl();
$tpl->display('index.tpl'); //подразумевая что корневой каталог templates/

И всё рухнет потому что объекты не копируются, а копируется ссылка на них или как там правильно выразится.
Клонировать средствами $di не получится, так как может попасться объект типа pdo.
Делать всегда new неохота и накладно.

Не знаю, может зря я на ночь глядя это затеял, может не туда смотрю. Кто дочитал, тот молодец :lol:

_____________
Промокод предоставляет скидку на заказ домена и/или хостинга reg.ru
BFCC-3895-8804-9ED2
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.