procedural php/mysql to object oriented issue - php

This is the original code I am trying to write in object oriented form..
$posResult = mysql_query("SELECT MAX(position)+1 FROM todo");
if(mysql_num_rows($posResult))
list($position) = mysql_fetch_array($posResult);
This is where I am at.... I think I need to bind_result? also, I have an issue with the mysql_fetch_array...
if($stmt = $this->HH->Database->prepare("SELECT MAX(position)+1 FROM todo")) {
$stmt->execute();
$stmt->store_result();
if($stmt->num_rows != FALSE) {
list($position) = mysql_fetch_array($posResult);
}
}
Can someone advise on how to correct this?

It looks like you are moving over to PDO, which is great, it is a much better way to connect, but you are still trying to use some of the older mysql_* commands which won't work. While there are a number of ways to get the data, but this is the approach that I most commonly use:
if($stmt = $this->HH->Database->prepare("SELECT MAX(position)+1 FROM todo")) {
$stmt->execute();
$stmt->setFetchMode(PDO::FETCH_INTO, new yourClassName);
foreach($stmt as $yourClassObject)
{
$someVar=$yourClassObject->QueryColumnName;
// or
$this->someProperty=$yourClassObject->QueryColumnName;
}
}
I do generally have a class that matches the results of the query, so I use FETCH_INTO but you can use a different method such as return an indexed array, associated array or others.

Related

how to get $stmt to return from a class function in mysqli

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.

Trying to use prepared statements would this work or do I have the complete wrong idea?

So first off, im generating the menus for that page from database.
First of all, do I really need to prepare all queries? it seems alot more complicated than the simple Query > fetch > done.
Id probably guess that the way i've done it is wrong. But i find it easier to try then find out what i done wrong as i feel it's easier to learn that way.
So what parts are pointless or incorrect?
function menu() {
global $db;
$pagename = $_SERVER['PHP_SELF'];
// alternate ussage notes bind_param('sdi', $string, $decimal, $integer);
$stmt = $db->prepare("SELECT `p_id` FROM `pages` WHERE `name` = ?");
$stmt->bind_param('s', $pagename);
$stmt->execute();
$stmt->bind_result($page_id);
if ($stmt->num_rows()) { $isindb = true; }
else { $isindb = false; }
$stmt->fetch();
//echo $page_id; //uncomment to debug
$stmt->close(); // not sure if its closed too early.
if ($isindb) {
// great. generate the menu.
$stmt = $db->prepare("SELECT * FROM `menu_items` WHERE `d_id` = ?");
$stmt->bind_param('i', $page_id);
$stmt->execute();
$stmt->store();
$stmt->bind_result($menulink_id, $menulink_d_id, $menulink_icon, $menulink_href, $menulink_title, $menulink_new_tab);
echo '<li><span class="fa fa-home">Dasne Home</span></li>';
while ($r=$stmt->fetch()) {
if ($menulink_new_tab) { echo '<li><span class="fa fa-'.$menulink_icon.'">'.$menulink_title.'</span></li>'; }
else { echo '<li><span class="fa fa-'.$menulink_icon.'">'.$menulink_title.'</span></li>'; }
}
$stmt->close();
// close if isindb
}
else {
// give default menu
default_menu();
}
// close function
}
Also can you still use data from a prepared query after closing the statement?
do I really need to prepare all queries?
Yes.
it seems alot more complicated
Yes. Because mysqli is not intended to be used as is, being only a low-level API, while you have to use a higher level abstraction library.
So what parts are pointless or incorrect?
This is a clearly offtopic question.
i find it easier to try then find out what i done wrong
Indeed, but you are doing it wrong way. Instead of "trying" A LOT of code you have to try with one alone query.
So, get rid of most of the code, leave only one query to run, and write it using PDO.

(PHP) How do I return regular MySQL result resources when using prepared statements?

