I'm currently trying to create a function where I can control what field and what values get pulled. This is something I had in mind, but it doesn't work. I get no error, it returns an empty array.
public function test ($field, $id) {
$sql = $this->con->prepare("SELECT ? FROM Content WHERE id=?");
$sql->bindParam(1, $field);
$sql->bindParam(2, $id);
$sql->execute();
while ($row = $sql->fetch()) {
echo $row;
}
}
I'm unsure about the "SELECT ?..." part I'm not 100% sure that is the correct way. The basic idea is I can make a call anywhere like:
< ?php $obj = new handler; $obj->test($_GET['Title'], $_GET['id']); ?> which will echo the Title with the correct id.
the way prepared statements work is that the quesry is prepared and then the data for the fields is sent. Because the first '?' refers to an actual part of query it can not be prepared.
Workarounds:
a) Fetch the whole row and return just the field you need
$this->con->prepare("SELECT * FROM Content WHERE id=?");
//.......
return $row->$field;
b) Insert the field raw into the query (you can use quotes though)
$this->con->prepare("SELECT `{$field}` FROM Content WHERE id=?");
Also if you intend to use it like the way you described it is possible that you be making a whole lot of dduplicate calls to the database
Related
My question is that I use mysqli in class function. I want to be able to return $stmt and use it, so that I can separate a lot of php from my html.
Here is my first bit of code, which is in the class of ticket
public function listTickets(){
$query = "SELECT `subject` FROM `tickets` WHERE `test_id`=?";
$stmt = $this->db->prepare($query);
$stmt->bind_param('i',$_SESSION['data']);
$stmt->execute();
$stmt->bind_result($subject);
return $stmt;
}
Then I call it like this from another file, but of course this does not work, because for some reason my class function is not returning a binded $stmt. However there is no error.
$stmt=$ticket->listTickets();
while($stmt->fetch())
{
echo '<pre>'.$subject.'</pre>';
}
However if I bind it after returning it works, which is annoying because I have already binded it in my function.
$stmt=$ticket->listTickets();
$stmt->bind_result($subject);
while($stmt->fetch())
{
echo '<pre>'.$subject.'</pre>';
}
So binding after returning works, but I would rather returned the binded $stmt so I can have less code cluttering up my html.
I know there are various ways of returning output from a mysqli call like loading it into arrays and stuff, but I was trying to do it with as less code as possible (and please nobody suggest pdo.)
So my question is how do I return a binded $stmt from my function without having to bind it after returning?
Ok going to add a little more. My mysqli is working correctly as when I do this inside the function it works ok
while($stmt->fetch())
{
echo '<pre>'.$subject.'</pre>';
}
$subject is not defined in the listTickets() method. Variables inside the method scope is not visible outside of the method. I think the last code you wrote is the best approach.
Seeing as nobody could give me a satisfactory answer I painstakenly found my own answer. It was nothing to do with scope.
Actually I have two answers and they both work. In the new answer I don't have to bind my variables, because I am using either fetch_assoc, or fetch_object.
So here is my answer
public function listTickets(){
$query = "SELECT `subject` FROM `tickets` WHERE `test_id`=?";
$stmt = $this->db->prepare($query);
$stmt->bind_param('i',$_SESSION['data']);
$stmt->execute();
$result = $stmt->get_result();
$stmt->close();
return $result;
//Notice I am not binding at all, and instead of returning $stmt, I am returning $result.
}
Ok the code above is the same for both answers, but in my other file I can do it two different ways.
Here is the first way, which outputs an object
$result=$ticket->listTickets();
while($row = $result->fetch_object()){
echo $row->subject;
}
And here is the second way, which outputs an associative array
$result=$ticket->listTickets();
while($row = $result->fetch_assoc()){
echo $row['subject'];
}
The difference is that the first one uses an object and the second one uses an associative array.
It took me many hours to work this out, but I am happy I actually worked it out on my own.
I am trying to find a way to create a function in PHP that will wrap a SQL query given in the parameter so that I can prevent SQL Injection in the function that can then be called many times throughout my application. Rather than repeating the same statements for each and every query.
For example say I have the following PHP code that prepares and executes a query to prevent SQL injection:
$name = "$_POST['name']";
$stmt = $db->prepare('SELECT * FROM test_table WHERE test_name = ?');
$stmt->execute(array($name));
For each query my application will need to make these statements will need to be repeated. I want a way to prevent having to do this each time, rather I would simply want to call a function each time and pass in the query.
How would I wrap this in a function that can then be called whenever I need to make a query in my application, given that I do not know in advance the amount of parameters that would need to be parameterized. The above query has one parameterized query, but each query may have a different amount.
Note:
I am using PDO statements
Something like this:
public function query($query)
{
// statements here
}
Where the query is passed in as a parameter.
Does anyone know how I can achieve this?
Currently, I am using something like this that might work for you.
Example:
function superQuery($query, $params, $type = null) {
$pdo = new pdo(...);
$stmt = $pdo->prepare($query);
$stmt->execute($params);
if ($type === "select") {
$result = $stmt->fetchAll();
return $result;
} else {
return $stmt;
}
$query = "SELECT row FROM column WHERE row1 = ? AND row2 = ?";
$params = [$row1, $row2];
$type = "select";
$row = selectQuery($query, $params, $type);
// returns multidimensional array or true/false depending if argument is used //
There's lots of ways you can do it. You could also pass a count argument if you wanted to return a count instead of a result set. But hopefully this points you in the right direction and gives you some ideas.
This has been driving me crazy, the issue is I cannot work out How i can get and set the cached data to be displayed within my view.
public function get_something($id, $account_name)
{
$sql = "SELECT one,two,three FROM table WHERE id = ? and account_name = ? ";
$key = md5("SELECT one,two,three FROM table WHERE id = $id and account_name = $account_name ");
$get_result = $this->Core->Core->Memcache->get($key);
if($get_result)
{
// How would I set the Data
}
else
{
$stmt = $this->Core->Database->prepare($sql);
$stmt->bind_param("is", $id, $account_name);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($one, $two, $three);
$stmt->fetch();
//Below is how i set the data
$this->Core->Template->set_data('one', $one);
//Set the Memcache
$this->Core->Memcache->set($key, $stmt, TRUE, 20);
}
So my question is how can I get and set the data from a prepared statement fetch within memcache?
Memcache is a key/value storage system with both the key and the value needing to be serialized. From the php.net page:
Remember that resource variables (i.e. file and connection descriptors) cannot be stored in the cache, because they cannot be adequately represented in serialized state.
It appears your sql statement is looking for three values in a single row. I'm no expert on mysqli, but this is kind of what you want to do:
public function get_something($id, $account_name){
$sql = "SELECT one,two,three FROM table WHERE id = ? and account_name = ? ";
$key = md5("SELECT one,two,three FROM table WHERE id = $id and account_name = $account_name ");
$get_result = $this->Core->Core->Memcache->get($key);
if($get_result){
return $get_result;//#1 just return it, the format is an array like what is being built below
}
else{
$stmt = $this->Core->Database->prepare($sql);
$stmt->bind_param("is", $id, $account_name);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($one, $two, $three);
$stmt->fetch();
//Below is how i set the data
$this->Core->Template->set_data('one', $one);//#2 I don't know what this line does or is for, presumably for something else besides memcache stuff, maybe it acts like return
//Set the Memcache
$array=array();//#3
$array[]=$one;
$array[]=$two;
$array[]=$three;
$this->Core->Memcache->set($key, $array, TRUE, 20);
//this is a function, do you want to return your values somewhere?
}
A few notes, #1 the answer to your question is simple, just return $get_result. It should be an array with three values. #2 I'm not familiar with this line, nor what it does. Is this how your "return" the values to your controller? If so, you'll want to mimick that line where I put the return inside the if #3 This is your problem. You can't save the $stmt variable in memcache, it's a mysqli object, not the data you want. You need to build an array and then save that array. And that should do it for you.
There are other nuances to do, you can loop on the returned values. You should check for mysql not returning anything. But this is the basic starting point to get this going.
Let me know if this works for you.
I have a standardized sequence of code which I used to display topic information on the home page and other pages on my site. I want to throw it in an include file so that I don't have to keep fixing multiple pages. The problem is sometimes this include occurs in a while statement which means there was a previous query supplying information for sorting purposes.
When the code is raw in the while statement, it works as it should and if there are multiple ids being served to the code from the previous query, it shows multiple results. However, if this code is in an include, I will only see one result. I assume because the include file only executes once. How would I serve an include file as the equivalent as my raw code?
Include
//outside query
while($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
$topic_id=htmlspecialchars( $row['topic_id'], ENT_NOQUOTES, 'UTF-8' );
//code to display topics
include('display_topics.php');
}
Raw Code
//outside query
while($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
//code to display topics
$sql = "SELECT * FROM topic WHERE id=?";
$stmt = $conn->prepare($sql);
$stmt->bindValue(1,topic_id, PDO::PARAM_INT);
$result=$stmt->execute();
}
while($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
//yada yada
...
}
Don't do it this way.
It's much better to do one include, and to declare a function in it that does what you need:
function display_topics($topic_id)
{
....
}
Call that function inside the loop, and pass all necessary data to it.
Include the file as normal, but put the repeated code in a function. Then, where you wish to add the code simply call the function.
That word, I don't think it is for what you think it is for.
Generally, include's use should not be used that way. That's why God invented functions (or Ada Byron, if you're not theologically inclined).
Try this instead:
function execute_row($row, $conn)
{
$topic_id=htmlspecialchars( $row['topic_id'], ENT_NOQUOTES, 'UTF-8' );
$sql = "SELECT * FROM topic WHERE id=?";
$stmt = $conn->prepare($sql);
$stmt->bindValue(1,topic_id, PDO::PARAM_INT);
return $stmt->execute();
}
Then, in your while statement:
while($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
$result = execute_row($row, $conn);
}
TADA! And the best part is, it makes your code smaller, easier to read, and faster to parse.
I created this code:
$statement = $db->prepare("SELECT * FROM phptech_contact");
$statement->execute();
$result = $statement->result_metadata();
$object = $result->fetch_object();
print_r( $object );
When I run it, it doesn't work. Can anybody tell me why it doesn't work?
I have 20 rows in this table so data should be returned.
From http://ch.php.net/manual/en/mysqli-stmt.result-metadata.php
Note: The result set returned by mysqli_stmt_result_metadata() contains only metadata. It does not contain any row results. The rows are obtained by using the statement handle with mysqli_stmt_fetch().
As long as you don't need this meta data you don't need to call this method.
$statement = $db->prepare("SELECT fld1, fld2 FROM phptech_contact");
$statement->execute();
$stmt->bind_result($fld1, $fld2);
while ($stmt->fetch()) {
echo "$fld1 and $fld2<br />";
}
But I really dislike the mysqli extension. PDO is much cooler ... ;-)
$db = new PDO('...');
$stmt = $db->prepare("SELECT fld1, fld2 FROM phptech_contact");
$stmt->execute();
while ($obj = $stmt->fetchObject()) {
// ...
}
or
$objs = stmt->fetchAll(PDO::FETCH_OBJ);
if you're trying to get the rows from the database, the function you need is mysqli_stmt::fetch(), not mysqli_stmt::fetch_metadata()
You're also missing a few steps. When using prepared statements, you must specify the fields you would like to return instead of using the star wildcard, and then use mysqli_stmt::bind_result() to specify which variables the database fields should be placed in.
If you're more familiar with the original MySQL extension, prepared statements have a different process to use. If your select statement has a parameter (eg., "WHERE value=?") prepared statements are definitely recommended, but for your simple query, mysqli:query() would be sufficient, and not very different from the process of mysql_query()
I believe the problem is that mysqli_stmt::result_metadata() returns a mysqli_result object without any of the actual results — it only holds metadata.
So what you want to do is use $result = $statement->bind_result(...) and then call $result->fetch() repeatedly to get the results.
One of the comments under the bind-result() article shows how to do this for a query like yours, where you don't necessarily know all of the columns being returned.