Эта тема на forum.dklab.ru


Чебурген:
Мне кажется, что в комментариях к этой функции надо обязательно указать, что параметры, приходящие от пользователя, перед помещением в массив аргументов должны проходить проверку на magic_quotes_gpc, и соответственно, очистку от слешей, если они были добавлены автоматом. Иначе слеши удвоятся, что будет нехорошо.
_sultan_: Ваша визитка - г (c)
Все ваши placeholder'ы - .
Код примитивный, и громоздкий.
Если уж вы претендуете на то, чтобы Ромик зачесался в районе бороды, при виде вашего кода, надо было бы попроще написать :) ;)
Все это можно было бы в несколько строчек вместить!
И работало бы пошустрее и было бы пофункциональнее...

Насчет magic_quotes_gpc:
В самих функциях ниче не стрипается. Да оно там и не надо!
За это должен отвечать не плейсхолдер а другая функция, для получения переменных из супер-глобальных массивов ...
почему ?
да потому что в более-менее сожных скриптах данные из $_GET (и иже с ним) используются НЕ ТОЛЬКО в плейсхолдере, но и в других местах. например при работе с файлами.
Поэтому получение этих переменных дожно быть вынесено в отдельную функцию, например:
mixed getrequestvar(string name, string source='_REQUEST') {
$value = isset($$source[$name]) ? $$source[$name] : NULL;
return magic_quotes_gpc()&&is_string($value) ? stripslashes($value) : $value;
}

пример использования:
$sql = sql_placeholder('SELECT * FROM ^table WHERE id=?n OR name=?s', "77 this string will be converted to 77", $name);
$sql = sql_placeholder('UPDATE ^table SET blob_field = ?b WHERE name=?s', file_get_contents('1.rar'), '1.rar');
$sql = sql_placeholder('INSERT INTO ^table(int_field, char_field, float_field) VALUES(?n,?s,?f)', "3133", "it is a string", "3.14 : yeah this string will be converted to 3.14");

$ids_to_delete = array(1,10,4,100,63,100,52);
$sql = sql_placeholder('DELETE FROM ^table WHERE id IN (?w)', implode(',', $ids_to_delete));
^ - префикс таблицы.

<?php
define('DB_PREFIX', 'db_prefix_'); // префикс для таблиц

function sql_placeholder()
{
$GLOBALS['__args'] = func_get_args();
return preg_replace_callback('!(?:\?[nswbf]{1}|\^)!', 'sql_calback', array_shift($GLOBALS['__args']));
}

function sql_callback($m)
{
if (!sizeof($GLOBALS['__args'])) return "''"; // список параметров исчерпался - вставляем ''
$value = array_shift($GLOBALS['__args']); // текущий аргумент
switch($m[0]) {
case '?n': return intval($value); // for integer fields
case '?s': return "'".addslashes($value)."'"; // (var)?char fields
case '?w': return $value; // insert AS IS
case '?b': return '0x'.bin2hex($value); // to BLOB fields
case '?f': return floatval(str_replace(',','.',$value)); // to float fields
case '^': return DB_PREFIX; // prefix for tables
}
}
?>

Дмитрий Котеров:
Код примитивный, и громоздкий.
Ну, вообще-то, размер всего на 3 строчки больше, чем у Вас. Но там же 2 функции в реальности определяются - одна для формирования строки, а другая - для запуска SQL-команды сразу. И плюс не используются регулярные выражения.

Честно говоря, наличие спецификаторов после ? лично мне кажется бесполезным, потому что MySQL и так прекрасно все значения переводит в соответствующие типы, а безопасность это не увеличивает ровным счетом нисколько. (Кстати, ?w - это вообще супер. За что боролись, на то и напоролись. :-)

