:blush: Представим класс: PHP: <?php class Database { ... public function query($query, $arguments) { .... } public function getArray($query, $arguments) { $result = $this->query($query, $arguments); while... .... } } Таким образом - сколько вариантов возвращения данных (методов для этого), столько раз нужно прописывать методы с аргументами (чтобы обращаться $db->getArray('SELECT ?s..', 'row'), в теле методов обращение к методу query. Получается много копипастного кода. В начале года я написал класс, где избежал дублирования: PHP: <?php class Database { ... public function query($method, $query, $arguments) { .... $this->resourse = mysql_query($sql); $this->$method(); } public function getArray() { while ($this->resourse)... .... } } Таким образом, я всегда обращаюсь к одному методу, а в качестве аргумента указываю метод, который будет возвращать необходимую структуру. Но сейчас мне такой вариант не нравится - нужно указывать на один аргумент больше. Хочется, чтобы вместо query указывалось имя необходимого метода (пример - $db->getArray). Как вариант - использовать перегрузку методов. Но здесь у меня сомнения: 1) Верно ли это идеологически, 2) верно ли это с точки зрения быстродействия, 3) какой вариант реализации выбрать? По поводу реализации: 1. Вариант: PHP: <?php class Database { private $methods = Array ("getArray" => false); private $m_data = Array ("getArray" => "gA"); ... public function query($query, $arguments) { .... $this->resourse = mysql_query($sql); $this->$method(); } function __call($method, $arguments) { if (isset($this->methods[$method])) { $this->query($arguments[0], $arguments[1]); return $this->m_data[$method](); } return false; } public function gA() { while ($this->resourse)... .... } } 2. Вариант с помощью наследования: PHP: <?php class Database extends mainDB{ private $methods = Array ("getArray" => false); ... public function query($query, $arguments) { .... $this->resourse = mysql_query($sql); $this->$method(); } function __call($method, $arguments) { if (isset($this->methods[$method])) { $this->query($arguments[0], $arguments[1]); return parent::$method(); } return false; } class mainDB { public function getArray() { while ($this->resourse)... .... } } Склоняюсь к 1 варианту. Что скажете?
вот те делать нечего =)) хватит писать велосипеды, займись полезным делом, хотя бы С++ поизучай вместе с Mr.M.I.T., чем ваять over-ООП велосипедные классы
Сейчас для С++ нет времени. Нужно сделать лучше то, что есть. Да и на ООП нормально программить научитсяю
Какашка. Смысла в таком функционале 0. Ты всегда получаешь в запросе строки и столбцы. Поэтому можешь смело его парсить сразу в ArrayAssoc. А объект результата уже должен подерживать методы своей сериализации в разные виды. PHP: <?php $db->query($queryString, $queryArguments); $result = $db->getLastResult(); $result->toArray(); $result->toArrayAssoc(); $result->toString(); $result->toJSON(); $result->toXML(); ?> Все. Твоя задача вернуть объект класса QueryResult, который является наследником Result и имплементирует абстрактные (или не очень) методы toArray() и т.д. Можно еще добавить интерфейс ArrayAccess для доступа к данным напрямую, тогда убрать первые два конвертера из моего примера.
Можешь кстати, наследоваться от http://www.php.net/manual/en/class.splobjectstorage.php где-то я читал что он на 20% быстрее, чем работа с массивом объектов. хотя надо бы проверить, но лень.
Много строк чего? можешь писать так PHP: <?php $result = $db->query($queryString, $queryArguments)->getLastResult()->toArray(); ?> Ты надеешься избежать лишних нажатий клавиш при наборе? Так я тебе скажу, тут их минимум втрое меньше, чем символов в строке, если ты конечно пользуешься нормальной IDE Зато когда мне понадобится добавить метод toJSON() я буду менять 1 класс Result в 1ном месте. А ты будешь менять код в 2х-3х местах, да еще, возможно, и в разных классах. Опять же, контроль параметров у тебя нулевой. PHP: <?php $db = new Database(); $db->getArray("Ждал 2 аргумента? Получи фашист гранату"); ?>
чё за проблемы? 1. Сделать много методов, (queryArray,queryResource ...) 2. Возвращай в query $this потом $db->query()->getArray() советую 1й Simpliest по кой чёрт разбивать реализацию на такое кол-во объектов?
На тот черт зачем вообще ООП 1.Потому что первый способ ТС - это идиотизм. Вызов методов через _call() при их фактическом объявлении. Второй способ ничем не лучше. 2. Хотим мы результаты БД сконвертировать в JSON и пишем метод getJSON? Да? А если мы хотим данные SOAP сконвертировать в JSON, ему тоже пишем getJSON? А если мы еще откуда-то получим данные, то мы еще один getJSON пишем? Множественного наследования в PHP нет, да и само оно (множественное наследование) не слишком удобно для многих вещей. Интерфейсы не поддерживают конкретную реализацию по определению. В моем примере выше мы отделили данные от способа их получения путем наследования от общего объекта Result (SplObjectStorage). Можно это было сделать через Dependency injection - создав класс(группу классов) конвертеров и подключая нужные к нашей модели PHP: <?php class DB { public function __construct() { foreach(func_get_args() as $arg) { if ($arg instanceof Converter) { $this->converters[] = $arg; } elseif ($arg instanceof Connection) { $this->connection = $arg; } } } } class Connection { private $name = 'Default'; public function __construct($name) { $this->name = $name; } } class Converter { private $name = 'Default'; public function __construct($name) { $this->name = $name; } } $db = new DB (new Connection('MySQL'), new Converter('JSON'), new Converter('XML'), new Converter('String')); var_dump($db); ?>
На самом деле пример был утрирован для демонстрации особенностей DI. Тебе достаточно было передать не десяток конвертеров, а один транспортный объект. Который уже в свою очередь может быть нашпигован конвертарами по DI или просто унаследован от абстрактного класса. При этом мы сохраняем и возможости typehinting в IDE и lowcoupling для кода. Вообще обычные массивы в php весьма удобны для передачи данных любого типа, но есть риск нарушения целостности структуры, проконтролировать которую у массива сложнее чем у класса P.S. Интересен Phemto, но все никак не было времени разобраться как он собирает классы. В частности автодополнение в IDE весьма проблематично, если он не компилирует в нативный PHP-код, а собирает их в runtime. А это только усложнит разработку
PHP: <?php $conf = new Zend_Config_Ini(APPLICATION_PATH.'/configs/application.ini', APPLICATION_ENV); $db = Zend_Db::factory($conf->db->adapter, $conf->db->toArray()); echo Zend_Json::encode($db->fetchAll('SELECT * from articles where id=?', $id));
В том и вопрос. Если решать задачу "влоб", то получим десятки несвязанных классов со своими методами getJSON(). Вдруг, внезапно, формат JSON забанили Переписывать все классы? Или может лучше 1?
класс БД не должен решать эту задачу, в том формате в котором его попросили и что значит забанили "JSON" банить функция приложения а не фреймвока
Вот видишь А теперь почитай, что рекомендовали сделать Во всех маршрутизаторах всемирной сети данные в формате JSON режутся и фильтруются аппаратно
боже, да я говорил про то что ты всё усложняешь вернуть объект, который наследник бла бла, потом бла бла будет там чёто с ним делать жопа всё это
У тебя следующие проблемы 1. Дерево классов может иметь несколько предков и не пересекаться Соответствено реализаций классов с JSON должно быть много - что неудобно. 2. Вытекает из п.1 - сделать общего предка у всех классов (какой нибудь - CommonObject). Можно, но тоже несколько неудобно. Мы будем тащить методы даже туда, где они не нужны... Поэтому на мой взгляд есть два разумных варианта. 1. Классы утилит как показал Frozen (он вообще 1 на все дерево) 2. Транспортный класс данных, датамапперы. Которые имеют общего предка и могут поддерживать конвертацию своего представления в JSON/XML/String etc. (таких классов будет 1-2)