PHP, OOP and Databases - performance question
I have a question regarding performance when using OOP in PHP together with databases. I'll ask my question by example, suppose a class foo represents a row from some table. Now suppose I need to use foo at 5 different pages on my web app.
The catch is that on each of the 5 pages I will use data from different columns. (i.e. the first page will use 开发者_高级运维column1 and column2 while the second page uses column3 and column 4, etc..)
The OOP approach (as far as I can see) would suggest that when I initialize foo on some particular row I would connect and fetch all the columns of that row and build my object. I could then proceed with my logic and use whatever data that I might need.
The issue I have with this is that with the procedural approach (which I'm more used to when it comes to web) would not waste resources to download columns that I do not need since the query would be specifically tailored to the needs of the particular page.(i.e. If im on the first page I would only download column1 and column2 since that's what I need.)
Am i going about the OOP approach wrong or is the extra overhead so insignificant that developers in general download data which they do not need?
Thanks and sorry if this has already been covered, I thought it would be an interesting topic! :)
Erik
further clarification:
The class is like:
class foo
{
$column1;
$column2;
$column3;
$column4;
public function _construct($id)
{
//get column 1,2,3 and 4 from database where table_id = $id
}
}
The issue is that if i only need column1 one one page i download column2,3 and 4 for nothing. In procedural approach you would not do that. Is my OOP model bad or is this ok?
You can still incorporate the selective query inside of an OOP class by using either an array of columns to grab upon construction, or by using a public class method to handle the query grabbing.
Example of constructor:
<?php
class Foo{
public function __construct( $column ) {
if(is_array($column)){
if(count($column) > 1){
$result = mysql_query('SELECT `'.implode('`,`', $column).'` FROM `table`;');
}else{
$result = mysql_query('SELECT `'.$column[0].'` FROM `table`;');
}
}else{
$result = mysql_query('SELECT `'.$column.'` FROM `table`;');
}
$this->result = mysql_result($result, 0);
}
}
?>
The public function method would be identical to that, except you could return the result instead of setting $this->result
.
I'm not entirely sure I understand your question. There are three things that I think could apply to how you are approaching this problem:
A) You are trying to build an object and then use data contained in that object throughout your script. B) You are using a PDO style database pull. C) You are using PHPs SPL to produce an iteration over an object which contains methods to pull information from the database.
I'll assume for now that you are using option A. Please forgive me if I am wrong and I am not trying to underestimate your knowledge at all...just getting it started here.
The approach of OOP is not to pull in all data to have it available throughout your script. Think of it as a collection of functions instead of a collection of data, although it could easily be either or both. You'll write your class methods just like you write functions without OOP. The only difference is, the object can be used to communicate with your script over the number of times that you need it to...
To answer your question plainly, I never pull more data than I need. For both security and performance reasons. You should use a class just like you use the procedural style. You could do all of your data pulls that will be required for the script upon instantiating the class (using a constructor method), but make sure that it's only the data you will need.
----Added
class foo{
function getData($page){
//Query to get the results you want based on the page number entered...
//Process it as you normally would into a result set, array, or whatever.
return $results;
}
}
Then call that
$foo = new Foo();
$page = "The page or the column that you want to pull";
$data = $foo->getData($page);
Your still doing everything procedurally, but now you have a dynamic function that can pull data based on what you send in as page... IN this case, I don't see any reason to use a constructor...only a getter method.
Does that help?
The general approach will be to select only the columns you need
foo->db->tablename->select('all', where date = $date)
.
Take a quick look at frameworks such as cakephp and symfony, it might help you get a better idea of how it's generally done.
My two cents. It depends on a number of things and how it affects the application as a whole ie. # of database requests, size per record, size of rowset, etc
I personally load all columns and profile to look for bottlenecks when I experience slow requests or high memory usage. If I have bottlenecks then I consider lazy loading only required columns at that point.
精彩评论