Впрочем, Ваш вариант, конечно, тоже имеет право на существование, если его немножко поуниверсальнее переписать (например, добавить что-то типа ?a для массива значений).
_sultan_: (+)
ну во первых с чего вы взяли что метод с рег. выражениями будет тормозить ???
Шаблон апроса проходит через рэгэксп только 1 раз - и он однопроходной когда как у вас есть как минимум 2 str_replace'а ;) не считая sprintf'a - он тоже проходит 1 раз по строке запроса.
разницу можно было бы почуствовать только на _Больших_Запросах_(>5K) если запускать по 5К раз и смотреть таймер, и то еще спорный вопрос что окажется быстрее:), но какой <censored> будет генерить и выполнять по 5К раз такие огромные запросы? :) 100% мускул упадет ;)
это раз.

насчет спецификаторов: а) вы так думаете ? попробуйте на досуге написать db filesystem и вставку 2М файла в кавычках еще и проэкранировав там слеши :lol:
б) ну спецификаторы больше нужны не для mysql, а для программиста: чтобы он по запарке не поменял бы местами аргументы :)
в) насчет строчек: switch можно считать вообще за 2 строчки, потому что зачастую идут операции со строками и числами, реже другими типами ;), поскольку switch не что иное как комплект if(){} elseif(){} elseif(){}.....

знаете в чем принципиальное отличие наших методов?
вы вашем методе str_replace'ами "подстраиваетесь" под sprintf(), и вынуждены оперировать только ими (%d, %s, %%)
когда как в моем методе: программист волен сам решать что и как делать: использовать текущие или добавить новые спецификаторы - вы сами верно подметили - добавить
case '?a': return implode(',', $value);
?w - на помойку, ?a - добавлю.
Спасибо за совет.

p.s.
а как бы вы с помощью своего метода реализовали бы вставку префикса таблиц?
str_replace??? ;)
Юрий Насретдинов:
return implode(',', $value);
Низя!

Надо так:


case '?a':
foreach($value as $k=>$v) $value[$k]="'".mysql_escape_string($v)."'";
break;
case '?an':
foreach($value as $k=>$v) $value[$k]=intval($v);
break;
case '?af':
foreach($value as $k=>$v) $value[$k]=floatval($v);
break;
case '?ab':
foreach($value as $k=>$v) $value[$k]='0x'.bin2hex($v);
break;


И естественно немного рег доработать. Иначе получается нарушение безопасности (сами подумайте, почему)
Дмитрий Котеров:
ну во первых с чего вы взяли что метод с рег. выражениями будет тормозить ???
Во-первых, с чего вы взяли, что я взял, что метод с рег. выражениями будет тормозить ??? (Если уж на то пошло.)

попробуйте на досуге написать db filesystem и вставку 2М файла в кавычках еще и проэкранировав там слеши
И пробовать не нужно - это стандартный и, кстати, рекомендуемый на mysql.com способ (кажется, видел там) - только надо не addslashes() примерять, а mysql_escape_string(). Он преобразует как раз те символы, которые нужно, а остальные - не трогает. Вот метод переведение в 16-ричное представление как раз жрет кучу ресурсов и к тому же раздувает данные в несколько раз.

ну спецификаторы больше нужны не для mysql, а для программиста: чтобы он по запарке не поменял бы местами аргументы
Непонятна эта фраза, совершенно. При чем тут программист? Какое ему преимущество дают спецификаторы, если он захочет что-то перепутать?

case '?a': return implode(',', $value);
Нет! Не implode(',', $value), а вначале их заслэшить, обрамить кавычками, а уж затем - имплодить.

а как бы вы с помощью своего метода реализовали бы вставку префикса таблиц?
Никак бы не реализовал. Надо все же отделять мух от котлет: префиксам в этой функции не место (далеко не в каждом проекте они используются, и далеко не всегда одинаковы - может понадобится использование разных префиксов). А вот вставку _констант_ - это реализовано в полной версии функции, http://dklab.ru/chicken/nablas/30.html ('SELECT * FROM ?#MY_TABLE WHERE a=?, b=?'). Там же, кстати, и вставка массивов, и даже вставка пар ключ='значение' есть (см. примеры). Плюс - предварительная трансляция запроса (хотя, пожалуй, это все же и правда из пушки по воробьям, через регулярные выражения не должно быть медленнее).
Ant:
Выделено из темы «Облегченные placeholder-ы для mysql_query().»,
расположенной в форуме Склад готовых решений :: PHP (14 Ноября 2004, 23:55).
_sultan_:
И плюс не используются регулярные выражения.
Какой вывод я могу сделать из вашей фразы, как не нежелательность использования рег.выр. ??

