Symfony 2/Doctrine - Always available DB Connection? - php

Accoring to the Symfony 2 Documentation, you have to use the following PHP code to connect to the database and execute a query...
$conn = $this->get('database_connection');
$users = $conn->fetchAll('SELECT * FROM users');
I'm a complete novice with Symfony 2 but I am experienced with OOP. I was wondering if it was possible to have a globally available $conn variable that I can access from any bundle. The $conn variable would contain the value of $this->get('database_connection') so I don't have to retype $conn = $this->get('database_connection');it every time I want to make a new query.
Thanks!

global variables are most of the time NOT something you want in OOP. They are confusing when it comes to a method which deals with multiple variables and they might even be hidden by local variables. For me, working with statements like
$anything = $this->get('what.the.hell.why.arent.those.identifiers.shorter');
is as annoying as for you so I ended up in creating one subclass of Symfony\Bundle\FrameworkBundle\Controller\Controller per project which provides methods which call get with the actual identifiers. In your case I would create a method
public function getDatabaseConnection()
{
return $this->get('database_connection');
}
In general - why don't you use Doctrine for managing the DB connection? Most of the queries can be done by the ORM and this is the way to work with a real object-oriented interface to the database. Think about it, I'm also playing with Symfony2/Doctrine since some days and it really feels good. In the beginning, it might look like a hell of configuration, but once you've done the basic configs, the development is really fast! :)

Related

What's a good way to make a PHP website approach the database object oriented?

