This question already has answers here:
mysqli/mysql query inside function not working [duplicate]
(2 answers)
Closed 9 years ago.
I'm trying to load some data from a database using PHP, but for some reason it doesn't work when I put it inside a function. If I try the code without a function, it works fine:
//$dbc connection
$call1 = 0;
$output = '';
$query = "select * from artists order by lname limit $call1, 15";
$result = mysqli_query($dbc, $query);
while($row = mysqli_fetch_array($result)){
$output .= "<ul>";
$output .= "<li>" . $row['name'] . "</li>";
$output .= "</ul>";
}
However, when I change the code to be inside a function, I don't get anything from the database (or at least it won't return anything):
//$dbc connection
$call1 = 0;
$output = '';
function loadArtists($call){
$query = "select * from artists order by lname limit $call, 15";
$result = mysqli_query($dbc, $query);
while($row = mysqli_fetch_array($result)){
$output .= "<ul>";
$output .= "<li>" . $row['name'] . "</li>";
$output .= "</ul>";
}
}
loadArtists($call1);
What am I doing wrong here?
You cannot use $dbc in your function, because it is a global variable.
You can use either
function loadArtists($call){
global $dbc;
...
}
to make $dbc known to loadArtists() or pass it as a second parameter
function loadArtists($dbc, $call){
...
}
and call it as
loadArtists($dbc, $call1);
As I mentioned in one of my comments, using global to fix the scope of your connection is poor practice. The correct way to pass your connection is like so:
$dbc = mysqli_connect("localhost", "my_user", "my_password", "world");
$call1 = 0;
$output = '';
function loadArtists($call, $dbc){
$query = "select * from artists order by lname limit $call, 15";
$result = mysqli_query($dbc, $query);
while($row = mysqli_fetch_array($result)){
$output .= "<ul>";
$output .= "<li>" . $row['name'] . "</li>";
$output .= "</ul>";
}
}
loadArtists($call1, $dbc);
Declaring your username and password on the same page as the code you're executing every time you want to make a DB connection is bad practice because:
You could potentially have more than one page to edit if you move to a different host or a different environment than the dev environment.
If you declare it outside of the root you can limit access to the DB password from FTP accounts.
I like to use a function for the connection so this way if the connection closes you can reopen it at will (reducing server overhead). Also you don't have to set it as a global var inside the function (not a good idea because of several reasons).
So for those reasons, this connection should be outside (below) the root.
/../safe/connection.php
function openSQL() {
$conn = mysqli('localhost', 'my_user', 'my_password', 'my_db');
return $conn;
}
functions.php
require_once($_SERVER['DOCUMENT_ROOT'].'/../safe/connection.php');
function loadArtists($call){
$dbc = openSQL();
$query = "select * from artists order by lname limit $call, 15";
$result = mysqli_query($dbc, $query);
while($row = mysqli_fetch_array($result)){
$output .= "<ul>";
$output .= "<li>" . $row['name'] . "</li>";
$output .= "</ul>";
}
mysqli_close($dbc);
return $output;
}
$myOutput = loadArtists(4);
The problem is variable scope. That variable does not exist within your function.
There are three ways to deal with that:
Make it global, that means an outside variable is readible from within a function. (Note that using global variables is often considered a security concern.)
global $dbc;
You can pass that variable into the function as an argument
function loadArtists($connection, $call) { ... }
you can make a class and that class variable will now be useable inside of class functions:
class Artists {
public $dbc;
public function __construct() {
$this->dbc = open_the_db_connection(); //etc?
}
public function loadArtists($call) {
$query = "select * from artists order by lname limit $call, 15";
$result = mysqli_query($this->dbc, $query);
while($row = mysqli_fetch_array($result)){
$output .= "<ul>";
$output .= "<li>" . $row['name'] . "</li>";
$output .= "</ul>";
}
return $output;
}
}
It looks like a scoping issue to me. The $output you reference in the function isn't the same as the $output you defined outside the function.
You should change your function to the following:
function loadArtists($call){
$output = "";
$query = "select * from artists order by lname limit $call, 15";
$result = mysqli_query($dbc, $query);
while($row = mysqli_fetch_array($result)){
$output .= "<ul>";
$output .= "<li>" . $row['name'] . "</li>";
$output .= "</ul>";
}
return $output;
}
$output = loadArtists($call1);
Related
I was experimenting if I could use a mySQL database to store CSS settings. I set up a simple database "colors" with one table "color" that had simple structure tag and color columns. In that, one row is h1 => red.
<?php
//function to dynamically change CSS
$tag = 'h1';
$q = "SELECT * FROM `colors` WHERE `tag`='" . $tag . "'" ;
echo $q . "<br>";
$query = mysqli_query($link, $q);
if ($row = mysqli_fetch_assoc($query))
{
echo $row['color'];
} else
{
echo "error - no such tag";
}
?>
When I tried to convert to a function, the code does not work at all.
<?php
//function to dynamically change CSS
function getCSS($tag)
{
$tag = 'h1';
$q = "SELECT * FROM `colors` WHERE `tag`='" . $tag . "'" ;
echo $q . "<br>";
$query = mysqli_query($link, $q);
if ($row = mysqli_fetch_assoc($query))
{
echo $row['color'];
} else
{
echo "error - no such tag";
}
}
getCSS('h1');
?>
Help please?
My guess is that in
$query = mysqli_query($link, $q);
$link goes out of scope and is empty. You should pass it to the function as well.
For the record: using $tag without escaping could be an sql injection attack possibility.
in function, there is no $link, you shoud define it as a global variable.
At the start of your function add a reference to your global DB link:
function getCSS($tag) {
global $link;
...
This should work:
<?php
$link = mysqli_connect('server_host', 'user', 'password', 'database') OR die('Could not connect because: '.mysqli_connect_error());
//function to dynamically change CSS
function getCSS($link, $tag){
$q = 'SELECT * FROM colors WHERE tag = "' . $tag . '"' ;
$r = mysqli_query($link, $q);
if(mysqli_num_rows($r)>0){ // check if there are results
while($row = mysqli_fetch_assoc($r)){
//echo '<pre>';
//print_r($row); // print the result array for debugging
//echo '</pre>';
echo $row['color'] . '<br />';
}
return $row;
} else { // if no result is found
echo 'No such tag';
}
}
// test it:
echo '<br />if tag is h1<br />';
getCSS($link, 'h1');
echo '<br />if tag is h2<br />';
getCSS($link, 'h2');
?>
When i would search for the keywords that i have specified in my database it will return everything from my database not just the corresponding links that have the keywords attached to the link. here is my code
<?php
$q = $_GET['q'];
$terms = explode(" ", $q);
$query = "SELECT * FROM search ";
foreach ($terms as $each){
$i=0;
$i++;
if ($i == 1)
$query .= "keywords LIKE '%$each%' ";
else
$query .= "OR keywords LIKE '%$each%' ";
}
//connect
mysql_connect("localhost", "root", "");
mysql_select_db("search");
$query = mysql_query("SELECT * FROM search");
$numrows = mysql_num_rows($query);
if ($numrows > 0){
while($row = mysql_fetch_assoc($query)){
$id = $row['id'];
$title = $row['title'];
$description = $row['description'];
$keywords = $row['keywords'];
$link = $row['link'];
echo "<h3><a href='$link'>$title</a></h3><h4>$link</h4>$description<br /><br />";
}
}
else
echo "<b>No Results Found</b><br><br>Suggestions:<br>
Make sure all words are spelled correctly.<br>
Try different keywords.<br>
Try more general keywords.";
//disconnect
mysql_close();
?>
<?php
$q = $_GET['q'];
$terms = explode(" ", $q);
//connect
mysql_connect("localhost", "root", "");
mysql_select_db("search");
$query = "SELECT * FROM search ";
$i=1;
foreach ($terms as $each){
if ($i == 1) {
$query .= "WHERE ";
$query .= "keywords LIKE '" . mysql_real_escape_string("%" . $each . "%") . "' ";
} else {
$query .= "OR keywords LIKE '" . mysql_real_escape_string("%" . $each . "%") . "' ";
}
$i++;
}
$query = mysql_query($query);
$numrows = mysql_num_rows($query);
if ($numrows > 0){
while($row = mysql_fetch_assoc($query)){
$id = $row['id'];
$title = $row['title'];
$description = $row['description'];
$keywords = $row['keywords'];
$link = $row['link'];
echo "<h3><a href='$link'>$title</a></h3><h4>$link</h4>$description<br /><br />";
}
} else {
echo "<b>No Results Found</b><br><br>Suggestions:<br>
Make sure all words are spelled correctly.<br>
Try different keywords.<br>
Try more general keywords.";
}
//disconnect
mysql_close();
?>
Fixes:
1) Removed second $query that was being defined. It selected all rows.
2) Moved initial $i declaration. It was being set back to 0 each loop.
3) Added WHERE
4) Moved $i++ after the if statement and set initial $i to 1.
5) Added mysql_real_escape_string so that data is escaped properly.
Recommendations:
I highly recommend taking a look at MySQLi (http://us2.php.net/mysqli) or PDO (http://us3.php.net/pdo)
Please let me know if this works or if you need further assistance.
A first sight, i see a couple of errors.
$i=0;
$i++;
if ($i == 1)
$i Will ALWAYS be one are.
you might want to move $i = 0; BEFORE the foreach
$query = mysql_query("SELECT * FROM search");
You build a query, but in the end you're not using it. you probably want to do : $query = mysql_query($query); instead. ( and also for code clarity using a different variable name for the output ? ) .
mysql_query is deprecated. Useless you're in a hurry, check PDO
First, you're missing the WHERE keyword before the conditions. So it should be:
foreach ($terms as $i => $each){
$each = mysql_real_escape_string($each); // Prevent SQL injection
if ($i == 0)
$query .= "WHERE keywords LIKE '%$each%' ";
else
$query .= "OR keywords LIKE '%$each%' ";
}
You don't need to increment your own counter variable, you can use the array indexes from $terms.
Second, after all that work to create $query, you're not using it. You wrote:
$query = mysql_query("SELECT * FROM search");
That should be:
$query = mysql_query($query);
BTW, it's generally a bad idea to reuse variables like that, it gets confusing when you use the same variable for different things. I suggest you call the second $query something like $results.
Change this line
$query .= "keywords LIKE '%$each%' ";
By
$query .= " Where keywords LIKE '%$each%' ";
And also cnhange this line
$query = mysql_query("SELECT * FROM search");
By
$query = mysql_query($query);
Need to pass through an argument for column header in to function.
Would like to have ["name"] be an argument in the function so I can pull different fields from sql, Can you please help. Thank you.
Here is the function:
function read_pages_array_2 () {
global $connection;
$query = "SELECT * ";
$query .= "FROM pages ";
$query .= "ORDER BY id ASC";
$result = mysqli_query ($connection, $query);
confirm_query ($result);
while($result_use = mysqli_fetch_assoc($result)) {
echo $result_use["name"] . "<br/>";
}
}
function read_pages_array_2($columnName) {
global $connection;
$query = "SELECT p.".$columnName." FROM pages p ORDER BY id ASC";
$result = $connection->query($query); // Object Oriented use of connection
confirm_query($result);
while ($result_use = $result->fetch_assoc()) {
echo $result_use[$columnName] . "<br/>";
}
Yes?
OP asked
Looking for ["name"] to be an argument, so I can change when using
function and instead of name, get ["page_id"] or whatever else.
function read_pages_array_2 ($param) {
global $connection;
$query = "SELECT * ";
$query .= "FROM pages ";
$query .= "ORDER BY id ASC";
$result = mysqli_query ($connection, $query);
confirm_query ($result);
while($result_use = mysqli_fetch_assoc($result)) {
echo $result_use[$param] . "<br/>";
}
}
read_pages_array_2("name");
read_pages_array_2("pageID");
Isn't this straight forward?
Hello im learning so im sorry if this is a fool question. (also sorry about my bad english)
Im trying to display the items from a particular category.
In my Database, i have set my categories like this.
And the Products or Items like this,
Im using this code to display tree categories.
function hasChild($parent_id)
{
$sql = "SELECT COUNT(*) as count FROM category WHERE parent_id = '" . $parent_id . "'";
$qry = mysql_query($sql);
$rs = mysql_fetch_array($qry);
return $rs['count'];
}
function CategoryTree($list,$parent,$append)
{
$list = '<li>'.$parent['name'].'</li>';
if (hasChild($parent['id'])) // check if the id has a child
{
$append++;
$list .= "<ul class='child child".$append."'>";
$sql = "SELECT * FROM category WHERE parent_id = '" . $parent['id'] . "'";
$qry = mysql_query($sql);
$child = mysql_fetch_array($qry);
do{
$list .= CategoryTree($list,$child,$append);
}while($child = mysql_fetch_array($qry));
$list .= "</ul>";
}
return $list;
}
function CategoryList()
{
$list = "";
$sql = "SELECT * FROM category WHERE (parent_id = 0 OR parent_id IS NULL)";
$qry = mysql_query($sql);
$parent = mysql_fetch_array($qry);
$mainlist = "<ul class='parent'>";
do{
$mainlist .= CategoryTree($list,$parent,$append = 0);
}while($parent = mysql_fetch_array($qry));
$list .= "</ul>";
return $mainlist;
}
But i cant find a good way to convert the categories in links, so each time a users clic one category i will display the items for that category..
What would be the best for that.
If you can point me in the right direction, some tutorial, or something, would be really , really great.
It sounds like you are looking for some sort of java tree viewer, like this example?
http://dftree.sourceforge.net/dftree/example.html
There are several open source options for this (I have no experience of the one I list above, I just use it as an example). I'm sure I have used a tree viewer in the past that took a list format like you are using - I suggest you have a search around sourceforge.
Your question is not foolish, but is quite long... and many of us are quite lazy :-)
Ok i solve this
This is the code for the page with the menu and categories
<?php
function hasChild($parent_id)
{
$sql = "SELECT COUNT(*) as count FROM category WHERE parent_id = '" . $parent_id . "'";
$qry = mysql_query($sql);
$rs = mysql_fetch_array($qry);
return $rs['count'];
}
function CategoryTree($list,$parent,$append)
{
$productpage = "index.php";
$list = '<li><a href='.$productpage.'?'.'cat='.$parent['id'].'>'.$parent['name'].'</a></li>';
if (hasChild($parent['id'])) // check if the id has a child
{
$append++;
$list .= "<ul class='child child".$append."'>";
$sql = "SELECT * FROM category WHERE parent_id = '" . $parent['id'] . "'";
$qry = mysql_query($sql);
$child = mysql_fetch_array($qry);
do{
$list .= CategoryTree($list,$child,$append);
}while($child = mysql_fetch_array($qry));
$list .= "</ul>";
}
return $list;
}
function CategoryList()
{
$list = "";
$sql = "SELECT * FROM category WHERE (parent_id = 0 OR parent_id IS NULL)";
$qry = mysql_query($sql);
$parent = mysql_fetch_array($qry);
$mainlist = "<ul class='parent'>";
do{
$mainlist .= CategoryTree($list,$parent,$append = 0);
}while($parent = mysql_fetch_array($qry));
$list .= "</ul>";
return $mainlist;
}
?>
And the code for the product page
<?php
$producto = mysql_escape_string($_GET['producto']);
$tablename = "productos";
$res = mysql_query("SELECT * FROM `$tablename` WHERE `id` = '$producto'");
$row = mysql_fetch_assoc($res);
$uid = $row["id"];
$titulo = $row["titulo"];
$descripcion = $row["descripcion"];
$modelo = $row["modelo"];
$img = $row["img"];
// echo the output to browser or compound an output variables here
echo "ID = $uid
<br />Titulo = $titulo
<br>Descripcion = $descripcion
<br>Modelo = $modelo
<br>Imagen = <img src=\"../admin/$img\" width=\"40px\" height=\"40px\" >
<hr />";
?>
I have a simple function to SELECT from MySQL:
function dbSelect($query) {
$db = db(); // refers to a database connect function
$result = mysqli_query($db, $query);
while ($row = mysqli_fetch_array($result)) {
echo $row['f_name'] . ' : ' . $row['s_name'] . '</br>';
}
}
as you can see it accepts the $query var which would be:
$query = "SELECT * FROM user"; // or whatever
What I would like to do is pass the line:
echo $row['f_name'] . ' : ' . $row['s_name'] . '</br>';
as an arg in the function call, eg:
function dbSelect($query, $display)
and the $display be something like (which I would echo out under the while statement):
$display = $row['f_name'] . " : " . $row['s_name'] . "</br>";
The above line will give an undefined variable error, I know why.
How would I go about passing the $display to the function or defining it correctly?
ps. I know there is not any error checking, I'm just trying to figure this out, will add that later. :-)
Thanks for any help
Try this, to maintain separation from program logic to program output:
// some configuration file you include
$db = db(); // refers to a database connect function
// some common functions file
function dbSelect($query)
{
global $db;
$result = mysqli_query($db, $query);
return $result;
}
// output script
$records = dbSelect('SELECT * FROM somewhere');
// loop until cannot fetch any more rows from the record set
while ($row = mysqli_fetch_array($records))
{
echo $row['f_name'] . ' : ' . $row['s_name'] . '</br>';
}
Personally I would pass a template name into the function and have the template stored somewhere as a snippet of html which has standard replacement vars
So you may have something like this (note this won't work out the box will need some fiddling but its the concept)
define TEMPLATE_NAME = "<tr><td>%COL1%</td><td>%COL2</td></tr>";
$colstospitout = array('COL1'=>'f_name','COL2'=>'s_name');
function dbSelect($query,$reportcols,$templatename) {
while ($row = mysqli_fetch_array($result))
{
$template = str_replace("%COL1%",$reportcols['COL1'],$templatename);
$template = str_replace("%COL2%",$reportcols['COL2'],$templatename);
echo $template;
}
}
dbSelect($inputquery,$colstospitout,TEMPLATE_NAME);
There are two ways to do it. The proper way to do it would be to have this function only run the query and return the results. You could make another function that outputs the results. This way you have a clear separation of logic in your code.
However, if you know that you want it done in this way, something like this should work:
function dbSelect($query, $format) {
$db = db();
$result = mysqli_query($db, $query);
while ($row = mysqli_fetch_array($result))
{
echo preg_replace_callback("/\{\{\s*(\w+)\s*\}\}/", function($matches) use ($row) { $column = trim($matches[1]); return isset($row[$column]) ? $row[$column] : $matches[0]; }, $format);
}
}
Where the arguments could look something like:
dbSelect("SELECT * FROM user", "{{ f_name }} {{ s_name }}");
You can't pass it the way that you're passing it because $row doesn't exist when you call the function (because it gets defined inside of the function). In addition, your variables in would be evaluated once when the function is called, not each time in the while loop.
And before anyone makes a "suggestion": eval is not an option.