Autoload database class - php

Can I avoid instantiate a Db object inside of Names object to access it anyways?
Would __autoload work for that?
Is there another smart solution?
I have following classes (They are conceptual so they won't work if executed):
Db {
function connect($config) {
// connect to data base
}
function query($query) {
// Process a query
}
}
Names {
function show_names($query) {
$Db = new Db(); // Is it possible to autoload this object?
$Db->query(query);
// Print data
}
}

Classes can be autoloaded, but objects must be instantiated. It seems that your problem is trying to make these two classes more loosely coupled. Probably the simplest solution to this problem is using the Singleton design pattern. However, it is not the best solution, as you may decide to have more than 1 database connection, and it also becomes problematic in unit testing. I suggest taking a look at the concept of Dependency Injection, which is more complicated, yet much more flexible.

A solution that is often used for database connection related classes is to work with the Singleton Design Pattern (example of implementation in PHP).
It allows to have a class that will encapsulate the connection to the DB, and will ensure there is only one connection opened for the lifetime of the PHP script -- never more.
This will allow you to use some syntax like this :
$db = Db::getInstance();
$db->query('...');
Or :
Db::getInstance()->query('...');
About autoload : it will work, as long as : there is a way for it to map the class' name to a file.

Related

Should MVC models be static?

EDIT: After some research, I saw this framework: this MVC framework. It have classes in Libs folder which are static (like Config, Session), can I use these ?
I am pretty new to MVC practices, and I am stuck on a weird problem..
I have many models, such as DB, User, Config, etc.. but I'm using many of these in each function I create.
I have a problem working with MVC patterns; I created multiple models, I'm using each one of them to handle grouped tasks(connection, DB, ect..).
Problem is, after creating the basic models, I ended up with code like this(within the controller).
class User
{
function signup($username, $password, ...)
{
$config = new Config();
$DB = new DB();
$HTML = new Session();
// And so on...
$canRegister = $config->get("registration-enabled");
if ($canRegister and ..) {
$this->username = $username;
$DB->saveAccount($this);
$session->setUser($this);
} else {
throw new Exception('bad signup');
}
}
}
I have to create instances of many models just for one or two functions.. but if the models are static, it should look like this:
class User
{
function signup($username, $password, ...)
{
$canRegister = Config::get("registration-enabled");
if ($canRegister and ..) {
$this->username = $username;
DB::saveAccount($this);
session::setUser($this);
} else {
throw new Exception('bad signup');
}
}
}
Note that many models doesn't use __construct method.. so is it good practice (or not bad) to have statics models in a MVC pattern ?
Please see EDIT above before responding.
Model is a concept of abstraction!
Model consist of services, while services themselves consist of storage abstractions and objects that handle computations. Simply put, a service is a bridge between domain objects and storage abstractions (such as Data Mappers or Table Gateways). A model consists of those services.
That's a typical way how a model should be structured:
Model
- Storage
- MySQL
- YourMapper
- Service
- YourService
A class that handles abstraction to a table and does computation and validation is also known Anemic Model (which seems to be your case), because it violates the SRP and breaks Separation of Concerns.
When adhering to this right way, you can easily replace storage (say you can replace MySQL to MongoDB) since they no longer tightly-coupled to business logic. Or you can replace domain objects that handle computations without even touching a storage.
And no, nothing ever should be static!
For the purpose of example, let's imagine, that your write a library that does file uploading.
class Uploader
{
...
public function upload(array $files)
{
$path = Config::read('upload_path');
$some_another_option = Config::read('foo');
$this->move($path, $some_another_option, $files);
}
...
}
So what kind of problem might lie here? Just remember that we write a library, and let's face these facts:
In order to use a uploading library, the Config object must be properly instantiated and its data must be fully loaded into the memory. Which is a waste of RAM and
What if you decide to replace Config to another source of required information? You can't because its tightly-coupled
If you want to distribute your library, you will also have to distribute your Config + its dependencies, which will make your library look bad.
Yeah, you probably have seen this approach in another frameworks. But popular doesn't mean correct, anyway.
The right way,
You gotta remember that object instantiation is another responsibility too. When you instantiate a Conifg you probably load data from somewhere (array or a table, whatever). So in your first approach you gotta load it n-times? That's seems a very wrong way to do.
What you should really do is to instantiate Config only once, and pass it to classes the require it, like this:
$config = new Conifg();
$config->load(__DIR__ . '/config_array.php');
$user = new User($config);
$system = new System($config);
// and so on, you got the point
The same applies to your DB and Session. Classes which use these objects should not bother about their instantiation. They just gotta bother how to use them.
Remember: Nothing ever kills code reuse-ability like Static classes and Singletons
All cool dudes refer to this technique as Dependency Injection

Manager classes for Objects

Moving from C#/C++ to PHP OOP has proven a bit problematic as I am not sure it is standard to design the code layout in the same manner. As that is the case, I am curious if the following would be considered problematic or wrong when it comes to PHP.
CDeviceManager class (1 initiated)
CDevice class
Keep a private array of CDevice in the CDeviceManager class
Use public methods to fetch devices, search devices, etc.
The most problematic question however is populating each CDevice from a MySQL Database. Would it be safe to include my Database class directly into CDeviceManager and Populate CDevice Array in CDeviceManager Construct?
A lot of what I have read says it is smart to separate the business logic from the view, where I feel this method would do just that. I have not seen many other projects that appear to use this approach though, why I am worried I may be missing something.
It would be best to separate your business logic from data storage system. I recommend using dependency injection to get your job done. The exact implementation would depend on your needs (and project size), but to get an idea here's would be what I would do:
class CDeviceManager
{
private $db; //holder for your database
private $cdevices = array();
//more properties here
public function __construct(Database $db)
{
$this->db = $db; //database connection has now been injected into your class
}
//more methods here
}
Then somewhere along the line when you create your CDeviceManager object you can inject the database connection.
$cdm = new CDeviceManager( new Database(...) );
Your Database class would likely be a wrapper for PDO or MySQLi or whatever database API you would want to use. You could also go farther and have CDeviceManager implement some kind of interface that relate to various CRUD functions in your database. Best part though, is you can test this a whole lot easier because now you can swap out your database connection with a mock/test database so you don't inadvertently screw up your production database.
$cdm = new CDeviceManager( new MockDatabase(...) );
or
$testdb = new TestDatabase(...);
$cdm = new CDeviceManager( $testdb );
So yes, in the end it is good to separate the database connection from your domain models. Some recommend going even farther and making sure that your domain models are completely ignorant to the storage mechanism in general, this way you could be flexible on your storage system/persistence layer. E.g:
$cdm = new CDeviceManager( new FileRetriever() ); //Maybe you are storing stuff in a flat file
Hope that helps clear things up a little bit.

Should I be using dependency injection in my php project?

I've recently learned the merits of dependency injection but am wondering if I should be using it in my project since I don't even require a full blown mvc. Now that I'm using it I'm realizing the extra overhead in each page that I write. For example...
require_once '../../include/session.class.php';
require_once '../../include/db.class.php';
require_once '../../include/account.class.php';
$objSession = new Session();
$objDb = new Db();
$objAccount = new Account( $objSession, $objDb );
account.class.php
class Account {
...
public function __construct( Session $objSession, Db $objDb ) {
$this->session = $objSession;
$this->db = $objDb;
}
}
...the Account class will always need Db and Session and I'll only ever have one class of each. So my question is, should I be using DI in a situation like this or should I just use...
account.class.php
require_once '../../include/session.class.php';
require_once '../../include/db.class.php';
class Account {
...
public function __construct() {
$this->session = new Session();
$this->db = new Db();
}
}
...?
Dependency Injection has nothing to do with MVC. It is really good at making unit tests easier to write and ultimately I have found that it makes me really think about the resources that I'm using and whether or not that implementation should be using that resource.
I personally don't see the harm in creating the injected object, so you've got a couple lines where you have to create an object? It tells the user a lot more about what's going on. I'd rather have clarity as compared to magic.
Personally, I think most of the clutter in the code is coming from the require statements. I'd say an autoloader would solve some of that problem.
I really enjoyed this Google Clean Code Talk on DI. It helped me grasp the concept and its benefits a little better.
You've read about the merits of dependency injection. Why did you start using it?
Was it because of the ability to swap out those particular dependencies for testing or different environments? Was it to isolate and make explicit the order of a circular chain of dependencies?
Suppose, for example, that it was the desire to inject different classes for testing purposes (the merit of DI that made me use it). How do you handle that without DI?
Look at your Account class. You can either modify the constructor with an if check on some predicate testMode(), or you can modify the Db and Session constructors, or you could possibly change a configuration file. Whatever non DI solution you opt for, are you ok with that? What about other dependencies (emailer, logger, etc)? Do you have any interfaces to external systems that you should mock for testing?
Anyway, the answer could be that you are satisfied without the DI solution and that your app is small enough to manage without it. But it's important to ask yourself the question anyway.
Similarly, apply that same line of questioning to the other merits of DI that motivated you to start using it.
Incidentally, do you have one instance of Db in Account and another in each of your other classes? Could you have just one instance? DI helps with that. You can have singleton classes without actually coding them as singletons by always injecting the same instance.
Out of curiosity, why are you doing your own dependency injection instead of using a DI library? Half of the benefit of using DI is that it is cleanly abstracted away by other people's implementations. Only write the code you need to and let the libraries take care of doing the injection for you. This is similar to drrcknlsn's suggestion, but without writing the actual implementation of the DependencyInjectionContainer class:
$account = DependencyInjectionContainer::build('Account');
and screw the rest.
A good DI library should see the constructor for Account, realize it needs a Db and a Session, and march up the chain of constructors (in this case, it ends there since both have empty constructors). That translates to having the same amount of code as the non DI case (plus the arguments to the constructor, minus the calls to the constructors inside, but no extra crap at top), with whatever benefits brought you to DI in the first place.
Dependency injection containers were invented to solve this very problem. Consider:
$account = DependencyInjectionContainer::build('Account');
The DependencyInjectionContainer class would handle the injection:
public static function build($class) {
switch ($class) {
case 'Account':
$session = new Session();
$db = new Db();
return new Account($session, $db);
// ...
}
}

performance of loading php classes and the use of 'extends'

I have an includes.php page that I load at the start of every page of my website.
As I develop the website, the number of classes that I am using is growing.
So I end up with something like this:
$db = new DB($config);
$login = new Login($db, $config);
$form = new Form($db, $config);
And the list goes on and on.
I have two questions about this practice:
First, Considering I might not be using a class at a certain page (I might not have a $form on every single page), how much does it really matter, performance-wise, to load this class every time any given page is loaded?
Second, you may have noticed that I am passing the class instance $db to all the other classes, as well as a variable $config. In the php code of every class, I do something like this:
public $db;
public $config;
public function __construct($db, $config, $smarty){
$this->db = $db;
$this->config = $config;
}
then in the class methods, I address the database and config files with 'this' as such:
public function myfunction(){
$this->db;
$this->config;
}
When should I use 'extends' rather than passing $db to the class, assuming every class uses the db? Does passing $db to every class hurt in any way in terms of performance?
Thanks!
When should I use 'extends' rather
than passing $db to the class,
assuming every class uses the db?
When it makes sense -- and only when it does !
You have at least two things to consider :
"class A extends B" kind of means "class A **is a** B"
more clearly, a Car is a MotorVehicule ; a MotorVehicule is a Vehicule ; a Bus is a MotorVehicule ; a Bicycle is a Vehicule
however, a Ball is not a Vehicule
In your case, a Form is definitly not a DataBase ! Nor is a Login
In PHP, a class can only extend one class
You can not have something being both a Vehicule and an Animal
But a Car is a MotorVehicule, which, itself, is a Vehicule :-)
In the case of a Database object (in your case, it's more a connection to a DB), mosts of your classes will not themselves "be" a database connection. So, they shouldn't extend that class.
However, they are using a DB connection (a Form "has a" DB connection) ; so, they should have a property representing that DB connection. That's what you are doing.
Instead of passing $db to each constructor, you might use
either the Singleton design pattern
or the Registry design pattern
or some kind of global variable, but that's almost the same... just being worse (not OOP and all that) !
But passing the $db object is great for unit-testing, mock objects, and all that...
I think it could be considered as being the Dependancy Injection design pattern, btw (not sure, but looks like it)
About loading lots of classes, other people gave answers :
Use autoloading if you can
Use an opcode cache, like APC, if you can
Both of those are great suggestions that you should take into consideration ;-)
One last thing :
Does passing $db to every class hurt
in any way in terms of performance?
Maybe it does a little bit ; but, honnestly, except if you are google and have millions of users... who cares ?
If you are doing a couple of DB queries, those will take LOTS of time, comparing to passing one more parameter to even a dozen methods !
So, the small amount of time used passing paremeters can probably be neglected :-)
Have you tried something like this?
function __autoload($class_name) {
require_once("includes/php/class." . $class_name . ".php");
}
So it only loads the class name when the class name is encountered.
(Change the path to suit your php classes... mine are like class.Object.php, with the class name "Object").
Why not include only the files that need to be included? Also, try to instantiate only those objects that you need where you need them. As it is, your includes.php is doing a lot of instantiation that you might not need all the time.
If $db is passed as a reference, it shouldn't affect performance. (I don't know much about PHP5, but with PHP4 there was a concept of reference with the '&' modifier.)
If loading and parsing the script files becomes a bottleneck you can use a bytecode cache like apc to speed up this part of the life cycle.
I'm not sure how exactly you'd want to use inheritance ('extends') here. You could use it to define the two fields $db and $config, but otherwise it would not change much.
Also, it might limit you when you actually do want to inherit something useful from another class.
Depending on your design, you might want to consider making $config global. Is there a situation where there is more than 1 configuration active at the same time? It probably wouldn't be a good idea to introduce a global $db variable however. It's conceivable that you might need more than one database connection at the same time for instance.

