PHP/MySQLI select multiple columns - php

Hello all,
This query below contains the prepared statement that I would like to have mysqli processed
"SELECT password, salt FROM accounts WHERE username=?"
So far there seems to be no documentation on how fetch_array() works in OO-style with prepared statements. The closest thing I can find is http://php.net/manual/en/mysqli-result.fetch-array.php
Is there a particular "correct" way of doing it with mysqli prepared statements (the OO way)? thanks!

You won't get Objects directly out of the database with prepared statements.
Use fetch http://php.net/manual/en/mysqli-stmt.fetch.php to loop through the results, creating the required class instances and assigning them the data.
A model class will typically have a read method that does this. The method returns a instance, or an array of instances.
(Have a look at symfony models: http://www.symfony-project.org/book/1_0/08-inside-the-model-layer There are so-called peer models that provide static methods "to retrieve records from the tables. Their methods usually return an object or a collection of objects of the related object class".)

Related

Where to put PDO prepared statements in a DB_Connector class - in the constructor or the functions?

My web project has a class called DB_CONNECTOR where all the functions are bundled that interact with the mysql database. These would be functions like get_user(), add_user(), change_user_attribute() and many more. In each of these functions a sql query is executed and as is good practice, I use prepared statements (with named parameters).
Currently the connection to the database is established in the constructor of the class and also all the statements are prepared there. I thought this would be a good idea, so the statements are all immediatly ready for execution.
Now I realized that my use case is often to create a db_connector object, execute one or maybe two functions and then the objects lifecycle ends and at a later step a new one might be constructed (or not). So, I'm not so sure anymore if it smart to put the prepared statements in the constructor as it is forseeable that I will end up with at least 20 or likely more prepared statements.
So my question is:
is it a good idea to prepare all the statements in the constructor even if only one or two are used?
Or should I prepare them in the functions right before execution to avoid stressing the db with unneeded preparations?
This answer is based in both my experience and humble opinion, but I'll try to elaborate my arguments so it isn't just some random guy's opinion.
I don't think the database connection must be the core object in your application, let alone the only one. It'd expect to see an entirely different class for the user, so you can later have further classes for everything else. Otherwise, your application will eventually consist of a single class in a 5000 line file and your class will not be suitable to track entity data at instance level and you'll need to pass variables around in method calls. That's pretty much procedural code in OOP dress.
Also, I don't that making your User class inherits from Database (something pretty frequent nonetheless) is practical at all. Interlacing the database connection and the business logic objects doesn't really simplify application design and actually makes some parts harder.
The design of the database layer itself is pretty much standardised:
One connection per application (or more... you may need to connect to several sources!)
One statement per query.
This is exactly how PDO works.
Given that, it's easier to make the database classes just one more dependency of your entities rather than their grandparent. The injection of this dependency can be done by different means:
Make it a class property:
public function __construct(\PDO $connection)
{
$this->connection = $connection;
}
Pass it to the methods they actually needed (if not many of them):
public function getOrders(\PDO $connection)
{
$stmt = $connection->prepare('SELECT ...');
}
... or use one of those fancy dependency injection containers you can find at Packagist.
Be aware that there're also object-relational mapping (ORM), active record pattern... Those are entirely different families of solutions which may suit your needs or not depending on your use case, but not what I'm describing here.
Said that, it becomes obvious that you prepare the statements at the exact point where you need them. This design doesn't even allow otherwise ;-)

Objects with recursive properties in php

I'm using a class, moduleSelectQuery, to generate SQL queries in PHP.
Basically, this class breaks up the individual components of a SQL SELECT query, such as the table name, the fields to select, the WHERE conditions, etc.
However, this quickly becomes complicated with nested queries, such as an WHERE table1.field1 IN (SELECT table2.field2 from table2 WHERE table2.field3 = criteria)
Currently I have a property for moduleSelectQuery called $inWhereClause that is used to store the WHERE... IN(SELECT...) clause. Like the other properties (i.e. $tableName, $whereClause, $havingClause), this is parsed together by its own function based on user input.
However, this parsing function is fundamentally limited. Even if I devote enough effort to it as I do parsing the $whereClause property, it can't have additional nested select statements.
I think one way to do this would be to set $inWhereClause to be another moduleSelectQuery object. This would mean that the parent moduleSelectQuery would have a property which was itself a moduleSelectQuery, i.e. it would be a recursive object. Is this possible/good practice in PHP? Are there other drawbacks?
I could see this being a possible solution. Visualize having a Person class. A person might have a child, which is a person. Doesn't seem unreasonable.
I wouldn't necessarily call this a recursive object, as the object doesn't reference itself, but rather that an object can have a property that is an instance of the same class.
It would, obviously need to be nested appropriately, as only sub-queries in the Where statement would need to be moduleSelectQuery object, where simple comparisons would be instances of strings, or integers.
The only drawbacks that can arrive from this approach are in the design of the class, and methods. I do not see any glaring performance issues, or maintainability issues.

Multiple PDO instances in a script?

I've got a 'best practice' question about using PDO. I'm trying to finally get into object-oriented development and away from the PHP habits I developed ten years ago.
My normal method of development was to open a DB connection at the beginning of a script/page, then do a bunch of mysql_query calls as needed (mostly SELECT and INSERT). I'm using PDO for the first time, and it looks like the practice here is to create distinct PDO objects for each query/transaction. These seems like it would create multiple connections to the same DB during a string, which seems like a lot of unnecessary overhead.
Is my read on this totally wrong?
My apologies if this is covered somewhere I missed. I did look through StackOverflow, php.net, and a PHP 5.3 book I have.
No, you should not create multiple instances of PDO in that case. Just create 1 instance and use PDO::query() on it. For example:
$pdo = new PDO(...);
/* ... */
$pdo->query("SELECT * FROM table1");
/* ... */
$pdo->query("SELECT * FROM table2");
/* ... etc ... */
If the query contains parameters, then prefer using PDO::prepare() and PDOStatement::execute() instead of PDO::query(). You can find an example in the documentation for PDO::prepare().
The PDO Object stores the connection in which the queries are carried out. Normally, you only need one of those.
While there are cases where 2 connections might be convinient (When connecting to entirely different databases for instance), you generally only need one instance of the PDO class.
What you will have multiple instances of, is the PDOStatement class. Which stores the query statements themselves (as well as the results). So for every query you will have a single PDOStatement instance.
yes, you initially connect to the database by creating an instance of the PDO object. But you use this object to run queries with and the results are packed into another class.
So you mainly have several classes with your query results, but just one connection to the database which runs the queries.

Extend MySQLi Class to EXPLAIN SQL queries on page

how can I extend the MySQLi class to explain all SQL queries on a given page?
Thanks.
There are several ways to do this. Here is one:
To start, you can get an explanation by simply prepending "EXPLAIN " to the mysql statement. See http://dev.mysql.com/doc/refman/5.0/en/explain.html for details on Mysql's explain.
Knowing that Mysql invocation, the mysqli::query and mysqli::prepare methods both take their first parameter as the $query string (side note: just use the Reflection class in a quick test script to get the current method or construct prototypes. You'll find extending mysqli_result class is not actually possible, but that shouldn't be a problem here).
Knowing that,
Store the mysql query string used in the calling of your extended methods as a new property of your extended `mysqli` class
Pass on the parent method's return results as normal
Create a new custom method to call this string property with `explain ` prepended and run a new separate query on that using any parent method or generic Mysqli invocation. This new method will be called any time you need to output the query explanation in your html view

PHP Mysqli fetch_assoc

The MySQLi feature of PHP is great.
Prepared Statements are great for injecting parameters in a query.
However, if you use Statements, it seems you dont have access to the fetch_assoc feature anymore. You have to manually bind all your results. This mean my SQL query has to list all the fields, then I have to list all the variables in advance when getting the results (using bind_result). This can become very annoying and time-wasting.
Is there an alternative?
Thanks
Yes, it's called PDO and is generally preferred to MySQLi. It offers statements with the regular fetch options, and doesn't force you to explicitly bind all parameters. A typical query might look like this:
$stmt = $db->prepare("SELECT * FROM foo WHERE a = ?");
$stmt->execute(array($a));
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
PDO is very flexible, so it can be used in other ways as well. There's a lot of great examples in the manual. Take a look!
MySQLi does provide methods for dealing with this, have a look at result_metadata function.
I've written a class to allow hassle-free parameterised MySQLi queries - a download and basic usage info is available here: http://www.robpoyntz.com/blog/?p=191

Categories