This question already has answers here:
mysql_fetch_array()/mysql_fetch_assoc()/mysql_fetch_row()/mysql_num_rows etc... expects parameter 1 to be resource
(31 answers)
Closed 8 years ago.
Can someone please help me with my code, I can't get it to work.
I have an html input form where I type for example "This is a sample".
(data is saved in $_POST['Begriff'])
I want to achive a simple translation, so that the table "drinks" in column "English" is checked for existence of every single word from my input sample sentence and output if found every entry from the corresponding row in one line.
Right now I have two problems:
As soon as I add " where English in $wert" to the select statement I get:
Notice: Array to string conversion in nachlesen.php on line 34
Warning: mysql_fetch_assoc() expects parameter 1 to be resource, boolean given
Second Problem: How to I put the sentence together again from the returned results?
(Right now I get the output for every found word below each other, instead of one line)
Here is my code:
if ( $_POST['Begriff'] <> "")
{
$wert = explode(' ',$_POST['Begriff']);
$select = mysql_query ("SELECT * FROM drinks where English in $wert");
while ( $row = mysql_fetch_assoc($select))
{
echo ("$row[German] <br>");
echo ("$row[English]<br>");
}
}
Thanks in Advance, Daniel
<?php
// premise: the user input in $_POST['Begriff'] is a string like 'This is a sample'
//first split it into single words
// preg_split: \s+ -> one or more whitespaces , PREG_SPLIT_NO_EMPTY -> no "empty" words
// e.g. " Mary had a little lamb" -> array('Mary','had','a','little','lamb')
$words = preg_split('!\s+!', $_POST['Begriff'], -1, PREG_SPLIT_NO_EMPTY);
// now encode each string so that it can be used
// safely as a string-literal within your sql query
// see: sql injection
// this should be:
// $words = array_map(function($e) use($mysql) { return mysql_real_escape_string($e, $mysql); }, $words);
// but apparently you're not storing the resource that is returned by mysql_connect
// mysql_real_escape_string() is applied to each single element in $words
// e.g. array("it's", "been") -> array("it\\'s", "been")
$words = array_map('mysql_real_escape_string', $words);
// now put the string literals into your query
// format: ... IN ('x','y','z')
// join(",", $words) gives you x,y,z
// join("','", $words) gives you x','y','z
// i.e. the first and the last ' has to be added "manually"
// keep in mind that for an empty array $words this will produce WHERE ... IN ('')
// better test that before even trying to build the query
$query = sprintf("
SELECT
German,English
FROM
drinks
WHERE
English IN ('%s')
", join("','", $words));
// send the query to the MySQL server
// should be: $result = mysql_query($query, $mysql);
$result = mysql_query($query);
// database query -> failure is always an option
if ( !$result ) {
// add error handling here
}
else {
// in case there is not a single match in the database
// your script would print ...nothing
// I don't like that - but that debatable
// anway: wrapped in a fieldset
echo '<fieldset><legend>results:</legends>';
while( false!==($row=mysql_fetch_array($result, MYSQL_FETCH_ASSOC)) ) {
printf('%s<br />%s<br />',
// just like on the input-side you had to worry about
// sql injections
// on the output side you want to avoid
// that characters from the database can break your html structure
htmlentities($row['German']),
htmlentities($row['English'])
);
}
echo '</fieldset>';
}
(script is untested)
why don't you try implode() and convert your array to string??
if ( $_POST['Begriff'] <> "")
{
//you'l have to replace all "spaces with ',' "
$pattern = '/\s*,\s*/';
$replace = "','";
$wert = preg_replace($pattern, $replace, $_POST['Begriff']);
$select = mysql_query ("SELECT * FROM drinks where English in ('$wert')");
while ( $row = mysql_fetch_assoc($select))
{
echo ("$row[German] <br>");
echo ("$row[English]<br>");
}
}
ANOTHER SOLUTION (TO PREVENT SQL INJECTION)
if ( $_POST['Begriff'] <> "")
{
//replace multiple spaces
$str1 = preg_replace( "/\s+/", " ", $_POST['Begriff'] );
//convert to array, separated by space
$arr=explode(" ",$str1);
$safe_params=array();
foreach($arr as $param){
$safe_params[]=mysql_real_escape_string($param);
}
$wert=implode("','",$safe_params);
$select = mysql_query ("SELECT * FROM drinks where English in ('$wert')");
while ( $row = mysql_fetch_assoc($select))
{
echo ("$row[German] <br>");
echo ("$row[English]<br>");
}
}
EDIT
Processing query output according to language
$german_words=array();
while ( $row = mysql_fetch_assoc($select))
{
$german_words[$row['English']]=$row['Gernam'];
}
//$str1 is having english string
echo "English: ".$str1."<br/>";
echo "German : ";
//$arr is having array of words of $str1
foreach($arr as $eng_word){
echo $german_words[$eng_word]." ";
}
"SELECT * FROM drinks where English in ('". implode("','", $wert) . "')"
EDIT: SQL Injection safe query:
$dsn = 'mysql:dbname=' . $settings['dbname'] . ';host=' . $settings['dbhost'];
$pdo = new PDO($dsn, $settings['dbuser'], $settings['dbpass'], array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
if ( $_POST['Begriff'] <> "")
{
$wert = explode(' ',$_POST['Begriff']);
$placeholders = implode(',', array_fill(0, count($wert), '?'));
$sth = $pdo->prepare("SELECT * FROM drinks WHERE English in ({$placeholders})");
$sth->execute($wert);
$rows = $sth->fetchAll();
foreach($rows as $row) {
print_r( $row );
}
}
Related
I have a code in php it takes a well formatted string such as 'field,operator,value' and produces a WHERE statement to MySQL database query.
if the two fields names below end with the same characters such as '*id' such as 'id' and 'classid' it produces strange behavior. such as the following:
$where = $_GET['where'];
$tokens = multiexplode(array("^", "~", "(", ")"), $where);
$where = str_replace("^", " AND ", $where);
foreach ($tokens as $item) {
if (!empty($item)) {
$where = str_replace($item, getOperand($item), $where);
}
}
echo 'WHERE '.$where;
function multiexplode($delimiters, $string)
{
$unifydelimters = str_replace($delimiters, $delimiters[0], $string);
$conditions = explode($delimiters[0], $unifydelimters);
return $conditions;
}
function getOperand($item)
{
$extokens = explode (",", $item);
switch (trim($extokens[1])) {
case 'eq':
return trim($extokens[0]) . " = '" . trim($extokens[2]) . "' ";
break;
default:
return "";
break;
}
}
tested with :
http://localhost/test/test.php?where=id,eq,1^classid,eq,19
ALways show: id = '1' AND classid='1' 9
Not: id = '1' AND classid='19'
But if any other field ends differently from the other such as:
http://localhost/test/test.php?where=id,eq,1^class,eq,19
It correctly shows: id = '1' AND class='19'
Any idea why this is happening??
Thanks,
The problem is that when you search for the first expression id,eq,1 for the replacement in the string
id,eq,1^classid,eq,19
You will find two positions:
id,eq,1^classid,eq,19
^ ^
id,eq,1 |
id,eq,1
This means you will do two replacements, even though you wanted only replace one.
To solve this problem you don't need to work with the original input string $where. Instead you can use the already create array in $tokens and change the individual array elements. You can use array_map() to do that, like this:
$changed = array_map('getOperand', $tokens);
Then you can put the array together to a string with ' AND ' as the separator:
$result = implode(' AND ', $changed);
This will finally generate the following result:
id = '1' AND classid = '19'
Keep in mind that you should use prepared statements to avoid SQL injections, see How can I prevent SQL injection in PHP?
I have a databse table with 100K rows and an array of 100 items. And I need to find if an array item is found in my Users table username row.
My database table Users
| id | username | fullname |
1 John John Smith
2 Elliot Jim Elliot
3 Max Max Richard
My array looks like this
[
{
string: 'Hello, this is Elliot from downtown Las Vegas!'
},
{
string: 'Hey how are you?'
}
]
My idea was to do a foreach loop through every row in my Users table (100k records) and find if it matches in my array, but it is so slow.
foreach ($MyArray as $Array) {
foreach ($dbrows as $dbrow) {
if (strpos($Array['string'], $dbrow['username']) !== false) {
echo 'found it!';
break;
}
}
}
It will be a bit hit and miss as you may find users with all sorts of weird names that match normal words, this approach splits the input into words and then uses them to form an in clause to search the database. So it only looks at records that match rather than all records...
$search = 'Hello, this is Elliot from downtown Las a1 Vegas!';
$words = str_word_count($search, 1);
$bind = str_repeat("?,", count($words));
$bind = trim($bind, ",");
$query = $conn->prepare("select * from users where username in ($bind)" );
$types = str_repeat("s", count($words));
$query->bind_param($types, ...$words);
$query->execute();
$res = $query->get_result();
while($row = $res->fetch_assoc()) {
// Process result
}
It also uses prepared statements, which is where all of the $bind and $types processing comes in. If you look at $query you will see how it's built up.
I think the better way was to separate your search arrays into words, and use it in the query, like:
<?php
// Assuming your search array is $search...
$words = array ();
foreach ( $search as $text)
{
$words = array_merge ( $words, explode ( " ", trim ( preg_replace ( "/[^0-9a-z]+/i", " ", $text))));
}
$words = array_unique ( $words);
$in = "";
foreach ( $words as $text)
{
$in .= ",'" . $mysqli->real_escape_string ( $text) . "'";
}
if ( ! $result = $mysqli->query ( "SELECT * FROM `Users` WHERE `username` IN (" . substr ( $in, 1) . ")"))
{
echo "MySQL error!";
}
// Results at $result
?>
You can use regular expressions:
<?php
$query_string = "bla bla bla...";
$qry = $mysqli_query($conn, "SELECT *FROM table WHERE username REGEXP '$query_string'");
?>
Regular expression matches data individually from table.
i wrote the following code:
<?php
$listO = $_POST["letter"];
//print_r($listO);
//Array ( [0] => A [1] => B [2] => C)
function to_pg_array($set) {
settype($set, 'array'); // can be called with a scalar or array
$result = array();
foreach ($set as $t) {
if (is_array($t)) {
$result[] = to_pg_array($t);
} else {
$t = str_replace('"', '\\"', $t); // escape double quote
if (! is_numeric($t)) // quote only non-numeric values
$t = '"' . $t . '"';
$result[] = $t;
}
}
return '{' . implode(",", $result) . '}'; // format
}
$pg_array_listO = to_pg_array($listO);
//print_r($pg_array_list_organisms);
//{"A","B","C"}
$conn = pg_connect("host=X dbname=Y user=Z");
$result = pg_query_params($conn, 'SELECT count(cp.id)
FROM cp, act, a, t
WHERE t.tid = a.tid AND
a.aid = act.aid AND
act.m = cp.m AND
t.n = $1 AND
act.st = $2 AND
t.o LIKE ANY(ARRAY[$3])', array($t1, $a2, $pg_array_listO));
while($row = pg_fetch_row($result)) {echo $row[0];}
?>
However i can't figure out how to pass the array $pg_array_listO to the postgres query. The function to_pg_array converts the php array into postgres array but still don't work. How can i do this?
postgres array looks like '{list}' :
t=# select array['a','b','c'];
array
---------
{a,b,c}
(1 row)
so you need to get rid of double quotes, otherwise postgres understands literals as identities.
Eg with $pg_array_listO = str_replace('"', '\\"',to_pg_array($listO)) or smth smarter - sorry - I'm not good in php
additionally modify ANY(ARRAY[$3]) to ANY('$3'::text[]), cos array[] or '{}'::text[] would be accepted
update
based on
//print_r($pg_array_list_organisms);
//{"A","B","C"}
I expect this to work:
$result = pg_query_params($conn, "SELECT count(cp.id)
FROM cp, act, a, t
WHERE t.tid = a.tid AND
a.aid = act.aid AND
act.m = cp.m AND
t.n = $1 AND
act.st = $2 AND
t.o LIKE ANY($3)", array($t1, $a2, str_replace('"', '',to_pg_array($listO))));
mind I changed quotes and SQL and str_replace for $3 variable
a working example of this approach:
t=# select 'a' like any('{a,b,c}'::text[]);
?column?
----------
t
(1 row)
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
How to sort the results of this code?
Im making a search feature which allows a user to search a question and it will show the top 5 best matching results by counting the number of matching words in the question.
Basically I want the order to show the best match first which would be the question with the highest amount of matching words.
Here is the code I have.
<?php
include("config.php");
$search_term = filter_var($_GET["s"], FILTER_SANITIZE_STRING); //User enetered data
$search_term = str_replace ("?", "", $search_term); //remove any question marks from string
$search_count = str_word_count($search_term); //count words of string entered by user
$array = explode(" ", $search_term); //Seperate user enterd data
foreach ($array as $key=>$word) {
$array[$key] = " title LIKE '%".$word."%' "; //creates condition for MySQL query
}
$q = "SELECT * FROM posts WHERE " . implode(' OR ', $array); //Query to select data with word matches
$r = mysql_query($q);
$count = 0; //counter to limit results shown
while($row = mysql_fetch_assoc($r)){
$thetitle = $row['title']; //result from query
$thetitle = str_replace ("?", "", $thetitle); //remove any question marks from string
$title_array[] = $thetitle; //creating array for query results
$newarray = explode(" ", $search_term); //Seperate user enterd data again
foreach($title_array as $key => $value) {
$thenewarray = explode(" ", $value); //Seperate each result from query
$wordmatch = array_diff_key($thenewarray, array_flip($newarray));
$result = array_intersect($newarray, $wordmatch);
$matchingwords = count($result); //Count the number of matching words from
//user entered data and the database query
}
if(mysql_num_rows($r)==0)//no result found
{
echo "<div id='search-status'>No result found!</div>";
}
else //result found
{
echo "<ul>";
$title = $row['title'];
$percentage = '.5'; //percentage to take of search word count
$percent = $search_count - ($search_count * $percentage); //take percentage off word count
if ($matchingwords >= $percent){
$finalarray = array($title => $matchingwords);
foreach( $finalarray as $thetitle=>$countmatch ){
?>
<li><?php echo $thetitle ?><i> <br />No. of matching words: <?php echo $countmatch; ?></i></li>
<?php
}
$count++;
if ($count == 5) {break;
}
}else{
}
}
echo "</ul>";
}
?>
When you search something it will show something like this.
Iv put the number of matching words under each of the questions however they are not in order. It just shows the first 5 questions from the database that have a 50% word match. I want it to show the top 5 with the most amount of matching words.
What code would I need to add and where would I put it in order to do this?
Thanks
Here's my take on your problem. A lot of things have been changed:
mysql_ functions replaced with PDO
usage of anonymous functions means PHP 5.3 is required
main logic has been restructured (it's really hard to follow your result processing, so I might be missing something you need, for example the point of that $percentage)
I realize this might look complicated, but I think that the sooner you learn modern practices (PDO, anonymous functions), the better off you will be.
<?php
/**
* #param string $search_term word or space-separated list of words to search for
* #param int $count
* #return stdClass[] array of matching row objects
*/
function find_matches($search_term, $count = 5) {
$search_term = str_replace("?", "", $search_term);
$search_term = trim($search_term);
if(!strlen($search_term)) {
return array();
}
$search_terms = explode(" ", $search_term);
// build query with bind variables to avoid sql injection
$params = array();
$clauses = array();
foreach ($search_terms as $key => $word) {
$ident = ":choice" . intval($key);
$clause = "`title` LIKE {$ident}";
$clauses []= $clause;
$params [$ident] = '%' . $word . '%';
}
// execute query
$pdo = new PDO('connection_string');
$q = "SELECT * FROM `posts` WHERE " . implode(' OR ', $clauses);
$query = $pdo->prepare($q);
$query->execute($params);
$rows = $query->fetchAll(PDO::FETCH_OBJ);
// for each row, count matches
foreach($rows as $row) {
$the_title = $row->title;
$the_title = str_replace("?", "", $the_title);
$title_terms = explode(" ", $the_title);
$result = array_intersect($search_terms, $title_terms);
$row->matchcount = count($result);
}
// sort all rows by match count descending, rows with more matches come first
usort($rows, function($row1, $row2) {
return - ($row1->matchcount - $row2->matchcount);
});
return array_slice($rows, 0, $count);
}
?>
<?php
$search_term = filter_var($_GET["s"], FILTER_SANITIZE_STRING);
$best_matches = find_matches($search_term, 5);
?>
<?php if(count($best_matches)): ?>
<ul>
<?php foreach($best_matches as $match): ?>
<li><?php echo htmlspecialchars($match->title); ?><i> <br/>No. of matching words: <?php echo $match->matchcount; ?></i></li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<div id="search-status">No result found!</div>
<?php endif; ?>
Try adding asort($finalarray); after your $finalarray = array($title => $matchingwords); declaration:
...
if ($matchingwords >= $percent){
$finalarray = array($title => $matchingwords);
asort($finalarray);
....
It should sort your array Ascending by the Values
How can I take a string business, jquery, css and explode that string and check a mySQL database to see if each one of the single words is already inside a database entry?
Thanks,
Drummer392
$string = "business, jquery, css";
$exploded = explode(",", $string);
$result = /* database select query */
foreach ($exploded as $value) {
// $value contains the value being processed
// compare $result to $value and do what's needed
}
PHP Manual: explode()
Hope that give you an idea as to what you need to do.
Edit: thanks to Chris for the suggestion of doing the database query first
$conn = mysql_connect("localhost", "mysql_user", "mysql_password");
mysql_select_db("database", $conn);
$string = "business, query, css";
$array = explode(", ", $string);
foreach($array as $str){
$result = mysql_query("SELECT * FROM tableName WHERE columnName='$str'", $conn);
$num_rows = mysql_num_rows($result);
if($num_rows > 0)
//found
else
//not found
}
Use PHP's explode function with a ", " delimiter, assigning to a new array variable.
I would improve upon the previous answer, I feel it would be better to use the SELECT query outside of the foreach loop. Then you'll avoid executing the same query 3 times.
$result = /* database select query */
foreach ($exploded as $value) {
// compare $result to $value and do what's needed
}