powered by simpleCommunicator - 2.0.40     © 2025 Programmizd 02
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / PHP: переменное число аргументов передать в массиве
20 сообщений из 20, страница 1 из 1
PHP: переменное число аргументов передать в массиве
    #39874217
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В PHP есть функция mysqli_stmt_bind_param , которой в аргументах передаются значения параметров запроса.
Я не знаю заранее число параметров.
Документация рекомендует использовать функцию call_user_func_array.
Но в комментариях рекомендуют использовать рефлекцию и вызывать invokeArgs.
Как будет лучше?
...
Рейтинг: 0 / 0
PHP: переменное число аргументов передать в массиве
    #39874933
TolikD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Документация не рекомендует call_user_func_array, а только предостерегает использование. Слишком мало информации для ответа на вопрос. Нужно выложить исходник или задачу, которую нужно выполнить.
...
Рейтинг: 0 / 0
PHP: переменное число аргументов передать в массиве
    #39874947
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Задача простая — сделать обертку для mysqli_stmt_bind_param, которая бы принимала строку с SQL-запросом и массивом параметров и возвращала подготовленный запрос.
...
Рейтинг: 0 / 0
PHP: переменное число аргументов передать в массиве
    #39875266
TolikD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Слишком абстрактная задача. Нужно конкретней. Я почему-то уверен, что здесь не нужно заморачиваться колбэком
...
Рейтинг: 0 / 0
PHP: переменное число аргументов передать в массиве
    #39875277
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мне нужна функция-обертка: dbquery($sql, $params=[])
Она принимает SQL-запрос. В SQL-запросе могут быть заданы переменные (параметры), в этом случае она должна их задать при выполнении запроса. После чего функция должна вернуть результат (например в ассоциированном массиве).
В mysqli параметры задаются вызовом mysqli_stmt_bind_param, в который сразу передаются все параметры запроса.
Если их количество мне неизвестно, нужно либо использовать многострочный switch вида:
Код: php
1.
2.
3.
4.
5.
6.
switch count($params) {
  case 1: mysqli_stmt_bind_param($st, 's', &$params[0]); break;
  case 2: mysqli_stmt_bind_param($st, 'ss', &$params[0], &$params[1]); break;
  case 3: mysqli_stmt_bind_param($st, 'sss', &$params[0], &$params[1], &$params[2]); break;
  ...
}


либо call_user_func_array.
...
Рейтинг: 0 / 0
PHP: переменное число аргументов передать в массиве
    #39875314
vkle
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Либо переходить на PDO. Там параметры по одному биндятся и не составит проблем сделать цикл.

Хотя, конечно, можно и на mysqli лисапед сочинить. Необходимую строчку кода с mysqli_stmt_bind_param собрать как текст, а потом ее выполнить при помощи eval().
...
Рейтинг: 0 / 0
PHP: переменное число аргументов передать в массиве
    #39875332
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Помоему cufa лучше, чем eval.
PDO у меня есть, но с этой прослойкой были какие-то неудобства.
Поэтому сейчас я хочу сделать более прямую обертку для mysqli и oci8.
...
Рейтинг: 0 / 0
PHP: переменное число аргументов передать в массиве
    #39875339
TolikD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
vkle,

дык проще сразу скуль делать сборку строк, чем коду в коде ))
...
Рейтинг: 0 / 0
PHP: переменное число аргументов передать в массиве
    #39875362
TolikD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Alibek B.,

авторлибо call_user_func_array.
тогда уж сразу с ReflectionClass, ибо авторthis saves you about 20-40% Speed. Головняк побольше, но только на первый взгляд.
...
Рейтинг: 0 / 0
PHP: переменное число аргументов передать в массиве
    #39875387
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Честно говоря, меня удивило написанное, что ReflectionClass быстрее.
Разве рефлекция по определению не медленная (поскольку нужно обрабатывать кучу метаинформации)?
...
Рейтинг: 0 / 0
PHP: переменное число аргументов передать в массиве
    #39875391
