I am trying to make a search key feature. But I am not getting any result with the following query.
public function SearchKey($key,$userid)
{
$key = mysqli_real_escape_string($this->db, $key);
$userid = mysqli_real_escape_string($this->db, $userid);
$query = mysqli_query($this->db,"SELECT * FROM posts WHERE
MATCH(theKey) AGAINST('$key' IN NATURAL LANGUAGE MODE)
AND uid = '$userid' ORDER BY sgq_id LIMIT 5") or die(mysqli_error($this->db));
while($row=mysqli_fetch_array($query)) {
$data[]=$row;
}
if(!empty($data)) {
return $data;
}
}
Then fetch,
$search = $Data->SearchKey($key, $userid);
if($search){
foreach($search as $data){
echo $data['theKey'];
}
}
For example if I search OK005 then I can not get any results. I tried Full-text Search functions https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html
Anyone can help me here, what I am missing ?
You're using single quotes to pass your variables. These will not be expanded in your query. You're better off using a prepared statement, and use parameter/value bindings to pass the variables. This will also solve the problem of SQL injection that your code appears to be vulnerable to.
You can try something like:
// Replace comment with appropriate connection data.
$pdo = new PDO(/* your DSN etc. */);
// Your query.
$sql =
'SELECT * FROM posts WHERE ' .
'MATCH(theKey) AGAINST(? IN NATURAL LANGUAGE MODE) ' .
'AND uid = ? ORDER BY sgq_id LIMIT 5';
// Create prepared statement from query.
$statement = $pdo->prepare($sql);
// Bind the values and enforce data type.
$statement->bindValue(1, $key, PDO::PARAM_STR);
$statement->bindValue(2, $userid, PDO::PARAM_INT);
// Run query.
$statement->execute();
// Get query results.
$rows = $statement->fetchAll();
// Your magic ...
How can I add ORDER BY field to the end of this SQL query
$sql = "SELECT item_id,field FROM item WHERE department=".$catid;? I can't get the syntax right due to the PHP variable at the end...
I tried $sql = "SELECT item_id,field FROM item WHERE department=".$catid ORDER BY field; but obviously that didn't work
You can fix your syntax error like this, using another concatenation operator . to append the ORDER BY clause:
$sql = "SELECT item_id,field FROM item WHERE department=".$catid." ORDER BY field";
As long as $catid is an integer, that will work, but it may leave you open to SQL injection, dependent on the source of the value in $catid.
Best practice is to use a prepared query. For MySQLi, something like this:
$sql = "SELECT item_id,field FROM item WHERE department=? ORDER BY field";
$stmt = $conn->prepare($sql);
$stmt->bind_param('i', $catid); // change to 's' if $catid is a string
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
// do something with results
}
I am using the following PDO query:
<?php
$cadena = $_SESSION[Region];
// We Will prepare SQL Query
$STM = $dbh->prepare("SELECT `id_mesero`, `nombre_mesero`,`alias_mesero`, `rest_mesero` FROM tbmeseros WHERE cadena_mesero='$cadena'");
// For Executing prepared statement we will use below function
$STM->execute();
// we will fetch records like this and use foreach loop to show multiple Results
$STMrecords = $STM->fetchAll();
foreach($STMrecords as $row)
{
The value from the 'rest_mesero' field is the index from the table 'tbrestaurantes'.
I would need to join some fields values from 'tbrestaurantes' to the PDO query, but I don't know how to do it using PDO.
Any help is welcome.
UPDATED QUESTION TEXT
This is my proposal for the query :
$dbh->prepare("SELECT * FROM tbmeseros LEFT JOIN tbrestaurantes ON tbmeseros.rest_mesero = tbrestaurantes.id_restaurante WHERE tbmeseros.cad_mesero = ?");
But is show an error:
Warning: PDOStatement::execute() [pdostatement.execute]: SQLSTATE[HY093]: Invalid parameter number: no parameters were bound in /.../AdminMeseros.php on line 80
Line 80 is
$STM->execute();
This is my updated query:
<?php
$cadena = $_SESSION[Region];
$STM =$dbh->prepare("SELECT * FROM tbmeseros LEFT JOIN tbrestaurantes ON tbmeseros.rest_mesero = tbrestaurantes.id_restaurante WHERE tbmeseros.cad_mesero = ?");
$STM->bindParam(1, $cadena);
// For Executing prepared statement we will use below function
$STM->execute(array($cadena));
// we will fetch records like this and use foreach loop to show multiple Results
$STMrecords = $STM->fetchAll();
foreach($STMrecords as $row)
{
And here table's screenshots:
For tbmeseros:
For tbrestaurantes:
The value of $cadena is 'HQ3'.
When you put a parameter in the SQL, you need to supply the value for the parameter. There are two ways to do that:
1) Call bindParam():
$STM->bindParam(1, $cadana);
2) Provide the values when calling execute():
$STM->execute(array($cadana));
You need to fill the ? in the query:
$q = $dbh->prepare("SELECT * FROM tbmeseros LEFT JOIN tbrestaurantes ON tbmeseros.rest_mesero = tbrestaurantes.id_restaurante WHERE tbmeseros.cad_mesero = ?");
$q->bindValue( 1, 'x' );
$q->execute();
print_r( $q->fetchAll( PDO::FETCH_ASSOC );
In prepare you can use '?' and then bindValue to attach an escaped value to the query. Your query doesn't appear to have this and that is the cause of the error.
I am confused.
This is working:
$sql = 'SELECT * FROM TABLE ORDER BY DATEOFUPLOAD DESC';
$stmt = $conn->prepare($sql);
$stmt->execute();
This is not:
$sql = 'SELECT * FROM TABLE ORDER BY DATEOFUPLOAD :orderbydateofupload';
$stmt = $conn->prepare($sql);
$stmt->bindValue(':orderbydateofupload', $orderbydateofupload, PDO::PARAM_STR);
$stmt->execute();
I have checked and set $orderbydateofupload by $orderbydateofupload='DESC', so it's definitely not null.
I get an error to the last line ($stmt->execute()):
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''DESC'' at line 1' in /home/gh6534/public_html/query.php:77 Stack trace: #0 /home/gh6534/public_html/query.php(77): PDOStatement->execute() #1 {main} thrown in /home/gh6534/public_html/query.php on line 77
I also tried to use the column as parameter:
$sort = 'DATEOFUPLOAD';
$sql = 'SELECT * FROM TABLE ORDER BY :sort :orderbydateofupload';
$stmt = $conn->prepare($sql);
$stmt->bindParam(':sort', $sort);
$stmt->bindParam(':orderbydateofupload', $orderbydateofupload);
$stmt->execute();
This does not throw an exception, but all items are queried without any sorting. What's wrong?
Try this
$orderbydateofupload = 'ASC'; //Or DESC
if($orderbydateofupload == 'DESC')
$sql = 'SELECT * FROM TABLE ORDER BY DATEOFUPLOAD DESC';
else
$sql = 'SELECT * FROM TABLE'
You can't bind identifiers with PDO because prepared statements can be used only with data, but not with identifiers or syntax keywords.
So, you have to use whitelisting, as shown in the example I posted before
That's why in my own class I use identifier placeholder, which makes whole code into one line (when you need to set the order by field only):
$data = $db->getAll('SELECT * FROM TABLE ORDER BY ?n',$sort);
but with keywords whitelisting is the only choice:
$order = $db->whiteList($_GET['order'],array('ASC','DESC'),'ASC');
$data = $db->getAll("SELECT * FROM table ORDER BY ?n ?p", $sort, $order);
My site is rather extensive, and I just recently made the switch to PHP5 (call me a late bloomer).
All of my MySQL query's before were built as such:
"SELECT * FROM tablename WHERE field1 = 'value' && field2 = 'value2'";
This made it very easy, simple and friendly.
I am now trying to make the switch to mysqli for obvious security reasons, and I am having a hard time figuring out how to implement the same SELECT * FROM queries when the bind_param requires specific arguments.
Is this statement a thing of the past?
If it is, how do I handle a query with tons of columns involved? Do I really need to type them all out every time?
I could be wrong, but for your question I get the feeling that bind_param() isn't really the problem here. You always need to define some conditions, be it directly in the query string itself, of using bind_param() to set the ? placeholders. That's not really an issue.
The problem I had using MySQLi SELECT * queries is the bind_result() part. That's where it gets interesting. I came across this post from Jeffrey Way: http://jeff-way.com/2009/05/27/tricky-prepared-statements/(This link is no longer active). The script basically loops through the results and returns them as an array — no need to know how many columns there are, and you can still use prepared statements.
In this case it would look something like this:
$stmt = $mysqli->prepare(
'SELECT * FROM tablename WHERE field1 = ? AND field2 = ?');
$stmt->bind_param('ss', $value, $value2);
$stmt->execute();
Then use the snippet from the site:
$meta = $stmt->result_metadata();
while ($field = $meta->fetch_field()) {
$parameters[] = &$row[$field->name];
}
call_user_func_array(array($stmt, 'bind_result'), $parameters);
while ($stmt->fetch()) {
foreach($row as $key => $val) {
$x[$key] = $val;
}
$results[] = $x;
}
And $results now contains all the info from SELECT *. So far I found this to be an ideal solution.
"SELECT * FROM tablename WHERE field1 = 'value' && field2 = 'value2'";
becomes
"SELECT * FROM tablename WHERE field1 = ? && field2 = ?";
which is passed to the $mysqli::prepare:
$stmt = $mysqli->prepare(
"SELECT * FROM tablename WHERE field1 = ? && field2 = ?");
$stmt->bind_param( "ss", $value, $value2);
// "ss' is a format string, each "s" means string
$stmt->execute();
$stmt->bind_result($col1, $col2);
// then fetch and close the statement
OP comments:
so if i have 5 parameters, i could potentially have "sssis" or something (depending on the types of inputs?)
Right, one type specifier per ? parameter in the prepared statement, all of them positional (first specifier applies to first ? which is replaced by first actual parameter (which is the second parameter to bind_param)).
While you are switching, switch to PDO instead of mysqli, It helps you write database agnositc code and have better features for prepared statements.
http://www.php.net/pdo
Bindparam for PDO:
http://se.php.net/manual/en/pdostatement.bindparam.php
$sth = $dbh->prepare("SELECT * FROM tablename WHERE field1 = :value1 && field2 = :value2");
$sth->bindParam(':value1', 'foo');
$sth->bindParam(':value2', 'bar');
$sth->execute();
or:
$sth = $dbh->prepare("SELECT * FROM tablename WHERE field1 = ? && field2 = ?");
$sth->bindParam(1, 'foo');
$sth->bindParam(2, 'bar');
$sth->execute();
or execute with the parameters as an array:
$sth = $dbh->prepare("SELECT * FROM tablename WHERE field1 = :value1 && field2 = :value2");
$sth->execute(array(':value1' => 'foo' , ':value2' => 'bar'));
It will be easier for you if you would like your application to be able to run on different databases in the future.
I also think you should invest some time in using some of the classes from Zend Framwework whilst working with PDO. Check out their Zend_Db and more specifically [Zend_Db_Factory][2]. You do not have to use all of the framework or convert your application to the MVC pattern, but using the framework and reading up on it is time well spent.
Is this statement a thing of the past?
Yes. Don't use SELECT *; it's a maintenance nightmare. There are tons of other threads on SO about why this construct is bad, and how avoiding it will help you write better queries.
See also:
What is the reason not to use select *?
Performance issue in using SELECT *?
Why is using '*' to build a view bad?
You can still use it (mysqli is just another way of communicating with the server, the SQL language itself is expanded, not changed). Prepared statements are safer, though - since you don't need to go through the trouble of properly escaping your values each time. You can leave them as they were, if you want to but the risk of sql piggybacking is reduced if you switch.
you can use get_result() on the statement.
http://php.net/manual/en/mysqli-stmt.get-result.php
I was looking for a nice and complete example of how to bind multiple query parameters dynamically to any SELECT, INSERT, UPDATE and DELETE query. Alec mentions in his answer a way of how to bind result, for me the get_result() after execute() function for SELECT queries works just fine, and am able to retrieve all the selected results into an array of associative arrays.
Anyway, I ended up creating a function where I am able to dynamically bind any amount of parameters to a parametrized query ( using call_user_func_array function) and obtain a result of the query execution. Below is the function with its documentation (please read before it before using - especially the $paremetersTypes - Type specification chars parameter is important to understand)
/**
* Prepares and executes a parametrized QUERY (SELECT, INSERT, UPDATE, DELETE)
*
* #param[in] $dbConnection mysqli database connection to be used for query execution
* #param[in] $dbQuery parametrized query to be bind parameters for and then execute
* #param[in] $isDMQ boolean value, should be set to TRUE for (DELETE, INSERT, UPDATE - Data manipulaiton queries), FALSE for SELECT queries
* #param[in] $paremetersTypes String representation for input parametrs' types as per http://php.net/manual/en/mysqli-stmt.bind-param.php
* #param[in] $errorOut A variable to be passed by reference where a string representation of an error will be present if a FAUILURE occurs
* #param[in] $arrayOfParemetersToBind Parameters to be bind to the parametrized query, parameters need to be specified in an array in the correct order
* #return array of feched records associative arrays for SELECT query on SUCCESS, TRUE for INSERT, UPDATE, DELETE queries on SUCCESS, on FAIL sets the error and returns NULL
*/
function ExecuteMySQLParametrizedQuery($dbConnection, $dbQuery, $isDMQ, $paremetersTypes, &$errorOut, $arrayOfParemetersToBind)
{
$stmt = $dbConnection->prepare($dbQuery);
$outValue = NULL;
if ($stmt === FALSE)
$errorOut = 'Failed to prepare statement for query: ' . $dbQuery;
else if ( call_user_func_array(array($stmt, "bind_param"), array_merge(array($paremetersTypes), $arrayOfParemetersToBind)) === FALSE)
$errorOut = 'Failed to bind required parameters to query: ' . $dbQuery . ' , parameters :' . json_encode($arrayOfParemetersToBind);
else if (!$stmt->execute())
$errorOut = "Failed to execute query [$dbQuery] , erorr:" . $stmt->error;
else
{
if ($isDMQ)
$outValue = TRUE;
else
{
$result = $stmt->get_result();
if ($result === FALSE)
$errorOut = 'Failed to obtain result from statement for query ' . $dbQuery;
else
$outValue = $result->fetch_all(MYSQLI_ASSOC);
}
}
$stmt->close();
return $outValue;
}
usage:
$param1 = "128989";
$param2 = "some passcode";
$insertQuery = "INSERT INTO Cards (Serial, UserPin) VALUES (?, ?)";
$rowsInserted = ExecuteMySQLParametrizedQuery($dbConnection, $insertQuery, TRUE, 'ss', $errorOut, array(&$param1, &$param2) ); // Make sure the parameters in an array are passed by reference
if ($rowsInserted === NULL)
echo 'error ' . $errorOut;
else
echo "successfully inserted row";
$selectQuery = "SELECT CardID FROM Cards WHERE Serial like ? AND UserPin like ?";
$arrayOfCardIDs = ExecuteMySQLParametrizedQuery($dbConnection, $selectQuery, FALSE, 'ss', $errorOut, array(&$param1, &$param2) ); // Make sure the parameters in an array are passed by reference
if ($arrayOfCardIDs === NULL)
echo 'error ' . $errorOut;
else
{
echo 'obtained result array of ' . count($arrayOfCardIDs) . 'selected rows';
if (count($arrayOfCardIDs) > 0)
echo 'obtained card id = ' . $arrayOfCardIDs[0]['CardID'];
}