вы наверное не совсем точно поняли насчет спецификаторов...
поясню на примере:
sql_placehlder("insert into tbl(field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13....fieldn) values (?n,?n,?n,?s,?s,?s,?f,?f,?n,?f,?n....?b)",
$some_$var, $other_var, $another_var, ... $varN)

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

на знаю как вам но мне еще ни разу не приходилось использовать конструкцию IN() со строками...
можете привести примеры когды это может понадобиться ???

а зря вы так насчет префиксов....
если допустим написали вы модуль какой-нибудь для cms (просто пример), и поставили на сайт, на котором уже стоит форум типа phpbb, и все там таблицы без префиксов и так получилось что имена одной или нескольких таблиц у вашего модуля и у phpbb совпадают - придется вам во всех запросах вставлять префикс ???
не лучше ли приучить себя везде использовать перед таблицами сивол ^ и уже в зависимости нужен он или нет - определять констунту db_prefix как пустую строчку или "your_prefix_" ?

насчет полной версии - это вообще ахтунг! (С) :)
вот именно там надо мух от котлет разгребать!
на какой ... такая заумная конструкция для вставки констант а???
не лучше ли, зная тип константы, вставить ее через ?n (?s)
почему бы тогда не сделать конструкцию ?!SOME_GLOBAL_VAR - для чиста пацанской вставки глобальных переменных ?? :)

а вот насчет ключ=значение - вы затронули очень интересную тему... ;)
почпму бы не пойти дальше ? ;)
почему бы не написать функцию, которая бы сама генерировала бы sql-запросы ???
мы задаем ей, что мы например хотим DELETE запрос к таблице table1, и она бы проявляя недюжинные навыки wifi-телепатии (:lol:) возвращала бы готовый запрос :)))

у меня есть некоторые наработки в этом направлении, но я ы хотел сперва увидеть ваше мнение :)
Дмитрий Котеров:
не лучше ли, зная тип константы, вставить ее через ?n (?s)
Вы не поняли, зачем нужно вставлять константы. Сравните:

sql_pholder("SELECT * FROM ".TBL_NAME." WHERE ...");

и

sql_pholder("SELECT * FROM ?#TBL_NAME WHERE ...");

Второе явно читается лучше. Это просто способ вставки в строку различных имен таблиц, полей и т.д. - не более того. Глобальные переменные тут совершенно ни при чем!

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

почему бы не написать функцию, которая бы сама генерировала бы sql-запросы ???
А зачем? Выразительные средства SQL весьма богаты. Генератор запросов в общем случае будет малополезен.

Кстати, если программа грамотно спроектирована, то в ней практически все запросы будут с JOIN-ами (запросов к одиночным таблицам на практике очень мало). Я раньше писал как раз в основном одиночными запросами (см. мою книгу, например), однако со временем понял, что мощь SQL - как раз в объединении данных из нескольких таблиц. Если ничего объединять не надо, то либо скрипт слишком прост, либо же это объединение производится программным способом (прямо на PHP), что заведомо менее оптимально.
_sultan_:
иcходя из своего опыта, я считаю что лучше сделать 2 простых запроса, чем 1 сложный, потому что mysql - это mysql, естественно в постгрес или мсскл нужно делать обратное :))

я так и не понял для чего выносить имена таблиц в константы ??? имхо это уже черезчур!
приведите пжлст четкую аргументацию имеющую прямое предназначение в практике, а не "по хорошему надо все выносить"....
давайте тогда не только имена и поля таблиц но и конструкции SQL выносить в константы, а то ведь есть PL/SQL, TransactSQL.... (шутка :)
ваши 2 примера я даже сравнивать не хочу - оба плохи :)
я бы написал
sql_pholder("SELECT * FROM ^tablename WHERE ...");
и не парился бы.