This is a bit of a clueless-beginner type of question, so I apologise. But I've not managed to find a website or video that helps me understand working with MySQL prepared statements, so I'm hoping for some direct advice.
For the last couple of weeks of my learning, I've been using procedural MySQLi calls to make database queries, and working through them with while loops. Things like
$query = mysqli_query("SELECT * FROM `Shoes` WHERE `Color` = 'Red'");
while ($row = mysqli_fetch_assoc($query)) {
echo $row['size'];
}
Things like that. It makes sense to me that I would be execute a query, get returned a special results resource, and then use a 'fetch_something' function to turn it into an array I can pick from and loop over, regardless of its size.
Now I'm trying to learn about prepared statements. What's tripping me up is the 'bind_result' function that seems to get used all the time, at least in every book and tutorial I've consulted so far. It tells me to provide one variable per column, to which the result for that column will be bound. Like
$db = new mysqli(server,user,pass,database);
$stmt = $db->prepare("select `Temperature` from `BuildingDetails` where `HouseNumber` = ?");
$stmt->bind_param("i",$_GET['num']);
$stmt->execute();
$stmt->bind_result($x);
$stmt->fetch();
echo "The temperature in this house is {$x}.";
Simple enough when I'm retrieving a single value, or a single row. But what if I want to loop over a table with 20 columns and 5,000 rows? Is there a way I can just return a regular old MySQL result resource and use fetch_assoc or something on it?
Is there a way I can just return a regular old MySQL result resource and use fetch_assoc or something on it?
You can use mysqli_stmt_get_result
Procedural
$result = mysqli_stmt_get_result($stmt);
while ($row = mysqli_fetch_assoc($result))
{
print_r($row);
}
OOP
$result = $stmt->get_result();
while ($row = $result->fetch_assoc())
{
print_r($row);
}
This way you do not have to bind all the variables to get results.

Creating a container function for a PDO query in PHP

