Поругайте класс

das6745

Новичок
Поругайте класс

Вот немного добавил к классу mysqli: http://freshcode.org/db.php. Мне это нужно было чтобы работать с процедурами.

Если у кого будет время посмотреть и покритиковать буду очень благодарен. Хотелось бы узнать где я не совсем верно (либо вообще неверно) решил задачи а также может кто предложит более оптимальные и красивые решения, ибо я далеко не гуру в пхп.

Хотелось написать не сильно тяжёлый класс.

Основная моя проблема в том что процедура возвращает еще и информацию о состоянии выполнения (или я неправ? я про такое где-то читал на форумах) . Толком в гугле в свое время ничего по пхп и mysql-процедурам не нашел, вот и попробовал дополнить существующий.

Первоочередной целью я ставил минимализм, так как ресурсы у мну на хостинге ограничены.

ЗЫ: про PDO я слышал но не пользовался.
 

Mols

Новичок
Ну я бы в класс ещё включил обработку аргументов процедур. mysqli_real_escape_string - для всех входящих параметров.
 

das6745

Новичок
"синглетон" тут лишний
хотелось бы чтобы инстанс Db был только один, даже не давать возможности зоздать два. Тоесть имеет смысл создать класс который и будет отдавать инстансы других классов? Будет ли это эфективно? Или просто следить за инстансами(я вообщето склоняюсь именно к этому варианту) ?

обработку аргументов процедур.
в большинстве случаев я передаю сид и айпи, а параметрами тоже в большинстве вызовов фигурируют интовые значения (айди объекта, диапазон, и т.д.). И мне кажется чтобудет не совсем разумно просто прогонять строки в которых в теории даже неможет быть.

Когда же в базу ложится, к примеру, статья она проганяется простеньким bbcode парсером(на регулярных выражениях) который также эскейпит спец. символы + переводит некоторый символы в сущности. Кстати, обратно он тоже может все преобразовать =).

В итоге, у меня лично на практике только в двух случаях используется addslshes, и то, скорее всего, из-за моей параноидальности. Вечером посмотрю еще, впринципе можно добавить флаг который будет указывать нужно ли эскэйпить входящие параметры.

Кто-то работал с процедурами/ф-циями mysql на пхп? мне пришлось использовать конструкцию
PHP:
while ($this->next_result()) {};
чтобы можно было дальше общатся с базой. Правильно ли это?
 

Mols

Новичок
Я говорю не о addslashes а о mysqli_real_escape_string. Она надёжнее и работает очень быстро. Так что даже если эскапить ИНТы - вы этого не заметите. Да и можно проверку делать... число это или нет. И эскапить если не число. Я именно так и сделал у себя (хотя это пижонство). Выигрыш очевиден на мой взгляд. Ведь вы же не думаете, что всегда и везде у вас будет необходимость работать только с ИД ? Да и вообще... сразу надо делать так, чтобы потом меньше отслеживать возможные траблы.
По поводу прохода дополнительных резалтов при работе с процедурами (при работе с функциями это не нужно) - сделал точно также. Где то я здесь писал об этом.... я предполагаю (не проверял), что второй резалт содержит (или должен содержать) OUT параметры для процедур. Так как я эти параметры не использую, собственно и не уверен... ради интереса не экспериментировал )))
 

das6745

Новичок
я читал что рутины возвращают статус о выполнении, про то что второй резалт содержит OUT интересно, сейчас проверю. А эскейпить мне прийдется тогда и уже внешне обработанные тексты, длинна которых до 65536 (типа текст), что не есть гут. наверно с помощью флага както решу.
А вы не пробовали в процедуре два селекта делать? Интересно просто, я не смог получить результаты второго и т.д.
 

Paxa

Новичок
А я в своем классе изаю функции которые я нашел в двиге друпал, наподобе printf сишного

например пишешь
$db->pqu('insert into #_table values (0, %d, %s, %f )', $input['id'], $input['text'], $microtime );

проверку на инъекции ставит сама :) и с кавычками не нужно ипаться
 

Mols

Новичок
Ну если речь идет о селектах которые должны выдать результат "на гора" то не пробовал(или пробовал и забыл )))) Ну а вообще в теле процедур можно использовать по несколько селектов. Я лично использую и по 4-5 иногда. Но возвращающий данные из процедуры - всегда один (ну если не придираться конечно к тому, что в UNION можно воткнуть сколько угодно SELECT). Остальные же запросы в теле процедуры либо вложенные, либо их результат вставляется во временную таблицу, либо в какие-то переменные которые использую в дальнейшем.
 