на проекте где кроме моих таблиц больше ничего не будет - префикс будет пустой и шляпка будет просто удаляться...
а вот ваш код из полной версии плейсхолдера имхо содержит бесполезный функционал.
объясните мне зачем писать имена констант в такой заумной конструкции, когда можно ограничиться лишь вставкой "?w" ??????
пример с глобальными переменными - аналогия к константам.
есть товарищи хранящие конфиг сайта не в константах а в какой-нить глобальной переменной $cfg (PMA например)
а как же с ними быть? :)

вы наверное не уловили мою мысль....
ситуация: админка в cms: пользователь удаляет новость с id=$_GET['id'].
стандартная ситуация, вы смотрите имеет ли юзер права удалять новость и т.д
а потом пишете DELETE FROM ....
или вызываете функцию и передаете 2 параметра: имя таблицы и тип запроса(delete)
она смотрит, что кючевым полем является id, находит такое же значение в $_REQUEST, и делает запрос...
красота да и только! :)
Дмитрий Котеров:
я так и не понял для чего выносить имена таблиц в константы ???
Простите, у вас в программировании опыт сколько лет?
Я же выше аргументировал, зачем нужны константы. Неужели для вас эти мысли не кажутся самой собой разумеющимися?

Короче говоря, про префикс - вы и сами можете догадаться, чем он плох, и какие у него недостатки. Главный - неуниверсальность и смешение нескольких областей в одну кучу.
?w - это что? Она вставляет текст, не обрамляя его апострофами?
Глобальные переменные ни при чем, еще раз говорю.

или вызываете функцию и передаете 2 параметра: имя таблицы и тип запроса(delete)
Опять вы мешаете все в одну кучу. REQUEST-параметры не имеют к MySQL ни малейшего отношения. Писать надо модульно, так, чтобы каждый модуль был самодостаточен, а не в виде простыни кода, которую потом очень трудно будет менять.
_sultan_:
?w - да текст вставляется без обрамения.
А неужели ваши константы (имена таблиц) как-то обрамляются ? не считая `` конечно же :)
У меня видно нету такого опыта как у вас, да и навыки телепатии у меня чрезвычайно слабо развиты, поэтому ваши нераскрытые доводы насчет смешения областей в кучу для меня остались непонятны....

все, дальше флеймить считаю делом бесполезным.
тему можно закрывать или вообще удалять, дабы в чьем-нибудь журнале не появилась очередная заметка о гастролирующих клоунах
каждый остался при своем мнении...
Дмитрий Котеров:
?w - да текст вставляется без обрамения.
А неужели ваши константы (имена таблиц) как-то обрамляются ? не считая `` конечно же
Кстати, можно сделать backtick-и, да. Для надежности.

?w и ?#КОНСТАНТА существенно отличаются тем, что, имея ?w, возникает потенциальная возможность вставить случайно и значение какой-нибудь переменной, в то время как ?# от этого застрахована (константы - на то и константы, чтобы иметь постоянное значение, а не пришедшее из формы, к примеру). К тому же при использовании ?w надо указывать имя таблицы в качестве аргументов, а не прямо в запросе. Это неудобно.

В общем, читайте Страуструпа и Кнута, постигайте философию программирования (в частности, чем плохо смешение всего в кучу).
Punisher:
Все ваши placeholder'ы - .

