Каждый раз, когда вы получаете ...
"Warning: mysqli_fetch_object () ожидает, что параметр 1 будет mysqli_result, boolean задан«
blockquote>... это, вероятно, из-за проблемы с вашим запросом.
prepare()
илиquery()
могут возвращатьFALSE
(логическое), но это общее сообщение об отказе не оставляет вас в стороне от подсказок. Как вы узнаете, что не так с вашим запросом? Вы задаете !Прежде всего убедитесь, что сообщения об ошибках включены и видны: добавьте эти две строки в начало файла (ов) сразу после открытия
<?php
:error_reporting(E_ALL); ini_set('display_errors', 1);
Если ваше сообщение об ошибках установлено в php.ini, вам не придется беспокоиться об этом. Просто убедитесь, что вы обрабатываете ошибки изящно и никогда не раскрываете истинные причины каких-либо проблем для ваших пользователей. Выявление истинной причины для общественности может быть приглашением на золото с гравировкой для тех, кто хочет нанести вред вашим сайтам и серверам. Если вы не хотите отправлять ошибки в браузер, вы всегда можете следить за журналами ошибок веб-сервера. Расположение журналов будет варьироваться от сервера к серверу, например, на Ubuntu журнал ошибок обычно находится в
/var/log/apache2/error.log
. Если вы изучаете журналы ошибок в среде Linux, вы можете использоватьtail -f /path/to/log
в окне консоли, чтобы видеть ошибки, когда они происходят в режиме реального времени .... или как вы их делаете.Как только вы 'squared away на стандартном сообщении об ошибках, добавляющем проверку ошибок в вашем соединении с базой данных, и запросы дадут вам гораздо более подробную информацию о проблемах. Посмотрите на этот пример, где имя столбца неверно. Во-первых, код, возвращающий роковое сообщение об ошибке:
$sql = "SELECT `foo` FROM `weird_words` WHERE `definition` = ?"; $query = $mysqli->prepare($sql)); // assuming $mysqli is the connection $query->bind_param('s', $definition); $query->execute();
Ошибка является общей и не очень помогает вам в решении того, что происходит.
С помощью пары больше строк кода вы можете получить очень подробную информацию, которую вы можете использовать для решения проблемы сразу . Проверьте утверждение
prepare()
для правдивости, и если это хорошо, вы можете перейти к привязке и исполнению.$sql = "SELECT `foo` FROM `weird_words` WHERE `definition` = ?"; if($query = $mysqli->prepare($sql)) { // assuming $mysqli is the connection $query->bind_param('s', $definition); $query->execute(); // any additional code you need would go here. } else { $error = $mysqli->errno . ' ' . $mysqli->error; echo $error; // 1054 Unknown column 'foo' in 'field list' }
Если что-то не так, вы можете выплюнуть сообщение об ошибке, которое приведет вас к проблеме , В этом случае в таблице нет столбца
foo
, решение проблемы тривиально.Если вы выберете, вы можете включить эту проверку в функцию или класс и расширить ее, обработав ошибки изящно, как упомянутых ранее.
AFAIK, нет простого способа сделать это, потому что интерфейс mexFunction
скорее flat . Тем не менее, есть несколько различных обходных решений, о которых я могу думать, что должно помочь вам приблизиться. Выберите лучший вариант в зависимости от ваших потребностей.
dlp
в вашей mex-функции. Сделать первый параметр функции mex вызовом строки, которая указывает, какая функция-член глобального объекта должна быть вызвана. Очевидным недостатком является то, что вы превратили вашу mex-функцию в одноэлементный. dlp
, вы можете создать некоторый глобальный контейнер в функции mex, например std::map<std::string, dlp>
, а затем ссылаться на каждый экземпляр dlp
с помощью какого-либо имени из MATLAB. Например, для создания нового экземпляра вы вызываете функцию mex с именем, которое еще не существует в map
. Затем вы можете вызвать функцию mex с этим именем, строку, указывающую, какую функцию-член вызывать, и любые параметры, которые должны быть переданы в функцию-член. Также настройте какое-то соглашение, по которому вы можете стереть экземпляр dlp
из map
. dlp
, вы можете вернуть дескрипторы для каждого экземпляра. Например, создайте глобальный std::set<dlp *>
, и если у вас есть функция mex, создайте новый экземпляр dlp
, добавьте его в set
и верните копию указателя на выделенный объект в MATLAB (вставьте его в скаляр переменная типа mxUINT64_CLASS
). Последующие вызовы для вызова функций-членов на этом объекте передают эту переменную handle в функцию mex из MATLAB, вы будете соответствующим образом ее применять в файле mex, найдите ее в set
и вызовите функции-члены . Ни один из этих методов не является особенно красивым, но это единственные способы, с помощью которых я могу вызвать функции-члены класса C ++ из файла mex.
Самый простой способ - создать оболочку MEX, которая хранит экземпляр объекта класса, и отправить вызов этому двоичному файлу MEX. Я создал библиотеку для тех, кто пытается создать MEX-оболочку на C ++.
https://github.com/kyamagu/mexplus
быстрый фрагмент.
// C++ class to be wrapped.
class Database;
// Instance session storage.
template class mexplus::Session<Database>;
// Constructor.
MEX_DEFINE(new) (int nlhs, mxArray* plhs[],
int nrhs, const mxArray* prhs[]) {
InputArguments input(nrhs, prhs, 1);
OutputArguments output(nlhs, plhs, 1);
output.set(0, Session<Database>::create(
new Database(input.get<std::string>(0))));
}
// Destructor.
MEX_DEFINE(delete) (int nlhs, mxArray* plhs[],
int nrhs, const mxArray* prhs[]) {
InputArguments input(nrhs, prhs, 1);
OutputArguments output(nlhs, plhs, 0);
Session<Database>::destroy(input.get(0));
}
// Member method.
MEX_DEFINE(query) (int nlhs, mxArray* plhs[],
int nrhs, const mxArray* prhs[]) {
InputArguments input(nrhs, prhs, 2);
OutputArguments output(nlhs, plhs, 1);
const Database& database = Session<Database>::getConst(input.get(0));
output.set(0, database.query(input.get<string>(1)));
}
// And so on...
MEX_DISPATCH
Вы можете взглянуть на это представление в MATLAB Central. Насколько я знаю, это показывает лучшую практику, разработанную с советами групп новостей от многих, включая MathWorkers.