das6745

Новичок
нет, я говорил о мифических на-гора селектах(естественно вывод только один), я такими пользуюсь чтоб общатся с базой. удобно тем что:

1. логика базы на ней и остается
2. при замене/модификации селекта или инсерта ненужно этот самый селект править в скрипте.
3. вроде как быстрее процедуры отрабатывают, да и немногим меньше данных идет при обращении к базе рутинами (проще же сказать call test() чем select и порядочно стэйтментов всяких)

+ мне нравится что по большому счету база живет своей жизнью а скрипт - своей, так сказать MVC =)
-----------

а вот и результаты моих экспериментов

SQL:
PHP:
CREATE
PROCEDURE test_1()
select 1;

CREATE
PROCEDURE test_2(INOUT a INT)
    select a+1 into a;

delimiter //

CREATE
PROCEDURE test_3()
BEGIN
    select 1;
    select 2;
END//

delimiter ;
PHP:

PHP:
echo '<pre>';
// $k = new Kernel();
$db = new Db();

#test_1
$db->multi_query('call test_1()');
$a = $db->store_result();   #we need save result to process it
while ($db->next_result()) {};             #use it to clear buffer, without it we'll get...
// $a = $db->multi_query('call test_1()'); #2014 : Commands out of sync; you can't run this command now
// $a->free();              #it doesn't work here, no sense
$a = $a->fetch_array();
var_dump($a);

while ($db->next_result()) {};  #clear buffer

# test_2, here we don't need to clear buff =)
$db->multi_query('set @a=1');
$db->multi_query('call test_2(@a)');
$db->multi_query('call test_2(@a)');
$db->multi_query('call test_2(@a)');
$db->multi_query('call test_2(@a)');
$db->multi_query('select @a');
$a = $db->store_result();
$a = $a->fetch_array();
var_dump($a);

# test_3
$db->multi_query('call test_3()');
$a = $db->store_result();
$a = $a->fetch_array();
var_dump($a);
while ($db->next_result()) {};  #clear buffer or not???

$db->multi_query('call test_3()'); #2014 : Commands out of sync; you can't run this command now
-----
Mols был прав, второй резалт под возвращемое значение идет, вот только его мы не получаем. или это только я незнаю как получть? в общем, не совсем логичное поведение

еще менее логичное поведение в 3м примере, мы получаем только 1й селект и все. дальше я незнаю как получить результаты. мало того, я немогу обработать полученые результаты, о чем нам мило говорит мускуль своей ошибкой.
после такого вызова разве что реконект поможет, по крайней мере мне помогает. но всеже я не смог сделать перед закрытим ровнм счетом ничего, а вообще бы желательно коммит сделать.

может кто сталкивался с подобным и знает что я неправильно делал?

и это все на kubuntu с последними апдетами
das6745@lhome:~$ mysql --version
mysql Ver 14.12 Distrib 5.0.38, for pc-linux-gnu (i486) using readline 5.2
das6745@lhome:~$ php -v
PHP 5.2.1 (cli) (built: Jul 17 2007 18:14:23)
Copyright (c) 1997-2007 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies
das6745@lhome:~$ apache2 -v
Server version: Apache/2.2.3
Server built: Aug 16 2007 22:49:04
das6745@lhome:~$ uname -a
Linux lhome 2.6.20-15-generic #2 SMP Sun Apr 15 07:36:31 UTC 2007 i686 GNU/Linux

на других машинах на 5х пхп и 5х мускулах тоже самое. да, и я тестил только на линуксе и фряхе, если кто скажет как это все работает на M$ буду благодарен.
 

Pigmeich

Новичок
Вопрос: зачем вам нужен сингелтон, если есть persistent connection?

Тем более, что инстанс будет один только в пределах скрипта. Которые небольшие и заметно меньше тех сишных пределов в которых выдумали использовать сингелтон.
 

zerkms

TDD infected
Команда форума
Pigmeich
синглтон и персистент соединение - немножко (точнее даже - очень сильно ;) ) разные вещи
 

Pigmeich

Новичок
zerkms
Э-э, сингелтон испульзуется в данном коде, чтобы сделать то, что делается persistent connection, как я понял.

Про то что разные, как бы знаю. GoF читал, можете с этой ссылкой не приставать.
 

jonjonson