PHP - Where is the best place to initiate a database class?

I recently took my Db initiating code out of the __construct of my Page class and placed it just after I initiate the Page class. I removed it from within the Page class because I want to be able to access it from anywhere (other classes for example). It also takes server, username, password and database arguments to it when initiated, and I don't wish to enter these every time.
Is there a way I can access it from under the Page class now? I've tried a few methods, even global (which I have been told is an awful way to do things) and so far no avail. I am still new to OO, but I am teaching myself as best as I can.
Should I make it a static class? Will this affect the lazy connector to the Db I have setup?
Any help would be much appreciated.
Thank you
[EDIT]
Similar Question: Global or Singleton for database connection?
A global of some sort (Be that global variables, singleton or some other variant) is an improvement over your previous approach, and as such you're on the right track. Generally speaking though, you should try to minimise the scope of program state (For a number of reasons, which I won't get into here). Having a global variable is in conflict with this principle. There are different solutions to this problem, but the most powerful and often overlooked approach, is to use inversion of control; Instead of obtaining a dependency, your class should receive it. For example, let's say you currently have this
class EditUserController {
function saveUser() {
$db = Database::GetInstance();
$db->execute("update users set ...", ...);
}
}
You could change this into:
class EditUserController {
function saveUser($db) {
$db->execute("update users set ...", ...);
}
}
Passing dependencies on the function-parameter level can be a bit unwieldy though, so a compromise could be to pass it on a per-object level:
class EditUserController {
protected $db;
function __construct($db) {
$this->db = $db;
}
function saveUser() {
$this->db->execute("update users set ...", ...);
}
}
This is a fairly common pattern in OO programming. In addition to being more practical than passing in function parameters, it has the additional benefit of separating construction (Where shared dependencies are wired up to each other), from runtime (Where they are used). This makes a lot of things simpler.
Global variables do have a use, and this would be one of them. Unless it's likely that you're going to be needing multiple database connections, (or even still), then I don't see a problem with setting up a global $db object.
An alternative way is to have a static "Factory" class which you can use to get the object. In Joomla 1.5, the way you access the DB object is like this:
$db =& JFactory::getDBO();
the getDBO function checks if the DB object has been created: if it has, return a reference to it, otherwise connect and initialise, and then return it.
This could equally apply to other "could-be-made-global" objects, like the current User object.
The singleton method was created to make sure there was only one instance of any class. But, because people use it as a way to shortcut globalizing, it becomes known as lazy and/or bad programming.

Categories