TolikD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Не знаю, но походу стОит доверять количеству голосов за комент. Бенчмарков никто пока не проводил, стань первым )
...
Рейтинг: 0 / 0
PHP: переменное число аргументов передать в массиве
    #39875418
TolikD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я не проверял, только предполагаю. Если использовать ReflectionClass, то задача даже упрощается, потому что это будет выглядеть примерно так
Пример из комента
Код: php
1.
2.
3.
4.
5.
6.
7.
$db     = new mysqli("localhost","root","","tests");
$res    = $db->prepare("INSERT INTO test SET foo=?,bar=?");
$refArr = array("si","hello",42);
$ref    = new ReflectionClass('mysqli_stmt');
$method = $ref->getMethod("bind_param");
$method->invokeArgs($res,$refArr);
$res->execute(); 

переделывается просто в такой вид
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
function dbquery($sql, $types, $params) {
	$db     = new mysqli("localhost","root","","tests");
	$res    = $db->prepare($sql);
	$refArr = array($types);
	foreach ($params as $v)
		$refArr[] = $v;
	$ref    = new ReflectionClass('mysqli_stmt');
	$method = $ref->getMethod("bind_param");
	$method->invokeArgs($res,$refArr);
	$res->execute();
	unset($ref);
}

$data = array("hello",42);
dbquery("INSERT INTO test SET foo=?,bar=?", 'si', $data)


Вот и не надо никаких ссылок
...
Рейтинг: 0 / 0
PHP: переменное число аргументов передать в массиве
    #39875554
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что-то не запутался со ссылками.
Не подскажите, как должно быть правильно?

Есть такой тестовый код, предполагающий наличие базы данных db, содержащей таблицу TMP(ID,C1,C2):
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
$sql = "insert into TMP(C1,C2) values (?,?);";
$col = ['C1','C2'];
$val = [[1,2]];
$tmp = 123;

$dbh = mysqli_connect('localhost', 'usr', 'pwd', 'db');
mysqli_set_charset($dbh, 'utf8');
mysqli_query($dbh,'delete from TMP');
$st = mysqli_stmt_init($dbh);
$rc = mysqli_stmt_prepare($st, $sql);
$param = []; $param[0] = str_repeat('s', count($col)); foreach ($col as $v) $param[] = &$tmp; debug_zval_dump($param);
call_user_func_array(array($st, 'bind_param'), $param);
$n = count($val);
foreach ($val as $row) {
        for ($i = 0; $i < $n; $i++) $param[$i+1] = &$row[$i]; debug_zval_dump($param);
        $rc = mysqli_stmt_execute($st);
        print "* #$i: new id " . mysqli_stmt_insert_id($st) . "\n";
}
mysqli_stmt_close($st);
$res = mysqli_query($dbh,'select * from TMP');
while ($row = $res->fetch_assoc()) print_r($row);
mysqli_close($dbh);


По идее, в таблицу должна добавиться строка со значениями (1,2).
Однако добавляется строка со значениями (123,123) и отладочный вывод таков:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
array(3) refcount(2){
  [0]=>
  string(2) "ss" refcount(1)
  [1]=>
  &long(123) refcount(3)
  [2]=>
  &long(123) refcount(3)
}
array(3) refcount(2){
  [0]=>
  string(2) "ss" refcount(1)
  [1]=>
  &long(1) refcount(2)
  [2]=>
  &long(123) refcount(4)
}
* #1: new id 39
Array
(
    [ID] => 39
    [C1] => 123
    [C2] => 123
)

