Сведения о сервере:
PHP v5.3.5
Использование MySQLi-библиотеки клиент api-версия: mysqlnd 5.0.7-dev – 091210 – $ Редакция: 304625 $
MySQL Server v5.5.9
У меня есть хранимая функция в MySQL, называемая f_get_owner_locations (_in int). Он создает текстовую переменную, в которой хранятся местоположения, принадлежащие конкретному владельцу. Если я запустил
SELECT f_get_owner_locations( 3 );
из командной строки MySQL, он делает то, что он должен делать, и возвращает одну строку:
+----------------------------+ | f_get_owner_locations( 3 ) | +----------------------------+ | A-01 | +----------------------------+
Однако всякий раз, когда я пытаюсь запустить его через PHP, используя библиотеку MySQLi:
$sql = "SELECT f_get_owner_locations( 3 )"; $location = $GLOBALS['db']->fetch( $sql );
Я получаю эту ошибку:
Fatal error: Call to a member function fetch_field() on a non-object in ~/kernel/Database.php on line 328
Эта строка относится к этому:
/** * Binds results from a returning SQL statement to an array we can * loop through. * * @param $statement Statement object we're binding from. * @return Array of values being returned. * @since 0.1 */ private final function _bindResult( $statement ) { $results = NULL; $bind = array( ); //Get the result set, so we can loop through the fields. $result = $statement->result_metadata( ); //Loop through the fields and get a reference to each. while( $column = $result->fetch_field() ) //<=<=<=LINE 328 $bind[] = &$results[$column->name]; //Do the actual binding. call_user_func_array( array( $statement, 'bind_result'), $bind ); //Free the memory since we already have the result. $result->free_result(); return $results; } //_bindResult
Имейте в виду, что это не сработает, если оператор SQL не включает вызов функции. т.е. это работает:
$sql = "SELECT `id` FROM `owners`"; $owners = $GLOBALS['db']->fetch( $sql );
Но как только я добавлю, что вам нужно, чтобы в них были владельцы квартир (и это заявление также работает в командной строке MySQL):
$sql = "SELECT `id`, f_get_owner_locations(`id`) FROM `owners`"; $owners = $GLOBALS['db']->fetch( $sql );
Это дает мне эту ошибку о вызове функции-члена для не-объекта.
Я в тупике. Выполнение var_dump на $ result прямо перед циклами while, в моем методе _bindResults дает мне 1 правильный дамп, а затем останавливается и эта ошибка есть.
object(mysqli_result)#11 (5) { ["current_field"]=> int(1) ["field_count"]=> int(1) ["lengths"]=> NULL ["num_rows"]=> int(0) ["type"]=> int(1) }
Примечание: вызов f_get_owner_locations является вторым полем в этом списке выбора, поэтому он не сохраняет правильное полевое число, несмотря на то, что он должен зацикливаться на правильное количество полей.
Любые предложения обойти этот небольшой дорожный блок или подтверждение того, что это ошибка в библиотеке MySQLi или проблема с моим кодом привязки, будут высоко оценены.
UPDATE: следующий код:
mysql_connect( ... ); mysql_query( "select f_get_owner_locations(3)" ); die( mysql_error() );
Дал мне этот результат:
FUNCTION f_get_owner_locations does not exist.
Я больше задаюсь вопросом, является ли это просто неудачей для части PHP / MySQLi, чем моя?
ОБНОВЛЕНИЕ 2:
В соответствии с запросом код, используемый для создания функции:
drop function if exists f_get_owner_locations; delimiter | create function f_get_owner_locations( _in int ) returns text deterministic begin declare _output text default ""; declare _location varchar(255); declare _count int default 0; declare _done int default 0; declare _cursor cursor for select condos.location from owners left join condo_owners on owners.id = condo_owners.owner left join condos on condo_owners.condo = condos.id where owners.id = _in; declare continue handler for not found set _done = 1; open _cursor; repeat fetch _cursor into _location; set_count = _count + 1; set_output = concat( _output, ", ", _location ); until _done end repeat; set _count = _count - 1; close _cursor; set _output = trim( leading ", " from _output ); set _output = substring( _output from 1 for (_count * 6) ); set _output = trim( trailing ", " from _output ); return _output; end;| delimiter ;
Предоставлено немного рефакторинга, который может быть немного чище, но это то, что я использовал.