Охренеть
Pigmeich, я использую синглетон только, например, потому, что не знаю кода мне понадобиться доступ к БД. А делать тупо соединение с БД в начале каждого скрипта инклудом одного и того же кода мне принцип DRY мешает. Пусть соединение само создаётся, когда оно понадобилось.
 

das6745

Новичок
Pigmeich
Вопрос: зачем вам нужен сингелтон, если есть persistent connection?
это абсолютно разные вещи. вы наверное не до конца понимаете механизм синглтонов а также неучитываете что persistent connection за частую разрывается по окончании выполнения скрипта (читал гдето что это проблемма апача и такое поведение не есть гуд) либо если php подключен как CGI, это раз. Во-вторых, вы про проблемму блокировок слышали?

Э-э, сингелтон испульзуется в данном коде, чтобы сделать то, что делается persistent connection, как я понял.
Нет. синглтон используется(точнее использовался) потому что он абсолютно ненужен=). убрал. позже обновлю скрипт.

инстанс будет один
как правило да, но не факт, в общем, применение синглтона было тупостью
 

Pigmeich

Новичок
jonjonson
А причём тут сингелтон? Ну коннектся когда тебя надо, зачем контроль инстансов?

das6745
Э-э... Я понимаю, что это разные вещи. Но используются они для достижения одного результата - минимум затрат на коннект и не допущение множественных коннектов.
И где я писал, что это одно и то же?

а также неучитываете что persistent connection за частую разрывается по окончании выполнения скрипта (читал гдето что это проблемма апача и такое поведение не есть гуд) либо если php подключен как CGI, это раз. Во-вторых, вы про проблемму блокировок слышали?
Сингелтон тоже больше скрипта жить не будет никогда. Проблемма с сохранением есть - это тоже ясно, но сингелтон разве сохраняет? По-моим скромным знаниям двух книжек GoF'а он только единственность инстанса и достпуность его для всех контролировать должен.

Про блокировки слышал. Даже видел. Давайте сюда эту развесёлую статью середины 90-х про фиговый сингелтон. Или про что это высказывание было?

Нет. синглтон используется(точнее использовался) потому что он абсолютно ненужен=). убрал. позже обновлю скрипт.
ну и правильно ;).

как правило да, но не факт, в общем, применение синглтона было тупостью
Если не один - это не сингелтон! Он же глобальный объект эмулировать должен.
 

das6745

Новичок
не, я сначала синглтон пихнул для того чтоб в других классах сказать что-то вроде база::дай_указатель_на_класс, в общем это было _абсолютно_ неверно, абсурдно. спасибо что ткнули носом. думаю не стоИт дальше это обсуждать.

Что касается постоянного соединения так этого я не старался добится (да и синглтоном в теории невозможно)

не допущение множественных коннектов.
...в пределах рантайма скрипта, но, опять же, мне может понадобится еще один коннект, верно? вооот, значит вечером обновлю, я там еще некоторые изменения сделал мелкие.

Paxa, не, мне такая идея принтфа в дб както не сильно нравится, разбор входящих параметров в ф-цию как был так и остался, а вот, мне кажется, на производительности это скажется (и вообще, я немного двинут на "производительности", надеюсь это лечится). единственная выгода - это читабельность кода... и то выигрыша я не вижу. лучше реализовать проверку и экранирование в зависимости от типа входных данных, хотя как было выше сказано, ф-ция ля-ля-ля_real_escape довольно шустрая и если эскейпить все входные параметры большого зла небудет

(все сказанное ИМХО)
и хотелось бы услышать мнение гуру по поводу всего того бреда что тут написали =)


обновил, http://freshcode.org/db.php, вроде как работает. странно. =). как насчет изобилия передачи и возврата аргументов по ссылке, а также в присваиваниях? я только теорию читал по ссылочности и смотрел бенчмарки, сам же не тестил, поэтому тоже хотел бы услышать мнения по поводу приминения ссылок, спасибо.

ps. принтф в дб я всетаки написал, прикольная штука =). но она, я так понимаю, помогает всего лишь с преобразованием типов, не более. не думаю что принтф нужен для вызова процедур, хотя кто его знает ;)
 

jonjonson

Охренеть
Автор оригинала: Pigmeich
jonjonson
А причём тут сингелтон? Ну коннектся когда тебя надо, зачем контроль инстансов?
При том, что я не задумываюсь о коннекте. Он выполняется один раз сам. Именно благодаря синглетону.
 
Сверху