Please note I'm not looking for 'use a framework' answers. I'm trying to structurally improve the way I code websites and approach databases from PHP.
I'm building a web service from scratch, without any frameworks. I'm using a LAMP stack and am trying to learn a bit of PHP's OO functionality while I'm at it. I've previously only used OO to make mobile apps.
I've been at it for months now (as planned, no worries). Along the way I've bumped into a couple of structural problems, making me wonder what the best way would be to make the code object oriented.
Pretty much all of the problems involve the database in some way. Say we have a class DB and a class User. In most cases I only need to fetch a single user's information from the database. I thought a good way to handle it was to have a global $_db variable and have the User object query the database like so (oversimplified):
class User {
function __construct($id) {
global $_db;
$q = $_db->query("SELECT name, mail FROM user WHERE id = ?", $id);
$this->loadProperties($q);
}
}
Now say we have a page that shows a list of users. I still want to make User objects for each of them, but I don't want to query the database for each separate user.
So, I extend the User class to take an object as an argument:
class User {
function __construct($id) {
if(is_object($id))
$q = $id;
else {
global $_db;
$q = $_db->query("SELECT name, mail FROM user WHERE id = ?", $id);
}
$this->loadProperties($q);
}
}
Now I can create a list of, for example, the 100 most recently created and active accounts:
$user_list = [];
$q = $_db->query("SELECT name, mail FROM user WHERE banned = 0 ORDER BY date_created DESC LIMIT 100");
while($a = $_db->fetch($q))
$user_list[] = new User($a);
This all works great, except for one big downside: the database queries for table user are no longer in one place, which is kind of making spaghetti code. This is where I'm starting to wonder whether this can be done more efficiently.
So maybe I need to extend my DB object instead of my User object, for example:
class DB {
public function getUsers($where) {
$q = $this->query("SELECT name, mail FROM user WHERE ".$where);
$users = [];
while($a = $this->fetch($q))
$users[] = new User($a);
}
}
Now I would create the user list as follows:
$user_list = $_db->getUsers("banned = 0 ORDER BY date_created DESC LIMIT 100");
But now I'm calling the getUsers() method in various places using various SQL queries, solving nothing. I also don't want to load the same properties each time, so my getUsers() method will have to take entire SQL queries as an argument. Anyway, you get the point.
Speaking of loading different properties, there's another thing that has been bugging me writing OO in PHP. Let's assume our PHP object has at least every property our database row has. Say I have a method User::getName():
class User {
public function getName() {
return $this->name;
}
}
This function will assume the appropriate field has been loaded from the database. However it would be inefficient to preload all of the user's properties each time I make an object. Sometimes I'll only need the user's name. On the other hand it would also be inefficient to go into the database at this point to load this one property.
I have to make sure that for each method I use, the appropriate properties have already been loaded. This makes complete sense from a performance perspective, but from an OO perspective, it means you have to know beforehand which methods you're gonna use which makes it a lot less dynamic and, again, allows for spaghetti code.
The last thing I bumped into (for now at least), is how to separate actual new users from new User. I figured I'd use a separate class called Registration (again, oversimplified):
class Registration {
function createUser() {
$form = $this->getSubmittedForm();
global $_db;
$_db->query("INSERT INTO user (name, mail) VALUES (?, ?)", $form->name, $form->mail);
if($_db->hasError)
return FALSE;
return $_db->insertedID;
}
}
But this means I have to create two separate classes for each database table and again I have different classes accessing the same table. Not to mention there's a third class handling login sessions that's also accessing the user table.
In summary, I feel like all of the above can be done way more efficiently. Most importantly I want pretty code. I feel like I'm missing a way to approach the database from an OO perspective. But how can I do so without losing the dynamics and power of SQL queries?
I'm looking forward to reading your experiences and ideas in this field.
Update
Seems most of you condemn my use of global $_db. Though you've convinced me this isn't the best approach, for the scope of this question it's irrelevant whether I'm supplying the database through an argument, a global or a singleton. It's still a separate class DB that handles any interaction with the database.
It's a common thing to have a separate class to handle SQL queries and to keep the fetched data. In fact, it is the real application of the Single Responsibility Principle.
What I usually do is keep a class with all the information concerning the data, in your case the User class, with all the user information as fields.
Then comes the business layer, for instance UserDataManager (though the use of "Manager" as a suffix is not recommended and you'd better find a more suitable name in each scenario) which takes the pdo object in its constructor to avoid use of global variables and has all the SQL methods. You'd thus have methods registerNewUser, findUserById, unsuscribeUser and so on (the use of "User" in the method can be implied by the class name and be omitted).
Hope it helps.
I've liked to use the data mapper pattern (or at least I think that's how I'm doing it). I've done this for some sites built on Silex, though it's applicable to going without a framework since Silex is very lightweight and doesn't impose much on how you architect your code. In fact, I recommend you check out Symfony2/Silex just to get some ideas for ways to design your code.
Anyway, I've used classes like UserMapper. Since I was using the Doctrine DBAL library, I used Dependency injection to give each mapper a $db. But the DBAL is pretty much a wrapper on the PDO class as far as I understand, so you could inject that instead.
Now you have a UserMapper who is responsible for the CRUD operations. So I solve your first problem with methods like LoadUser($id) and LoadAllUsers(). Then I would set all the properties on the new User based on the data from the database. You can similarly have CreateUser(User $user). Note that in "create", I'm really passing a User object and mapping it to the database. You could call it PersistUser(User $user) to make this distinction more clear. Now all of the SQL queries are in one place and your User class is just a collection of data. The User doesn't need to come from the database, you could create test users or whatever else without any modification. All of the persistence of `User is encapsulated in another class.
I'm not sure that it's always bad to load all of the properties of a user, but if you want to fix that, it's not hard to make LoadUsername($id) or other methods. Or you could do LoadUser($id, array $properties) with a set of properties taht you want to load. If your naming is consistent, then it's easy to have set the properties like:
// in a foreach, $data is the associative array returned by your SQL
$setter = 'set'.$property;
$user->$setter($data[$property]);
Or (and?) you could solve this with Proxy objects. I haven't done this, but the idea is to return a bunch of UserProxy objects, which extend User. But they have the Mapper injected and they override the getters to call into the Mapper to select more. Perhaps when you access one property on a proxy, it will select everything via the mapper (a method called populateUser($id)?) and then subsequent getters can just access the properties in memory. This might make some sense if you, for example, select all users then need to access data on a subset. But I think in general it may be easier to select everything.
public function getX()
{
if (!isset($this->x)) {
$this->mapper->populateUser($this);
}
return $this->x;
}
For new users, I say just do $user = new User... and set everything up, then call into $mapper->persist($user). You can wrap that up in another class, like UserFactory->Create($data) and it can return the (persisted) User. Or that class can be called Registration if you'd like.
Did I mention you should use Dependency Injection to handle all of these services (like the Mappers and others like Factories maybe)? Maybe just grab the DIC from Silex, called Pimple. Or implement a lightweight one yourself (it's not hard).
I hope this helps. It's a high-level overview of some things I've picked up from writing a lot of PHP and using Syfmony2/Silex. Good luck and glad to see PHP programmers like yourself actually trying to "do things right"! Please comment if I can elaborate anywhere. Hope this answer helps you out.
You should first begin by writing a class as a wrapper to your Database object, which would be more clean that a global variable (read about the Singleton Pattern if you don't know it, and there is a lot of examples of Singleton Database Wrapper on the web). You'll then have a better view of the architecture you should implement.
Best is to separate datas from transactions with the database, meaning that you can for example have two classes for your User ; one that will only send queries and fetch responses, and the other that will manage datas thanks to object's attributes and methods. Sometimes, there can be also some action that doesn't require to interact with the database, and that would be implemented in these classes too.
Last but not least, it can be a good idea to look a MVC frameworks and how they work (even if you don't want to use it) ; that would give you a good idea of how can be structured a web application, and how to implement these pattern for you in some way.

How to use DAL on PHP

Hello i have a code where they use this to connect to database
$db= DAL::get_instance();
$count=$db->read_single_column("select count(id) from ".TABLE_PREFIX."users where email=? and status=1", array($email));
echo "Aqui".$count;
I make a blank new page for that site, but i think $db= DAL::get_instance(); is not working.. i dont want to create multiple Connections to database, so how can i use DAL on PHP so i can use that same chain to connect...
And where and how is set DAL? (how can i search for the string where is set, whats the format)
Thanks
I Found a DAL.php on the library core.. But its encripted with Ioncube.. so my guess is i wont be able to see how is set :(
Your DAL class is userland-defined - there is no such thing in PHP. Post the entire code of it somewhere and someone might be able to tell you what to do with it.
I will, however, provide generics based on what you've said. static::get_instance() and the mention that you are not able to fire more than one instance of it suggests that your database abstraction layer is, in fact, a Singleton. This is good, and then again, this is very bad. The entire aim of the Singleton is to restrict the class to one and one instance only, which is quite nice for a database layer.
In your case, however, it looks like you want to connect to multiple DBs at the same time. Depending on how the code is coded, you may be able to do this with little to no modification to the code.
For reference, this is a simplified version of your DAL: http://codepad.viper-7.com/gPQ8bo . I kept the bits you are concerned with and stripped everything else out.
The obvious way
Rip up the singleton and start using dependency injection.
The not-so-obvious way
You can use Reflection to reset a Singleton's private static member. This is a hack, so use only if you have to.
The fiddle to this lies here: http://codepad.viper-7.com/ja6zHL . The code is as follows:
$reflection = new \ReflectionProperty('MySingleton', 'instance'); // Get a handle to the private self::$instance property
$reflection->setAccessible(true); // Set it to public
$reflection->setValue(null, null); // Modify it
// Optional: re-restrict it
$reflection->setAccessible(false);
Note that this is hackish for three reasons:
You should not be doing this. Instead, you should consider using a DAL that actually allows you to fire multiple connections or make one yourself
This uses Reflection, which has pretty big performance implications
This is a hack. You also lose your first DB connection, so you need extra housekeeping.

PHP conventions for encapsulation and database calls

This is going to take a bit to explain. I'm creating my first real-world web application, and I'd to do it properly. I have very little PHP experience, but vast experience in other languages so technical skill isn't a problem, it's more conventions of the language. I'm following the MVC pattern, and I am at the stage where I'm implementing user registration for the application.
To standardise connections to the database, I've created a Config class with a static getConnection method, which creates a mysqli connection object. This isn't a problem, it's the next bit that is.
To make my classes a bit more readable, I have various functions built into them that make database calls. For example, my User class has a getFriends method like so:
class User
{
public $id;
public getFriends()
{
return UserController::getFriends($id);
}
}
But as it stands now, if I implement it that way, it means creating a connection for every query on a page, probably many times in a single script, which is just horrific.
I was thinking about doing the same as above, but pass getFriends a mysqli object, which in turn passes one to UserController::getFriends as well, but that feels messy, and frankly poor form, even though it would guarantee only one connection per script, a much better improvement.
I also thought about scrapping the idea of keeping the methods inside User altogether, and instead making calls like UserController::getFriends($connection, $id) directly in the script, with a single $connection declared at the beginning, in place of user->getFriends(). That seems like the absolute cleanest, nicest solution, but I'm unsure.
So, essentially, how do PHP folks normally do this sort of thing?
What I do in my MVC framework is create a db connection and assign it to the Model base class (in the config):
$db = new database\adapters\MySQL(...);
if ( !$db->connected() ) {
exit('Ewps!');
}
database\Model::dbObject($db);
Then later on, anywhere, I can use:
User::getFriends(13);
because User extends Model and Model has access to $db: self::dbObject()
If I need my raw db connection, I either use Model::dbObject() or $GLOBALS['db'], but I rarely do need the raw connection, because all db logic should be in your Models.
https://github.com/rudiedirkx/Rudie-on-wheels/blob/master/example_app/config/database.php
https://github.com/rudiedirkx/Rudie-on-wheels/blob/master/example_app/models/User.php#L30
Have a look into the Singleton Pattern . It allows you to create a class (a DB object), but where only one of them is ever allowed (so more than one can't be instantiated).
This means that you only have to create one connection to the DB and it's shared.
Check here for a code example

Designing a general database interface in PHP

I'm creating a small framework for my web projects in PHP so I don't have to do the basic work over and over again for every new website. It is not my goal to create a second CakePHP or Codeigniter and I'm also not planning to build my websites with any of the available frameworks as I prefer to use things I've created myself in general.
I have had no problems in designing and coding the framework when it comes to parts like the core structure, request handling, and so on, but I'm getting stuck with designing the database interface for my modules.
I've already thought about using the MVC pattern but found out that it would be a bit of an overkill for my rather small project(s).
So the exact problem I'm facing is how my frameworks modules (viewCustomers could be a module, for example) should interact with the database.
Is it (still) a good idea to mix in SQL directly into PHP code? (Would be "old way": mysql_query( 'SELECT firstname, lastname(.....))?
How could I abstract a query like the following?
SELECT firstname, lastname FROM customers WHERE id=X
Would MySQL "helper" functions like
$this->db->customers->getBy( 'id', $x );
be a good idea?
I'm not really sure because they tend to become useless when dealing with more complicated queries like the pretty much trivial one above.
Is the "Model" pattern from MVC my only real option to solve this?
What do you currently use to solve the problems shown above?
I believe you just want to get access to your DB from your module. I'd avoid using mysql_query directly from the code. Rather, going for simple model with abstracted DB access would be easy and straight-forward.
For example, you can have a file like models/Customers.php with this code:
<?php
class Customers {
public function getById($id) {
$sql = "SELECT first_name, last_name FROM customers WHERE id='$id'";
$res = $DB::getRow($sql);
return ($res);
}
}
I am assuming some kind of DB helper is already instantiated and available as $DB. Here is a simple one which uses PDO.
Now, you should include this in your module and use the following way:
<?php
include_once "models/Customers.php";
$customers = new Customers();
$theCustomer = $customers->getById(intval($_REQUEST['cust_id']));
echo "Hello " . $theCustomer['first_name']
Cheers.
have you looked into http://www.doctrine-project.org/ or other php orm frameworks (zend_db comes to mind)?
If you need speed, then use raw queries (but you should really use PDO with prepared queries).
If you want something more OOP, you can —as you suggest it— design this with helpers.
Once, I've designed something similar which had the following concept:
DB connection/handler classes (handling multi-connections to different databases and different servers such as MySQL, Oracle, etc.);
A class per action (ie. SELECT, DELETE, etc.);
Filter classes (eg. RangeFilter);
The code looked something like this:
$select = new Select('field1', 'field2', );
$result = $select->from('myTable')
->addFilter(SQLFilter::RangeFilter, 'field2')
->match(array(1, 3, 5))
->unmatch(array(15, 34))
->fetchAll();
It's a simple example of how you can build it.
You can go further and implements automated handling of table relations, field type check (using introspection on your tables), table and field alias support, etc.
It might seem to be a long and hard work, but actually, it won't take you that much time to make all these features (≈1 month).
Three tips:
Use Stored Procedures (so you can separate the php from the db)
Use PDO/MySQLi for prepared statements CALL NEWS_LIST(?, ?)
Use a Static Class for your DB. Allows you to access it within any module.
Raw SQL is still the winner for me, I like to control what I send to the server (for cases like index usage, complex JOIN clauses and etc) so I generally stay away from helper functions.
You should use PDO which already provides a lot of power and if that's not enough, you can extend that (possibly with your own functions, such as checking for hits on Memcached/APC before actually querying the database). You can also extend the class to implement your own SQL functions like:
function getUser($user_id) {
return $this->query("SELECT * FROM users WHERE id = " . (int) $user_id);
}
Of course that, from the model you should still be able to send:
$this->db->query("SELECT * FROM users WHERE id = " . (int) $user_id);
and get the same result. The functions should act merely as a shortcut and the extended class should not be included with the framework as it will be site-dependant.
The MVC pattern will fit nicely into this because you can use the database merely as a driver and your model can then transform the data into what you need. It's not hard to create a simple MVC structure and it will bring you benefits later.
You sound like me. Have you seen http://github.com/Xeoncross/micromvc and the one file ORM in http://github.com/Xeoncross/database? Dig through my code and I think you will find what you're looking for.
The solution is to use the full raw power of some queries - while still allowing ORM and query builders (like codeigniter's AR) for other things.
Both are good.
Not that i know the definitive answer (nor do i think it exists), but i thought i can just share what i have here. I use my own db 'framework', lightweight (~1000 lines currently) and easy to use. My main goal was to simplify the use of sql, not to 'hide' it from the programmer (me:). Some examples:
// row() is 'query' + 'fetch' in one
$user = $db->row("select * from users where id=25");
// the same, injection safe
$user = $db->row("select * from users where id=?", $_GET['id']);
// ? placeholders are smart
$someUsers = $db->rows("select * from users where id IN(?)", array(1, 2, 10));
// ...and even smarter
$data = array('name' => 'Joe', 'age' => 50);
$id = 222;
$db->exec("update users set ?a where id=?", $data, $id);
// 'advanced' fetch functions
$topNames = $db->vlist("select name from users order by name limit 10");
$arrayOfIds = $db->nlist("select id from users where age > 90");
// table() returns a Table Gateway
$db->table('users')->delete('where id=?', 25);
// yes, this is safe
$db->table('users')->insert($_POST);
// find() returns a Row Gateway object
$db->table('users')
->find('where name=?', 'Joe')
->set('status', 'confirmed')
->save();
Understand this: database interaction is a solved problem.
So unless you really want to do it a) for the experience or b) because you're OCD and want to know every character of the code you'll be using, then I'd choose an existing solution.
And there are many: PEAR::MDB2, Zend::Db, Creole, Doctrine, Propel, just to name a few.
I've just come off the "helper functions" path and the one thing that bugged me was that I continued adding functions in one file which grew and grew with identical or similar or defunct functions. I think the line count was at 600 and that is way to much for a single file in my opinion. This has not put me off the idea but I'll be more organised for the next trek. I'll probably split the db functions into multi files according to the db operation (select, insert etc...).
So my advice is to go try the "helper functions" and be as organized as you can.
Also, I used PDO for the first time and quite liked it. Its not as low tech as the mysql() functions or as bloat tech like some we could mention but won't. I'll be using PDO again.
It seems like there are many different opinions on this topic and as I haven't found a really satisfying answer here yet and the bounty is nearly over, I'll just write what I have come up in the last days after some trial and error:
I'm using a singleton MySQL class to handle the connection and the very basic queries as well as errors that may occur.
Single pages like /users/show/1 (using mod_rewrite) don't use raw SQL but some kind of lightweight ORM that works like in the following example:
$user = $this->db
->users
->getBy( 'id', $id );
$this->db is an instance of a Database Abstraction class with a __get( $tableName ) method. Accessing the undefined users property then triggers it. The rest explains itself; A query is formed from the arguments passed to getBy( ) (SQL escaping is also handled by it) and its results are returned as an array.
I haven't finished the whole idea yet, but adding a new user to the database could look like the following:
$user = $this->db
->users
->new;
$user->id = 2;
$user->name = 'Joe';
$user->save( );
As I said the concept isn't really completed and may have (huge) flaws in it. Yet I think that it may be easier to write, more secure and easier to maintain than plain MySQL.
Some other good sides of the whole "thing" would be that it is small, therefore rather fast and also pretty straightforward.
I know that this can't compete with the extremely powerful ORMs and frameworks already out there but I'm still creating this for some reasons mentioned in one of my comments above.
If you do plan on making a database class it may be an idea looking into making it a singleton, allowing you to use it without declaring it/creating it, as...
global $db;
$db = new db;
$db->query ('... sql ...');
is kinda redundant when you can do
db::query ('... sql ...');
I have a set of SQL functions that I use on a near regular basis to reduce what used to be a multi-line escaped lot of SQL to a single call, for example:
get_element ($table, $element, $value, $column='id');
get_row ($table, $value, $column='id');
So if you just want to get the name from a table 'customers' where the id is 4 you:
$name = db::get_element ('customers', 'name', 4);
There are also accompanying functions query_element and query_row, where you just pass it an SQL string and it returns a single element/row.
Along with the functions for insert/update, e.g.
$array = array (
'name' => 'bob jones',
'age' => 28
);
$insert_id = db::insert_array ('customers', $array);
$customer_details = db::get_row ('customers', $insert_id);
$customer_details['age'] = 30;
db:update_array ('customers, $customer_details);
Would create a new row, pull the details back out, update the age, then re-write it to the database.
Creating custom SQL access modules on a per-table basis is generally a mistake I have always found - it's better to just generically query the database using sensible functions.
If you do have to use anything with complex joins then it is always best to create function for it getCustomerInfo () for example, but if you just want a generic table value lookup making lots of custom methods just increases the chances of mistakes in one of them. Plus escaping data is very important - if you can use non-sql as much as possible and funnel it through a few core functions you can ensure everything is properly escaped fairly easily.
If you want to look at my custom database class let me know.

Should I instantiate new objects for all different interactions?

Im having a hard time grasping this concepts of objects and how they should interact/exist.
Should I for instance have different objects (well, maybee I mean connections to the database here if there is any difference) for interactions with my database whenever they are not related?
Lets say I have one object that index.php uses to get and display content from the database
and another object that a user use to add/remove things in the database. We can say that the objects are all of the class dbinteract which holds all the functions for messing about with the database.
Or should I maybee divide the classes into something like: dbconnection, dbdisplay, dbinsertion, dbmodification where I send the dbconnection to the other objects?
I feel like im missing something very obvious and it's frustrating trying to move forward not knowing where in the thought process im going wrong, I guess im looking for a question as well as a an answer here.
index.php
$connection = new dbconnection();
$displayer = new dbdisplay();
$activeconnection = $connection->connecttodatabase();
$pagetodisplay = $connection->getcontentofpagetodisplay($query);
$displayer->displayPage($activeconnection, $pagetodisplay);
userinsert.php
$inserter = new dbinsert();
$usersdbconnection = new dbconnection();
$inserter->newPost($userdbconnection, $usercredentials, $posttextfromuser);
$usersdbconnection->closedatabaseconnection();
You seem to be think at the wrong level of abstraction. OOP allows you to think about 'users' and 'articles' instead of 'database connections' and 'pages'.
I'm not sure I understand the problem fully - I think your question is 'which object should be responsible for connecting to the database?'. Creating a connection to the database only needs to be done once. This connection can then be shared between all of the objects. To share the connection you will need to create a class which all other classes that connect to the database can inherit from and a static variable in that class to ensure that only one connection object exists.
In other languages static variables are commonly called class variables.
To me, what it seems like you're missing is that object-oriented programming isn't there to make you do extra work following its rules, it's there to make your life easier. If it isn't making your life easier, you're doing it wrong.
sometimes books are better then surfing the net
i found this book really useful.
the examples lean towards java, but can be applied to any language
http://oreilly.com/catalog/9780596008673/

Categories