April 23, 201016 yr I am trying to use object orientated programming with a database but I fail to see the benefit with some applications. For example: - I use a query to get a list of unique IDs from a database (via an object, which is fine) and this is returned as a 2D array. - I then use a for loop to create a collection of objects of type Topic and pass the ID into the Topic constructor for each iteration. - In each Topic's constructor another connection is made to the database to obtain further Topic information. - I then use functions in the Topic class to get this information from within the topic and output it via HTML. That is making use of objects. My problem is, why don't I just use my original query to get all the information I need via my 2D array and just traverse the array to find and display the data I want? I have been asking myself why don't I just disregard the Topic object and use the array directly, which contains all the information anyway? Could someone comment because I am struggling to comprehend which approach I should use. I do understand the merits of object orientated programming and I do use it in my coding for various tasks but there are just some things, such as the scenario described above, where I ask myself is it worth it? Let me know your thoughts.
April 23, 201016 yr OOF! This is a tricky subject - a minefield in programming. The point of mapping data to objects is to deal with something called "impedance mismatch". In principle, the reasoning is sound - but in practice, it can be more trouble than it's worth. There are 2 principle patterns for representing data in objects: 1: Active Record - see Ruby on Rails, Doctrine, Propel 2: Domain Model - see nHibernate, iBatis... more from the Java end of things Basically - ActiveRecord object map 1:1 to a table in the database. This works really well, but falls apart if your data for Object X comes from several tables. Active Record looks a bit like this: $User = new User(1);//pass the id to the constructor, loads record with id 1 $User->setName('Different Name'); $User->save() As you can see, that's very handy To deal with 1:m relationships, you need to use a Data Mapper $UserMapper = new UserMapper; $User = $UserMapper->load(1);//pass the id to the mapper, loads record with id 1 $User->setName('Different Name'); $UserMapper->save($User); In this example, the user mapper is responsible for mapping the fields from different tables to one object, and you can create different mappers to handle different query requirements. However, where it starts to fall apart is graphing object relationships: $UserMapper = new UserMapper; $User = $UserMapper->load(1);//pass the id to the mapper, loads record with id 1 $User->getBlogPosts(); Once you start getting into this territory, you run into performance problems as you load large collections of data as objects. You also have issues of Identity: $User1 = $UserMapper->load(1); $User2 = $UserMapper->load(1);//same object being made $User1->changeName('David'); $User1->save(); $User2->save();//!!! UH OH, the old data has just gone back over the new data These issues can be mitigated with use of the Identity Map, Unit of Work and Lazy Load patterns, but it gets increasingly complex to keep an eye on what's happening. So, for what it's worth - Object mapping from data is great, but it's a game of diminishing returns. It works for 50-60% of your needs, but the amount of effort to accomplish complex query requirements is not justified by the returns, often resulting in an API that is more complex than raw SQL. You can still use OOP productively - but you should think about using a Transaction Script which simply provides a common interface for query strings - I made a post on the subject here: http://www.webdesignerforum.co.uk/blog/298/entry-711-oop-php-part-2-database-access/ Hope that helps!
April 23, 201016 yr You're only creating one top-level object called Topic, right? i.e. that doesn't store other objects as its properties (as this gets into the nested objects complexities which sunwukung was talking about)? The way you are doing it does sound clunky. You can do better... namely using one database query only. Why don't you have a constructor for Topic which accepts a row from the database? This then populates all the Topic object's properties from the data in that row. For example: // Topic constructor (in your Topic class) function __construct($proprow) { $prop1 = $proprow["field1"]; $prop2 = $proprow["field2"]; // etc } // Creation code (usually good in a factory class) $result = mysql_query("SELECT field1,field2,field3,... FROM table_name WHERE conditions"); $topics = array(); while($row = mysql_fetch_assoc($result)) { $topics[] = new Topic($row); } You can also look at Factory method pattern on Wikipedia. In any case, that takes the total amount of database queries down to one (excluding the PHP request to find the associative column names for the array), with a single loop to go through the results. Does that help, or at least make sense?
Create an account or sign in to comment