Прочитал ветку и сразу же возник вопрос - чем ваши, товарищ гастролирующий клоун, плэйсхолдеры собственно фундаментально, да и вообще, отличается? За исключением абсолютной неосведомлённости о работе с типами данных в MySQL вам не стоит претендовать даже на какую-либо кртику... Или просто своё "" к телу ближе?
И о каких наработках может идти речь, если у вас имеется лишь малейшее понятие (да судя по всему и опыт) работы с базами данным, и в частности с MySQL, слабое понятие обработки глобальных массивов и пр... Откуда только берутся такие крикливые товарищи... Гастроли, видно! :-)
Дмитрий Котеров:
В соответствии с правилами форума, давайте будем воздерживаться от нецензурных выражений, ОК? А то я уже устал модерировать.
_sultan_:
1 пример:
sql_placeholder("SELECT * FROM ?#USERS_TABLE WHERE ....", $args, $args, $args....);
$sql_placeholder("SELECT * FROM ?w WHERE ....", USERS_TABLE, $args, $args, $args....);
.....
закрывайте топик....
Дмитрий Котеров:
Очень показательный пример, кстати. Второе - совершенно явно хуже читается, к тому же еще и ошибкам подвержено, да и желанию использовать переменную вместо константы.
А топик закрывать не будем, потому что тут - обсуждение функции вообще, а не конкретно беседа с вами. С чего бы его закрывать? Опять у вас эгоцентризм? (-:
Юрий Насретдинов:
Небольшой апдейт, добавляющий поддержку массивов (а заодно «причесанный вид», чтобы можно было запихать функцию куда-нибудь, и чтобы она занимала там как можно меньше места):

function qw()
{
$args=func_get_args();
$conn=null;
if(is_resource($args[0])) $conn=array_shift($args);
$query = call_user_func_array('mk_qw', $args);
return $conn!==null? mysql_query($query, $conn) : mysql_query($query);
}

function mk_qw()
{
$args=func_get_args();
$tmpl=&$args[0];
$tmpl=str_replace('%', '%%', $tmpl);
$tmpl=str_replace('?', '%s', $tmpl);
foreach ($args as $i=>$v)
{
if(!$i) continue;
if(is_array($v))
{
$tmp=array();
foreach($v as $val)
{
if(is_numeric($val)) $tmp[]=$val;
else $tmp[]="'".mysql_escape_string($val)."'";
}
$args[$i]=implode(',',$tmp);
}
if(is_numeric($v)) continue;
$args[$i] = "'".mysql_escape_string($v)."'";
continue;
}
for($i=$c=count($args)-1; $i<$c+2; $i++) $args[$i+1]='UNKNOWN_PLACEHOLDER_'.$i;
return call_user_func_array('sprintf', $args);
}
Дмитрий Котеров:
Вот теперь точно preg_replace_callback будет оптимальнее.
Юрий Насретдинов:
Дмитрий Котеров:
ИМХО и так нормально =). В принципе, какая в конце концов разница - использовать sprintf или preg_replace_callback?
Дмитрий Котеров:
В данном случае разница есть: приходится организовывать вложенный цикл, в то время как preg_replace_callback могла бы эту задачу взять на себя. Получился бы и более короткий, и более оптимальный код. Это в исходной версии было примерно все равно, здесь же - некоторое преимущество имеется.
Юрий Насретдинов:
Дмитрий Котеров:
Да нет, в любом случае пришлось бы все обрабатывать =). Так что разницы особой ИМХО нет. Или я такой глюпый, не понимаю, что ты имеешь ввиду?
Иван Шумков:
Если поместить эти две функции в класс, то выдает ошибку в строке колбека. Видимо он функцию не находит. Как поступить?

Очень просто оказывается. Аргументом является массив, где первый элемент класс, а второй функция.
$query = call_user_func_array(array($this, '_mkSql'), $args);

Простите, что задаю вопросы не подумав.
Юрий Насретдинов:
Ivan Shumkov
Да, именно так.
Алексей Пешков:
Извините, немного не в тему, но зачем делать:
$tmpl=str_replace('%', '%%', $tmpl);
$tmpl=str_replace('?', '%s', $tmpl);

вместо того, чтобы напрямую использовать синтаксис функции sprintf, который побогаче простых '?'
Дмитрий Котеров:
Потому что % может, например, использоваться в SQL-выражениях.
Vasiliy:
Небольшой апдейт, добавляющий поддержку массивов