Because I find PDO executions extremely hard to remember and find myself looking back at previous projects or other websites just to remember how to select rows from a database, I decided that I would try and create my own functions that contain the PDO executions and just plug in the data I need. It seemed a lot simpler than it actually is though...
So far I have already created a connect function successfully, but now when it comes to create a select function I'm stumped for multiple reasons.
For starters there could be a variating amount of args that can be passed into the function and secondly I can't figure out what I should pass to the function and in which order.
So far the function looks like this. To keep me sane, I've added the "id" part to it so I can see what exactly I need to accomplish in the final outcome, and will be replaced by variables accordingly when I work out how to do it.
function sql_select($conn, **what to put here**) {
try {
$stmt = $conn->prepare('SELECT * FROM myTable WHERE id = :id');
$stmt->execute(array('id' => $id));
$result = $stmt->fetchAll();
if ( count($result) ) {
foreach($result as $row) {
print_r($row);
}
} else {
return "No rows returned.";
}
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
}
So far what I've established that the function will need to do is
Connect to the database (using another function to generate the $conn variable, already done)
Select the table
Specify the column
Supply the input to match
Allow for possible args such as ORDER by 'id' DESC
Lastly from this I would need to create a function to insert, update and delete rows from the database.
Or, is there a better way to do this rather than functions?
If anyone could help me accomplish my ambitions to simply simplify PDO executions it would be greatly appreciated. Thanks in advance!
First of all, I have no idea where did you get 10 lines
$stmt = $conn->prepare('SELECT * FROM myTable WHERE id = ?');
$stmt->execute(array($id));
$result = $stmt->fetchAll();
is ALL the code you need, and it's actually three lines, which results with a regular PHP array that you can use wherever you wish. Without the need of any PDO code. Without the need of old mysql code.
Lastly from this I would need to create a function to insert, update and delete rows from the database.
DON'T ever do it.
Please read my explanations here and here based on perfect examples of what you'll end up if continue this way.
accomplish my ambitions to simply simplify PDO executions
That's indeed a great ambition. However, only few succeeded in a real real simplification, but most resulted with actually more complex code. For starter you can try code from the first linked answer. Having a class consists of several such functions will indeed improve your experience with PDO.
. . . and find myself looking back at previous projects or other
websites just to remember how to select rows from a database . . .
FYI, we all do that.
You had a problem with the PDO API and now you have two problems. My best and strongest suggestion is this: If you want a simpler/different database API, do not roll your own. Search http://packagist.org for an ORM or a DBAL that looks good and use it instead of PDO.
Other people have already done this work for you. Use their work and focus instead on whatever awesome thing is unique to your app. Work smart, not hard and all that.
Writting a wrapper, should start form connecting the DB, and all the possible method could be wrapped. Passing connection to the query method, doesn't look good.
A very rough example would be the code bellow, I strongly do not suggest this mixture, but it will give you the direction.
You connection should be made either from the constructor, or from another method called in the constructor, You can use something like this:
public function __construct($driver = NULL, $dbname = NULL, $host = NULL, $user = NULL, $pass = NULL, $port = NULL) {
$driver = $driver ?: $this->_driver;
$dbname = $dbname ?: $this->_dbname;
$host = $host ?: $this->_host;
$user = $user ?: $this->_user;
$pass = $pass ?: $this->_password;
$port = $port ?: $this->_port;
try {
$this->_dbh = new PDO("$driver:host=$host;port=$port;dbname=$dbname", $user, $pass);
$this->_dbh->exec("set names utf8");
} catch(PDOException $e) {
echo $e->getMessage();
}
}
So you can either pass connection credentials when you instantiate your wrapper or use default ones.
Now, you can make a method that just recieves the query. It's more OK to write the whole query, than just pass tables and columns. It will not make a whole ORM, but will just make the code harder to read.
In my first times dealing with PDO, I wanted everything to be dynamically, so what I achieved, later I realized is immature style of coding, but let's show it
public function query($sql, $unset = null) {
$sth = $this->_dbh->prepare($sql);
if($unset != null) {
if(is_array($unset)) {
foreach ($unset as $val) {
unset($_REQUEST[$val]);
}
}
unset($_REQUEST[$unset]);
}
foreach ($_REQUEST as $key => $value) {
if(is_int($value)) {
$param = PDO::PARAM_INT;
} elseif(is_bool($value)) {
$param = PDO::PARAM_BOOL;
} elseif(is_null($value)) {
$param = PDO::PARAM_NULL;
} elseif(is_string($value)) {
$param = PDO::PARAM_STR;
} else {
$param = FALSE;
}
$sth->bindValue(":$key", $value, $param);
}
$sth->execute();
$result = $sth->fetchAll();
return $result;
}
So what all of these spaghetti does?
First I though I would want all of my post values to be send as params, so if I have
input name='user'
input name='password'
I can do $res = $db->query("SELECT id FROM users WHERE username = :user AND password = :password");
And tada! I have fetched result of this query, $res is now an array containing the result.
Later I found, that if I have
input name='user'
input name='password'
input name='age'
In the same form, but the query remains with :user and :password and I submit the form, the called query will give mismatch in bound params, because the foreach against the $_REQUEST array will bind 3 params, but in the query I use 2.
So, I set the code in the beginning of the method, where I can provide what to exclude. Calling the method like $res = $db->query("SELECT id FROM users WHERE username = :user AND password = :password", 'age'); gave me the possibility to do it.
It works, but still is no good.
Better have a query() method that recieves 2 things:
The SQL string with the param names
The params as array.
So you can use the foreach() logic with bindValue, but not on the superglobal array, but on the passed on.
Then, you can wrap the fetch methods
public function fetch($res, $mode = null)
You should not directly return the fetch from the query, as it might be UPDATE, INSERT or DELETE.
Just pass the $res variable to the fetch() method, and a mode like PDO::FETCH_ASSOC. You can use default value where it would be fetch assoc, and if you pass something else, to use it.
Don't try to be so abstract, as I started to be. It will make you fill cracks lately.
Hum... IMHO I don't think you should try to wrap PDO in functions, because they're already "wrapped" in methods. In fact, going from OOP to procedural seems a step back (or at least a step in the wrong direction). PDO is a good library and has a lot of methods and features that you will surely lose if you wrap them in simple reusable functions.
One of those features is the BeginTransaction/Rollback (see more here)
Regardless, In a OOP point of view you can decorate the PDO object itself, adding some simple methods.
Here's an example based on your function
Note: THIS CODE IS UNTESTED!!!!
class MyPdo
{
public function __construct($conn)
{
$this->conn = $conn;
}
public function pdo()
{
return $this->conn;
}
public function selectAllById($table, $id = null)
{
$query = 'SELECT * FROM :table';
$params = array('table'=>$table);
if (!is_null($id)) {
$query .= ' WHERE id = :id';
$params['id'] = $id;
}
$r = $this->conn->prepare($query)
->execute($params)
->fetchAll();
//More stuff here to manipulate $r (results)
return $r;
}
public function __call($name, $params)
{
call_user_func_array(array($this->conn, $name), $params);
}
}
Note: THIS CODE IS UNTESTED!!!!
ORM
Another option is using an ORM, which would let you interact with your models/entities directly without bothering with creating/destroying connections, inserting/deleting, etc... Doctrine2 or Propel are good bets for PHP.
Howeveran ORM is a lot more complex than using PDO directly.

Why doesn't this prepare statement work in MYSQLI?

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.

Categories