Почему $param принимает не те ссылки?
...
Рейтинг: 0 / 0
PHP: переменное число аргументов передать в массиве
    #39875557
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кстати, если делать bind_param на каждой итерации, то работает:
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
$st = mysqli_stmt_init($dbh);
$rc = mysqli_stmt_prepare($st, $sql);
$param = []; $param[0] = str_repeat('s', count($col)); foreach ($col as $v) $param[] = &$tmp; debug_zval_dump($param);
call_user_func_array(array($st, 'bind_param'), $param);
$n = count($col);
$c = 0;
foreach ($val as &$row) {
        for ($i = 0; $i < $n; $i++) $param[$i+1] = &$row[$i]; debug_zval_dump($param);
        call_user_func_array(array($st, 'bind_param'), $param);
        $rc = mysqli_stmt_execute($st);
        $c++; print "* #$c: new id " . mysqli_stmt_insert_id($st) . "\n";
}
mysqli_stmt_close($st);
$res = mysqli_query($dbh,'select * from TMP');
while ($row = $res->fetch_assoc()) print_r($row);


Но в документации прямо указывается, что bind_param нужно делать только один раз, а execute() будет использовать те значения, которые заданы в привязанных переменных на момент вызова этого метода.
...
Рейтинг: 0 / 0
PHP: переменное число аргументов передать в массиве
    #39875560
TolikD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Нет. В документации сказано, что bind_param использует ссылки при прямом использовании функции. А в данном коде используется колбэк, который выполняет привязку ссылок на переменную $tmp. Если в дальнейшем менять $tmp, то и значения будут меняться. Пых не делает связь между байндом и колбэком, это ошибочное мнение.
...
Рейтинг: 0 / 0
PHP: переменное число аргументов передать в массиве
    #39875563
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
https://www.php.net/manual/ru/mysqli-stmt.execute.php
Пример #1
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
$stmt = $mysqli->prepare($query);

$stmt->bind_param("sss", $val1, $val2, $val3);

$val1 = 'Stuttgart';
$val2 = 'DEU';
$val3 = 'Baden-Wuerttemberg';

/* выполняем запрос */
$stmt->execute();

$val1 = 'Bordeaux';
$val2 = 'FRA';
$val3 = 'Aquitaine';

/* выполняем запрос */
$stmt->execute();
...
Рейтинг: 0 / 0
PHP: переменное число аргументов передать в массиве
    #39875565
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TolikDПых не делает связь между байндом и колбэком, это ошибочное мнение.
Я вызываю bind_param и передаю в него набор ссылок &$param[i].
Я это понимаю так, что при вызове execute в запрос будут переданы значения, которые заданы по ссылке, указанной в массиве $param. И если я меняю значения в массиве $param, то адреса элементов $param[i] не меняются, но заданные в них ссылки на значения меняются — и в execute должны передаваться новые значения.
Не так?
...
Рейтинг: 0 / 0
PHP: переменное число аргументов передать в массиве
    #39875566
TolikD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: php
1.
call_user_func_array(array($st, 'bind_param'), $param);


Код: php
1.
$param = &$tmp;


Вот и всё! О какой привязке $val идет речь?
Чтоб работало, нужно именно так:
Код: php
1.
2.
3.
4.
5.
6.
7.
$n = count($val);
foreach ($val as $row) {
        for ($i = 0; $i < $n; $i++) $param[$i+1] = &$row[$i]; debug_zval_dump($param);
        $rc = mysqli_stmt_execute($st);
        print "* #$i: new id " . mysqli_stmt_insert_id($st) . "\n";
}
call_user_func_array(array($st, 'bind_param'), $param);
...
Рейтинг: 0 / 0
PHP: переменное число аргументов передать в массиве
    #39875567
TolikD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Байнд и колбэк, повторяюсь, это совершенно разные функции. Может выспаться надо? )
...
Рейтинг: 0 / 0
PHP: переменное число аргументов передать в массиве
    #39876497
Фотография ScareCrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
автор&$params[0]
а амперсанд то зачем?
...
Рейтинг: 0 / 0
20 сообщений из 20, страница 1 из 1
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / PHP: переменное число аргументов передать в массиве
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]