А что вы подразумеваете под "поддержкой массивов" ? В моём понимании это то, в функции передаётся только 2 параметра – шаблон запроса и массив значений.

Не хочу ставить под сомнение работоспособность функции mk_qw(), как я понял её многие используют, но она уменя не работает:


echo mk_qw('... WHERE firs=? OR second=?',1,2);
//... WHERE firstname=1 OR secondname=2

$array1 = array('first','second');
echo mk_qw('... WHERE first=? OR second=?',$array1);
//Notice: Array to string conversion in …
// ... WHERE first='Array' OR second=UNKNOWN_PLACEHOLDER_1

$array1 = array('first','second');
$array2 = array(1,2);
echo mk_qw('... WHERE first=? OR second=?',$array1,$array2);
//Notice: Array to string conversion in …
//Notice: Array to string conversion in …
// ... WHERE first='Array' OR second='Array'
[/PHP:1:4ebb461f3e]

Небольшой разбор кода функции mk_qw() привел к тому, вместо этой части:

...
}
if(is_numeric($v)) continue;
$args[$i] = "'".mysql_escape_string($v)."'";
continue;
}
...
[/PHP:1:4ebb461f3e]

Использовать этот код:

...
} else {
if(is_numeric($v)) continue;
$args[$i] = "'".mysql_escape_string($v)."'";
continue;}
}
...
[/PHP:1:4ebb461f3e]

Проверка:

$array1 = array('first','second');
echo mk_qw('... WHERE first=? OR second=?',$array1);
// ... WHERE first='first','second' OR second=UNKNOWN_PLACEHOLDER_1

$array1 = array('first','second');
$array2 = array(1,2);
echo mk_qw('... WHERE first=? OR second=?',$array1, $array2);
// ... WHERE first='first','second' OR second=1,2
[/PHP:1:4ebb461f3e]

Разве полученная строка, согласно SQL синтаксису, верна?

Из всего это вероятнее всего то, что я чего-то не понимаю! Поэтому я использую такую функцию:

function mysql_make_qw(){

$args=func_get_args();
$tmpl=&$args[0];
$tmpl=str_replace('%', '%%', $tmpl);
$tmpl=str_replace('?', '%s', $tmpl);

$args_out = array();
array_push($args_out, $args[0]);

if(is_array($args[1])){
foreach ($args[1] as $v){
if (!is_int($v)) $v = "'".mysql_escape_string($v)."'";
array_push($args_out, $v);
}
}
else{
foreach ($args as $i=>$v) {
if (!$i) continue;
if (!is_int($v)) $v = "'".mysql_escape_string($v)."'";
array_push($args_out, $v);
}
}
for($i=$c=count($args_out)-1; $i<$c+2; $i++) array_push($args_out, 'UNKNOWN_PLACEHOLDER_'.$i);
return call_user_func_array('sprintf', $args_out);
}
[/PHP:1:4ebb461f3e]

Примеры использования:

echo mysql_make_qw('... WHERE first=? OR second=?',1,2);
//... WHERE first=1 OR second=2

$array2 = array(1,2);
echo mysql_make_qw('... WHERE first=? OR second=?',$array2);
//... WHERE first=1 OR second=2

$array1 = array('first','second');
$array2 = array(1,2);
echo mysql_make_qw('... WHERE first=? OR second=?',$array1,$array2);
//... WHERE first='first' OR second='second'

$array1 = array('first','second');
$array2 = array(1,2);
echo mysql_make_qw('... WHERE first=? OR second=?',$array1,2,$array2);
// Notice: Array to string conversion …
// … WHERE first=1 OR second='Array'
[/PHP:1:4ebb461f3e]

Если существует вероятность того, что аргументы функции будут иметь вид, как в последнем примере, то можно в функции добавить дополнительное условие для переопределения того, является ли текущий аргумент массивом или нет.
Юрий Насретдинов:

