tags:

views:

394

answers:

5

Hi,

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!

+4  A: 

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").

Michael
add to this what jeyoung said: you really should only load what you need *when* you need it present. There's still some unanswered questions in this post (when to use extends), which might be better extracted into new SO Questions.
anonymous coward
Would I put this code in my includes file, or in my classes?Won't it always encounter the variable, though, since I instantiate the class straight after loading the file?Thanks!
yuval
You would put this code in your header.php (that is included in all your files).Can you explain what you mean by instantiating the class right after loading the file?
Michael
@ anonymous coward, this is exactly what the autoload function provides. It won't load the class until the class object has been instantiated.
Michael
@Michael, I mean that straight after loading a class file like so:includes "db.class.php"; I do the following: $db = new DB; - Won't that always make __autoload encounter a class variable?
yuval
So you delete all includes, and just use the __autoload function in your header.
Michael
+1  A: 

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.)

jeyoung
yuval
Tom Haigh
+2  A: 

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.

VolkerK
What exactly does apc do?
yuval
When PHP loads a script it has to parse the contents into opcodes. apc stores these opcodes so the next time there's no need to run the parser. If you disable the stat-check it is even possible to avoid (relatively slow) file access at all.
VolkerK
+1  A: 

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.

Thorarin
The only reason I do not use $config as global is because I heard it is insecure. My database username and password is stored in the config file. Is there no real security issue with declaring global variables?
yuval
+4  A: 

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 :-)

Pascal MARTIN
Great and comprehensive! Thank you very much.
yuval
You're welcome :-) Have fun !
Pascal MARTIN