I'm only half-familiar with OO PHP. I have made a few simple classes before, and used many downloaded ones, but would like to make one properly for once and am hoping for some reco's on either how to do it best, or which resource / tutorials to consult to get my head properly wrapped around it.
I will start with the background on how what I want to do.
I'm building a program that takes a user uploaded file (an excel file) which contains a list and various values. It would look something like this:
Item, person1, person2, person3
Car, 1, 3, 4
Bike, 5, 0, 1
Now, the main part of the class is used to create a graphic for each person that shows how many bikes and cars they have (and possibly many more items). So I create the class with some functions to specify background imagery, size etc... that is straightforward enough I think.
What I want to do though is figure out the best way to pass the data to that class so it can efficiently make my graphic. Should I just read through the data in the excel file using some excel file reading class and do something like:
foreach column {
foreach row {
$data[$vehiclename] = $columnVehicleCount;
}
$image = new MyClassName;
$image->loadData($data);
...
}
and then within my class I just just iterate through the $data's key value pairs? Or should I create some other object form to store the data before passing it? My hunch is that is the right thing to do, and sort of the point of OOP but this is where I am at a loss. Is this were I extend something? I am getting used to JS Objects using JSON, but still not 100% certain of the best way to use them.
Would I create some sort of subclass? How would it work?
$thisItem = $image->addItem(Bike);
$thisItem->quantity(5);
And then within the main class something like
foreach($this->items as $item) {
draw($item->name);
resize($item->quantity)
}
I'm sure that last bit is all wrong, but that's why I'm here. Any help or direction would be greatly appreciated.
Cheers,
M
I recommend you to build your classes according to oo principals
think about each object, what can he do (methods) what defines him (properties)
afterwards think about how you create the objects (Factory), and how you initialize them with data(builder).
Related
I'm currently at an impasse in reguards to the structural design of my website. At the moment I'm using objects to simplify the structure of my site (I have a person object, a party object, a position object, etc...) and in theory each of these is a row from it's respective table in the database.
Now from what I've learnt, OO Design is good for keeping things simple and easy to use/implement, which I agree with - it makes my code look so much cleaner and easier to maintain, but what I'm confused about is how I go about linking my objects to the database.
Let's say there is a person page. I create a person object, which equals one mysql query (which is reasonable), but then that person might have multiple positions which I need to fetch and display on a single page.
What I am currently doing is using a method called getPositions from the person object which gets the data from mysql and creates a separate position object for each row, passing in the data as an array. That keeps the queries down to a minimum (2 to a page) but it seems like a horrible implementation and to me, breaks the rules of object orientated design (should I want to change a mysql row, I'd need to change it in multiple places) but the alternative is worse.
In this case the alternative is just getting the ID's that I need and then creating separate positions, passing in the ID which then goes on to getting the row from the database in the constructor. If you have 20 positions per page, it can quickly add up and I've read about how much Wordpress is criticised for it's high number of queries per page and it's CPU usage. The other thing I'll need to consider in this case is sorting, and doing it this way means I'll need to sort the data using PHP, which surely can't be as efficient as natively doing it in mysql.
Of course, pages will be (and can be) cached, but to me, this seems almost like cheating for poorly built applications. In this case, what is the correct solution?
The way you're doing it now is at least on the right track. Having an array in the parent object with references to the children is basically how the data is represented in the database.
I'm not completely sure from your question if you're storing the children as references in the parent's array, but you should be and that's how PHP should store them by default. If you also use a singleton pattern for your objects that are pulled from the database, you should never need to modify multiple objects to change one row as you suggest in your question.
You should probably also create multiple constructors for your objects (using static methods that return new instances) so you can create them from their ID and have them pull the data or just create them from data you already have. The latter case would be used when you're creating children; you can have the parent pull all of the data for its children and create all of them using only one query. Getting a child from its ID will probably be used somewhere else so its good just to have if its needed.
For sorting, you could create additional private (or public if you want) arrays that have the children sorted in a particular way with references to the same objects the main array references.
I'm just starting out with a new project which has a product class. An object will represent a product.
Each product has any number of un-defined attributes (could be colour, could be foobar etc..). The product object will contain an array of either attribute objects:
class attr {
var type; // string, float, int etc..
var name; // the name
var value; // the value
...
(and then the product object has an array of these attr objects..)
OR should I store an array for each product:
class product {
var attributes = array('colour' => 'red', 'weight' => '11')
...
Obviously I can make the array 2d and store the attribute type if I needed to.
My main concern is that products may have 20 or so attributes and with lots of users to the site I'm creating this could use up loads of memory - is that right, or just a myth?
I'm just wondering if someone knows what the best practice is for this sort of thing.. the object method feels more right but feels a bit wasteful to me. Any suggestions/thoughts?
As a general advise I'm against early optimization, especially if that means turning your OO models into implicit (non-modeled concepts) things like arrays. While I don't know what is the context in which you will be using them, having attributes as first class citizens will allow you to delegate behavior to them if you need, leading to a much cleaner design IMO. From my point of view you will mainly benefit in using the first approach if you need to manipulate the attributes, their types, etc.
Having said that, there are lots of frameworks that use the array approach for dynamically populating an object by using arrays and the _get()/_set() magic methods. You may want to take a look for example at how Elgg handles the $attributes array of the ElggEntity class to see it working and get some ideas.
HTH
There is no best practice for that, AFAIK.
You have two options as described in Your question where each has its cos'n'pros. All it depends on is how/where the products and attributes will be stored - if it is in MySQL database still there shouldn't be a difference as You could fetch an array or an object from a DB.
If You are using classes for every simple thing, then use classes also for attributes, if You use classes only for the big objects, then use arrays. It is upon Your preference. There won't be any significant memory consumption difference when using classes or arrays and by no means while having 20 or so attributes.
If it was upon me, I'd go with classes and array of classes for attributes as it gives more advantages in the future should I need to extend the attributes some way.
If the Product class really needs to be flexible and accomodate an arbitrary number of attributes, I would be tempted to make use of __get and __set e.g.
class Product {
protected $attributes = array();
public function __get($name) {
if (array_key_exists($name, $this->attributes)) {
return $this->attributes[$name];
}
}
public function __set($name, $value) {
$this->attributes[$name] = $value;
}
}
$o = new Product();
$o->foo = 123;
var_dump($o->foo);
This would lend itself nicely to implementing ArrayAccess and other SPL iterator type classes in the future - if your solution required it.
I thinks it more important to considering how you are going to store them in you database. I guess that you want to have a search where you could say something like I want a RED HAT size 12 then you must be able to find all the products that have attributes that match this. This is all done on a database level. It would not be a good idea to load all products in PHP classes first and then search.
Once you get what you want to show (search result, overview page, details) then you load the full product class with attributes. Since its all text/numbers and probably not more then a 100 products at once, speed wise it wont matter what you choose in PHP. Do what you like best.
In your database it could matter (since there you always works with all the products). Make sure you seperate strings/numbers/bools etc and put the correct indexes or you could have a mayor performance drop.
In my MVC web app, I'm finding myself doing a lot of actions with ActiveRecords where I'll fetch a specific subset of Products from the database (for a search query, say), and then loop through again to display each one -- but to display each one requires several more trips to the database, to fetch things like price, who supplies them, and various other pieces of metadata. To calculate each of these pieces of metadata isn't very simple; it's not really something that could be achieved with a simple JOIN. However, it WOULD be possible (for most of these cases anyway) to batch the required database calls and do them all at once before the loop, and then within the loop refer to those pre-fetched data to do the various calculations.
Just as an example of the type of thing -- in a search, I might want to know what regions the product is provided by. In the database I have various rows which represent a particular supplier's stock of that item, and I can look up all the different suppliers which supply that item, and then get all the regions supplied by those suppliers. That fits nicely into one query, but it would start getting a bit complex to join into the original product search (wouldn't it?).
I have two questions:
does anyone else do something similar to this, and does it sound like a good way to handle the problem? Or does it sound more like a design problem (perhaps the application has grown out of ActiveRecord's usefulness, or perhaps the models need to be split up and combined in different ways, for instance).
If I do pre-fetch a bunch of different things I think I'll use inside the loop, I'm having a hard time deciding what would be the best way to pass the appropriate data back to the model. At the moment I'm using a static method on the model to fetch all the data I need at the start of the array, like fetchRegionsForProductIds(array $ids) and so forth; these methods return an array keyed by the ID of the product, so when I'm working inside the loop I can get the regions for the current product and pass them as a parameter to the model method that needs them. But that seems kind of hacky and laborious to me. So, can anyone tell me if there is just some really obvious and beautiful design pattern I'm missing which could totally resolve this for me, or if it's just a bit of a complex problem that needs a kind of ugly complex solution?
Small update: I wonder if using a datamapper class would put me on the right track? Is there a common way of implementing a data mapper so that it can be told to do large batch queries up front, store that information in an array, and then drip feed it out to the records as they request it?
I really hope this question makes sense; I've done the best I can to make it clear, and will happily add more detail if someone thinks they can have a go at it!
I'm trying to replace a site written procedurally with a nice set of classes as a learning exercise.
So far, I've created a record class that basically holds one line in the database's main table.
I also created a loader class which can:
loadAllFromUser($username)
loadAllFromDate($date)
loadAllFromGame($game)
These methods grab all the valid rows from the database, pack each row into a record, and stick all the records into an array.
But what if I want to just work with one record? I took a stab at that and ended up with code that was nearly identical to my procedural original.
I also wasn't sure where that one record would go. Does my loader class have a protected record property?
I'm somewhat confused.
EDIT - also, where would I put something like the HTML template for outputting a record to the site? does that go in the record class, in the loader, or in a 3rd class?
I recommend looking into using something like Doctrine for abstracting your db-to-object stuff, other than for learning purposes.
That said, there are many ways to model this type of thing, but in general it seems like the libraries (home-grown or not) that handle it tend to move towards having, at a high level:
A class that represents an object that is mapped to the db
A class that represents the way in which that object is mapped to the db
A class that represents methods for retrieving objects from the db
Think about the different tasks that need done, and try to encapsulate them cleanly. The Law of Demeter is useful to keep in mind, but don't get too bogged down with trying to grok everything in object-oriented design theory right this moment -- it can be much more useful to think, design, code, and see where weaknesses in your designs lie yourself.
For your "work with one record, but without duplicating a bunch of code" problem, perhaps something like having your loadAllFromUser methods actually be methods that call a private method that takes (for instance) a parameter that is the number of records to be retrieved, where if that parameter is null it retrieves all the records.
You can take that a step further, and implement __call on your loader class. Assuming it can know or find out about the fields that you want to load by, you can construct the parameters to a function that does the loading programatically -- look at the common parts of your functions, see what differs, and see if you can find a way to make those different parts into function parameters, or something else that allows you to avoid repetition.
MVC is worth reading up on wrt your second question. At the least, I would probably want to have that in a separate class that expects to be passed a record to render. The record probably shouldn't care about how it's represented in html, the thing that makes markup for a record shouldn't care about how the record is gotten. In general, you probably want to try to make things as standalone as possible.
It's not an easy thing to get used to, and most of "getting good" at this sort of design is a matter of practice. For actual functionality, tests can help a lot -- say you're writing your loader class, and you know that if you call loadAllFromUser($me) that you should get an array of three specific records with your dataset (even if it's a dataset used for testing only), if you have something you can run which would call that on your loader and check for the right results, it can help you know that your code is at least right from the standpoint of behavior, if not from design -- and when you change the design you can ensure that it still behaves correctly. PHPUnit seems to be the most popular tool for this in php-land.
Hopefully this points you in a useful group of directions instead of just being confusing :) Good luck, and godspeed.
You can encapsulate the unique parts of loadAllFrom... and loadOneFrom... within utility methods:
private function loadAll($tableName) {
// fetch all records from tableName
}
private function loadOne($tableName) {
// fetch one record from tableName
}
and then you won't see so much duplication:
public function loadAllFromUser() {
return $this->loadAll("user");
}
public function loadOneFromUser() {
return $this->loadOne("user");
}
If you like, you can break it down further like so:
private function load($tableName, $all = true) {
// return all or one record from tableName
// default is all
}
you can then replace all of those methods with calls such as:
$allUsers = $loader->load("users");
$date = $loader->load("date", false);
You could check the arguments coming into your method and decide from there.
$args = func_get_args();
if(count($args) > 1)
{
//do something
}
else // do something else
Something simple liek this could work. Or you could make two seperate methods inside your class for handling each type of request much like #karim's example. Whichever works best for what you would like to do.
Hopefully I understand what you are asking though.
To answer your edit:
Typically you will want to create a view class. This will be responsible for handling the HTML output of the data. It is good practice to keep these separate. The best way to do this is by injecting your 'data class' object directly into the view class like such:
class HTMLview
{
private $data;
public function __construct(Loader $_data)
{
$this->data = $_data;
}
}
And then continue with the output now that this class holds your processed database information.
It's entirely possible and plausible that your record class can have a utility method attached to itself that knows how to load a single record, given that you provide it a piece of identifying information (such as its ID, for example).
The pattern I have been using is that an object can know how to load itself, and also provides static methods to perform "loadAll" actions, returning an array of those objects to the calling code.
So, I'm going through a lot of this myself with a small open source web app I develop as well, I wrote most of it in a crunch procedurally because it's how I knew to make a working (heh, yeah) application in the shortest amount of time - and now I'm going back through and implementing heavy OOP and MVC architecture.
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.