Небольшой разбор кода функции mk_qw() привел к тому, вместо этой части:
...
Использовать этот код:

Да, там действительно ошибка, я как-то не заметил... Видимо, раз не заметил никто, поддержка массивов особо не нужна...


// ... WHERE first='first','second' OR second=1,2

Разве полученная строка, согласно SQL синтаксису, верна?

Нет, конечно. Если передаётся в качестве аргумента массив, то подразумевается, что используется выражение типа

SELECT ... WHERE id IN (?)

Ну и соотвественно генерируется правильный и безопасный SQL-запрос.

P.S. Когда вы наконец научитесь вместо is_int использовать is_numeric... Ну нет фактически в PHP типизации данных, а если и есть, то не стоит на неё особо полагаться. Надо проверять СТРОКУ на то, СОДЕРЖИТ ЛИ ОНА ТОЛЬКО ЦИФРЫ, а не проверять, является ли переменная integer`ом сейчас, или нет... Пример:


$a=123;
$b='123';
$c='12_3';

function bool2str($bool) { if($bool) return ' истина '; else return ' ложь '; }

echo bool2str(is_int($a)).bool2str(is_int($b)).bool2str(is_int($c)).'<br>';
//выведет «истина !ложь! ложь»
echo echo bool2str(is_numeric($a)).bool2str(is_numeric($b)).bool2str(is_numeric($c));
//выведет «истина !истина! ложь»

Иван Шумков:
Вот теперь точно preg_replace_callback будет оптимальнее.

Не совсем вас понимаю. Как preg_replace_callback может заменить здесь цикл?
Дмитрий Котеров:
Читайте документацию на preg_replace_callback.

Ссылка в тему:
http://forum.dklab.ru/php/heap/DesigningOfTheElementaryModuleForAbstractionFromSqlA-server.html

Я уже почти готов выложить классы. Еще чуть-чуть только.
Иван Шумков:
Читайте документацию на preg_replace_callback
Туплю я, простите :)

Я уже почти готов выложить классы. Еще чуть-чуть только.
Уже читал, жду с нетерпением.
snark:
Надо проверять СТРОКУ на то, СОДЕРЖИТ ЛИ ОНА ТОЛЬКО ЦИФРЫможет тогда лучше ctype_digit юзать?
Юрий Насретдинов:
может тогда лучше ctype_digit юзать?
Нет, ведь float тоже можно вставлять в MySQL, а с помощью этой функции мы проверяем только на цифры. В данном случае это не важно, что использовать, но уж точно не надо заменять is_numeric на что-то другое
streloc: не могу сделать ORDER BY
$news = sql_placeholder(
'SELECT * FROM news WHERE del=? ORDER BY news_id=?', 1, "DESC"
Юрий Насретдинов:
ORDER BY news_id=?
Это ещё что :)?
Maus:
streloc
еще бы. Даже если бы все остальное было в норме - функция облегчённых плейсхолдеров закавычит DESC - т.к. это строковое значение. И в запросе появится ошибка .
streloc:
Спасибо. Давно уже понял в чём ошибка, но вчера не смог войти на форум что бы удалить сообщение.
snark:
всетаки самое обидное в плейсхолдерах - это то, что не смотря на мое увжение к ДК (по его книге собсно делал первые неловкие шаги) и на то что он всем советует активно придерживаться PEAR-овского формата кода он таки написал свои плейсхолдеры так, что PEAR сотоварищи просто побелеют от того как оно написано... не поймите мя неправильно, я ЗА плейсхолдеры, но так жеж низя чесслово...
кстати тема плейсхолдеров не нова :) я давно юзаю ф-цию подобную mk_qw просто для легкогй переносимости perl-ового DBI под php и думаю что многие так же делают...

З.Ы. таки спасибо ДК и всем остальным за святое дело моего просвещения... некоторые вещи я б даже и не понял как можно сделать не будь этого форума :) бывает так что вот вроде все очевидно, а как сделать не знаешь :( спасибо Вам всем и извините за оффтоп
Дмитрий Котеров:
он таки написал свои плейсхолдеры так, что PEAR сотоварищи просто побелеют от того как оно написано
http://dklab.ru/lib/DbSimple смотрели?
Anonymous:
ув. ДК, Вы меня не поняли :( я имел ввиду это и потом гляньте как у Вас
я никоим образом не хочу показаться невежливым к Вам или кому бы то нибыло, но, имхо, многие уважаемые на данном форуме люди требуя чего либо от людей (а тут часто проскакивает что то в духе "оформления нет - даже смотреть не буду") могли бы и сами придерживаться стандартов

З.Ы. за плейсхолдеры - СПАСИБО! подсмотрел там некоторые вещи до которых сам никак не доходил...
Дмитрий К.:
Такой вопрос: у меня есть таблица, из которой нужно выбирать значения по различному в каждом случае количеству критериев, т.е. иногда нужно написать:
...word1=?, word2=?', $element['word1'], $element['word2']...
, а иногда:
...word1=?', $element['word1']...
(Пример: поиск, в котором естественно каждый раз кол-во слов, а в конечном счёте аргументов, будет разным)
И если строку запроса я могу сформировать динамически, то как мне указывать каждый раз различное кол-во аргументов?
Спасибо!
Maus:
Дмитрий К.
А Вы не пробовали глянуть в сторону "необлегчённых" плейсхолдеров? http://dklab.ru/lib/Database_Placeholder/
Там поддерживается списковый плейсхолдер.
А так посмотрите на call_user_func_array()
Дмитрий К.:

Вставлять целые списки:

$sql = sql_placeholder(
'SELECT * FROM ?#MY_TABLE WHERE a IN (?@)',
array(10, 20, 30, 40, 50, 60, 70, 80)
);


А как указать, что a например должно быть равно второму элементу массива?

Скажем, есть mysql_qw('SELECT * FROM news WHERE new=? AND aut=?', $new, $aut). Я правильно понимаю, что нужно записать так:
call_user_func_array('mysql_qw', $args)
, где $args = array('SELECT * FROM news WHERE new=? AND aut=?', $new, $aut) ?
Maus:
А как указать, что a например должно быть равно второму элементу массива?
Никак. а - это все элементы списка.
Я правильно понимаю
Вроде да. Попробовали бы сначала, что ли...
Дмитрий К.:
Никак. а - это все элементы списка.
Я думал, это любой элемент из списка. Видимо не так понял.

Спасибо за помощь, теперь всё работает!
Rusl@nus:
А что делать, если нужно сделать запрос вида:
INSERT INTO table (id,name) VALUES (1,'some_string'),(2,'some_string'),(3,'some_string')...
Количество таких выражений в скобках может варьироваться и быть сколь угодно большим.
Юрий Насретдинов:
Такой запрос вполне можно составить и вручную. Если очень хочется, можно использовать call_user_func_array() для решения Вашей проблемы.
Rusl@nus:
Вручную составлять не охота. Нужно чтобы все обращения к БД проходили через эту библиотеку.
Возник еще один нюанс. Есть запрос вида:
... WHERE name LIKE 'abc%'...
Как можно осуществить это в рамках данной библиотеки? Если вызывать так:
('... WHERE name LIKE ?% ...',$param)
то на выходе имеем:
... WHERE name LIKE '$param'% ...
Если:
('... WHERE name LIKE ? ...',$param.'%')
то:
... WHERE name LIKE '$param\%' ...
Ни то, ни другое не подходит...
Rusl@nus:
Нет предложений?
Selfauthor: Значение NULL в placeholder
Пользуюсь placeholder-ом. Но есть одно неудобство: когда нужно передать в запрос значение NULL, появляется проблема. Если передавать NULL, как строку, то он её в апострофы заключает. Если переменной присвоить NULL, то в результате в запросе всё равно пустая строка. Как всё-таки правильно передать NULL?

Эта тема на forum.dklab.ru