The SitePoint Forums have moved.

You can now find them here.
This forum is now closed to new posts, but you can browse existing content.
You can find out more information about the move and how to open a new account (if necessary) here.
If you get stuck you can get support by emailing forums@sitepoint.com

If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

sike: I'd be very interested to see the xmi reader, at the moment I'm manually writing the xml description files for my business objects, and it's the only tedious part of the developing.

Brenden: I'm interested to see how you're using XSLT to create the business objects. At the moment things follow a rough timeline as

- Upload zip containing xml descriptor, php base class, any additional classes (eg specialised view / edit / admin pages).
- Read XML descriptor to discover any requirements (ie an entitywikipage requires that a certain version of entitywebpage already be installed because it inherits from it), and to discover what properties it contains. These properties are the saved to the database. Currently, at this point, the xml file becomes redundant and could be deleted
- To create the business object, I call 'new businessobjecttype()'. In the object's constructor, all the property definitions for that object's type are read in from the database, and a property object created for them. These property objects are then saved in a $properties array, indexed by the property name. I then use __set and __get for accessing the properties.

What I'm thinking is that it might be possible that instead of the need to read the information about the properties from the database, I could use XSLT to create all the property objects. Do you have any code you're interested in sharing?

And that point you make about not needing to use only ORM is very important; I prefer it when relating objects because it simplifies the whole process (and I'm willing to take the small performance hit). Sometimes though you just need the raw SQL power and I'll use that if necessary; however, it's not a core part of the system.

My current method for data access is similar to jdo (arborint may not be happy ). I pass an object I call PHPDataMapper ($pdm) through my controller like most people pass a db object. There is a single data mapper for all objects, instead of 1 mapper for each object.

Can you show the detail implementation of PHPDataMapper? Im really interested to see how the whole things fit together.

An example script with a actual "Object" <> "Mapper" would be every nice.

Hi there guys, another one of this wonderful data access strategy threads

In the last discussions I stated that I'd like to have an O/R-mapper that doesn't use code generation and is non-intrusive (which means the persistable domain objects don't need to inherit from a certain class). I'm still developing such a thing and have finished about 40% maybe

I'm parsing an XML-File similar to the ones shown above, populating "ClassDescriptor", "FieldDescriptor" and "ReferenceDescriptor" objects from this and save them serialized on the disk. The XML-File will only be parsed again, when changes occured and the serialized data is lazy loaded by my application.

I'm quite inspired by apache OJB and try to provide a similar API. That means your persistable objects are very simple lightweight classes with only properties and setter/getter methods.

Queries will be done using a Query Object combined with Criteria objects similar to propels. The required joins will be generated automatically (including m:n associations)

I hope my approach has become clear. I'd appreciate any comments, suggestions, critic. If my app will be finished one day (and be performant enough) I'd like to release it licensed by LGPL. If anybody would like to help developing, I'd appreciate this!

Then when we are optimising SQL we find that we use findAllWithLastNameLike on 3 pages. One where we need all the customers data, one where we only need the firstname and lastname and one where we need the firstname, lastname and id. So we change the interface to look like this:

Whenever I see code like this I have to ask the question "Why are you guys making life difficult for yourselves?" Rather than trying to hard-code a separate function that will deal with a specific set of selection criteria why don't you adopt a generic approach with a single

PHP Code:

$fieldarray = $object->getData($where);

function. The $where argument is a string that can be used as the WHERE clause in an sql SELECT statement, so it can contain as many or as few parts as you wish. So regardless of what you want inside your WHERE clause you never have to create an alternative to the getdata() method.

By default this will select all columns from the current table, but if you want something different then supply a value such as:

PHP Code:

$object->sql_select = 'column1, column2';

When it comes to dataMappers - I don't use them. Basic information is held within each business object, but passed to a DAO when communication with the physical database is required.

When it comes to data access objects - I have one for the whole application, not one per database table. How is this possible? Because my DAO is not coded with any database, table or column names. These are all supplied by the calling object at run time. The DAO will then use whatever information it is given to construct an sql query, then call the relevant API for its designated DBMS.

Note that I have a separate DAO for each DBMS, so I can switch from one DBMS to another simply by switching my DAO.

Whenever I see code like this I have to ask the question "Why are you guys making life difficult for yourselves?"

There are plenty of occasions where this is easier. Either the methods wrap very simple solutions, so that hand coding is sufficient, or they mask a complex problem such as non-SQL data, non-isomorphic schema (e.g. group bys), highly optimised queries or non normalised data. They are just the ones I can think of off the top of my head. I bet there are more.

Originally Posted by Tony Marston

Rather than trying to hard-code a separate function that will deal with a specific set of selection criteria why don't you adopt a generic approach

Yes.

Originally Posted by Tony Marston

with a single

PHP Code:

$fieldarray = $object->getData($where);

function.

No. The column names, and with it the schema, are bleeding upwards and destroying the layering. A minor concern for one object for each row, a big headache for fetching collections and other relationships (e.g. ForeignKeyMapping). It's also harder to unit test as a result.

A DataMapper is a full on solution and one not to be taked lightly. Not least because you will need a new class for every business object to do the mapping. If you want the most flexible solution (it offers complete data source independence), and you are willing to resort to tricks like reflection and code generation to speed up development, then it is the Rolls-Royce answer.

Depending on the problem there could be much simpler answers, but the discussion seems to be too abstract right now for me to say.

Whenever I see code like this I have to ask the question "Why are you guys making life difficult for yourselves?" Rather than trying to hard-code a separate function that will deal with a specific set of selection criteria why don't you adopt a generic approach with a single

PHP Code:

$fieldarray = $object->getData($where);

function. The $where argument is a string that can be used as the WHERE clause in an sql SELECT statement, so it can contain as many or as few parts as you wish. So regardless of what you want inside your WHERE clause you never have to create an alternative to the getdata() method.

I don't think that's making life more difficult

Here's what I see as disadvantages of your solution

a) with a query object/criteria approach joins are generated as needed by the mapper, I don't see how you would add a join only within a where clause

b) maybe you don't want to hardcode your query but generate it based on certain conditions, criteria objects can easily be generated but with valid SQL that's more difficult

c) maybe you want an instance of a certain persistable object as result fo your query, not just an array of fields.

There are plenty of occasions where this is easier. Either the methods wrap very simple solutions, so that hand coding is sufficient, or they mask a complex problem such as non-SQL data, non-isomorphic schema (e.g. group bys), highly optimised queries or non normalised data. They are just the ones I can think of off the top of my head. I bet there are more.

I do not think it is easier to code additional functions for different types of SELECT if your infrastructure already contains a single generic mechanism that will already cater for all possibilities. As to customising the SELECT statement for particular situations I solved that problem several years ago. If you look at the sql manual you will see that the SELECT statement has several clauses. If you define each of these fragments as a separate variable within the class these can be assembled by the DAO into a complete query, as in:

The presentation layer component (page controller) may supply whatever values for each fragment it wishes to the business layer component (business object) which may or may not adjust the values before passing them to the DAO for final assembly and execution.

Originally Posted by lastcraft

Originally Posted by TonyMarston

... with a single function:

PHP Code:

$fieldarray = $object->getData($where);

No. The column names, and with it the schema, are bleeding upwards and destroying the layering. A minor concern for one object for each row, a big headache for fetching collections and other relationships (e.g. ForeignKeyMapping). It's also harder to unit test as a result.

I do not recognise this concept called "bleeding upwards", so I ignore it. It certainly does not destroy my layering as my infrastructure is based on the 3-Tier architecture which I have successfully implemented in more than one language. Each layer (or tier) does exactly what it is supposed to, so there is no problem with any sort of bleeding.

Originally Posted by lastcraft

A DataMapper is a full on solution and one not to be taken lightly. Not least because you will need a new class for every business object to do the mapping. If you want the most flexible solution (it offers complete data source independence), and you are willing to resort to tricks like reflection and code generation to speed up development, then it is the Rolls-Royce answer.

I do not need a separate dataMapper to go with each business object as I successfully combine the two into a single class/object. This keeps all the informaton about an entity (including information on its data structure) in a single class which is what encapsulation is supposed to be about.

Before you jump on me and say that I am not achieving the "correct separation of concerns" let me point out that although each business object holds information about the data structure it does nothing with it - it is passed to the DAO which is the only object in the entire application which communicates with the database. Thus my business object holds all information about an entity (thus satisfying the principle of encapsulation), but it is the DAO which is responsible for using this information to communicate with the database. This is my interpretation of what "separation of responsibilities" actually means.

a) with a query object/criteria approach joins are generated as needed by the mapper, I don't see how you would add a join only within a where clause

See my previous reply in which I indicate how the sql fragments are defined within the presentation layer before they are passed through the business layer, then to the DAO for final assembly and execution. All without a dataMapper.

Originally Posted by hantu

b) maybe you don't want to hardcode your query but generate it based on certain conditions, criteria objects can easily be generated but with valid SQL that's more difficult

Conditions may be hard-coded, or they may be supplied at run time from user input, or they may be inserted into the sql fragment by code within the business object. All these variations still do not require more than a single generic getdata() method (at least in my infrastructure they don't).

Originally Posted by hantu

c) maybe you want an instance of a certain persistable object as result fo your query, not just an array of fields.

Maybe, but the point under discussion is creating functions to retrieve data under different circumstances. Doing a retrieve without expecting data to be returned is another topic.

The concept of 'bleeding upwards' is not really a concept but a term to refer to one layer knowing about the layer above it; and as pointed out by Lastcraft this will definitely without any doubt at all, break layering - this is what your application layer(s) does and it's been pointed out to you.

Alas, you are ignoring this. What arrogance. What stupidity. Ahem.

You seam to ignore a lot of thought and advice pointed out to you by sitepoint members; they are trying to help you but you lack the understanding as you are not willing to learn more.

Btw, in relation to layering, any given layer (regardless of it's disposition or task) should only ever know of the layer(s) below it, and not never know what's above it; if you understand this, then maybe you can explain as to why this is?

See my previous reply in which I indicate how the sql fragments are defined within the presentation layer before they are passed through the business layer, then to the DAO for final assembly and execution. All without a dataMapper.

It definitely breaks layering and separation of concerns when the presentation layer cares for generating SQL. In my eyes, in an efficient design the presentation layer shouldn't even know the data is coming from an RDBMS.

Originally Posted by Tony Marston

Conditions may be hard-coded, or they may be supplied at run time from user input, or they may be inserted into the sql fragment by code witin the business object. All these variations still do not require more than a single generic getdata() method (at least in my infrastructure they don't).

They do not require more than a single generic getdata() and a hell a lot of typing. Sorry for me becoming sarcastic.

Originally Posted by Tony Marston

Doing a retrieve without expecting data to be returned is another topic.

Whenever I see code like this I have to ask the question "Why are you guys making life difficult for yourselves?" Rather than trying to hard-code a separate function that will deal with a specific set of selection criteria why don't you adopt a generic approach with a single

PHP Code:

$fieldarray = $object->getData($where);

function. The $where argument is a string that can be used as the WHERE clause in an sql SELECT statement, so it can contain as many or as few parts as you wish. So regardless of what you want inside your WHERE clause you never have to create an alternative to the getdata() method.
...

Hey Tony,

I think you've missed the point. "Hard-coded" behind that function may be a generic approach similar to yours. The point is, it doesnt matter as long as the parameters to the function are the same and the the return value is what is expected.

By putting the generic approach inside the function you start to see spots to refactor and your code becomes cleaner.

Originally Posted by Tony Marston

I do not recognise this concept called "bleeding upwards", so I ignore it.

The presentation layer component (page controller) may supply whatever values for each fragment it wishes to the business layer component (business object) which may or may not adjust the values before passing them to the DAO for final assembly and execution.

Great. So the presentation layer has to construct SQL statements. That's one tier.

Originally Posted by Tony Marston

I do not recognise this concept called "bleeding upwards", so I ignore it. It certainly does not destroy my layering as my infrastructure is based on the 3-Tier architecture which I have successfully implemented in more than one language.

This choice juxtaposition just about sums it up. I know better than to bother to explain anything to you because you will just come back with the same broken assertions. Your claim for three tier is utterly bogus.

The concept of 'bleeding upwards' is not really a concept but a term to refer to one layer knowing about the layer above it; and as pointed out by Lastcraft this will definitely without any doubt at all, break layering - this is what your application layer(s) does and it's been pointed out to you.

None of my objects has knowledge of the layer above it. It receives a request and generates a response. Thus a business object may be called from a controller or another business object. It does not matter which.

Originally Posted by Dr Livingston

Alas, you are ignoring this. What arrogance. What stupidity. Ahem.

So I am arrogant just because I refuse to accept your interpretation? What makes you think that your interpretation is the only true interpretation? Is it not you who is being arrogant?

Originally Posted by Dr Livingston

You seam to ignore a lot of thought and advice pointed out to you by sitepoint members; they are trying to help you but you lack the understanding as you are not willing to learn more.

No, the people here are not trying to help out, they are trying to enforce their opinion of what is right and wrong and utterly refuse to accept any alternative opinions.

Originally Posted by Dr Livingston

Btw, in relation to layering, any given layer (regardless of it's disposition or task) should only ever know of the layer(s) below it, and not never know what's above it; if you understand this, then maybe you can explain as to why this is?

Just so we all know you know what your talking about?

Yes, I do know what I am talking about, but do you? Can you explain in words of one syllable exactly how my approach breaks this "bleeding" rule between the layers?

Just because objects in the presentation layer, business layer and data access layer each have knowledge of database column names does not break any rules. Even the guru most often quoted in this forum acknlowledges this fact:

Martin Fowler in PoEAA
Layers encapsulate some, but not all, things well. As a result you sometimes get cascading changes. The classic example of this in a layered enterprise application is adding a field that needs to display on the UI, must be in the database, and thus must be added to every layer in between.

It definitely breaks layering and separation of concerns when the presentation layer cares for generating SQL. In my eyes, in an efficient design the presentation layer shouldn't even know the data is coming from an RDBMS.

The presentation layer does not generate SQL. It contains fragments of SQL which are passed to the business layer where they may or may not be massaged. The business layer then passes these fragments to the data access layer where they are assembled into a complete SQL query and then executed.

As a complete SQL query is only assembled and executed within my DAO I do not consider that I am breaking any rules.

Your interpretation of the requirements of the presentation layer are incorrect. According to every book or article I have read on the subject the ONLY requirement is that the presentation layer must not communicate directly with the database. It passes a request to the business layer which in turn passes a request to the data acess layer. The response is then passed back through the business layer to the presentation layer. It is only the DAO that can have any type of communication with the database. The passing of sql fragments between the various layers does not constitute database access, therefore I am not breaking the principles of the 3-tier architecture.

Great. So the presentation layer has to construct SQL statements. That's one tier.

Wrong again. The presentation layer does not CONSTRUCT sql statements, it merely identifies fragments of sql statements which are passed through the business layer to the data access layer. It is only in the DAO that a complete SQL query is assembled and executed. This conforms to the principles of the 3-tier architecture.

Originally Posted by lastcraft

This choice juxtaposition just about sums it up. I know better than to bother to explain anything to you because you will just come back with the same broken assertions. Your claim for three tier is utterly bogus.

I'm afraid that it is YOUR interpretation of the principles behind the 3-tier architecture which is utterly bogus. You invent rules that do not exist, then you have the arrogance to me that I am wrong.

I know your code snippet may be just that, an example, and therefore not complete and I've probably missed how you do this in the course of the discussion, or it may not even be covered in this discussion, but is it possible using the technique you have developed to generate SQL with JOINs? Around 90% of the queries in the application I maintain have a couple of JOINs and around 5% have conditional logic inside the query, such as IFs and CASEs. If this is a requirement can it be fulfilled using your technique?

Originally Posted by Tony Marston

I do not recognise this concept called "bleeding upwards", so I ignore it.

Maybe ask for someone to elaborate then?

Originally Posted by Tony Marston

I do not need a separate dataMapper to go with each business object as I successfully combine the two into a single class/object. This keeps all the informaton about an entity (including information on its data structure) in a single class which is what encapsulation is supposed to be about.

So perhaps the crux is it seems some people think an entity should not contain information on its data structure, whereas you believe it should.

I don't think (excuse me if I'm speaking out of place here) those who believe it should not contain it, say that what you're doing isn't "encapsulation". I don't think that's the argument against your idea, although they may not agree with your expansion of the term encapsulation to cover that as well.

They think that the entity should not contain the data structure information EVEN if it does not use it itself, the even being the key point.

I feel Swiss I'm trying to be so neutral

Off Topic:

Is it just me or at a cursory glance do the smilies look like they say "fag!"?

...is it possible using the technique you have developed to generate SQL with JOINs? Around 90% of the queries in the application I maintain have a couple of JOINs and around 5% have conditional logic inside the query, such as IFs and CASEs. If this is a requirement can it be fulfilled using your technique?

Yes, definitely. You can put whatever code you like into these fragments, including JOINs with other tables. The only condition is that when the DAO assembles a complete SQL query from these fragments that the end result is a valid query.

Originally Posted by timnz

Originally Posted by Tony Marston

I do not need a separate dataMapper to go with each business object as I successfully combine the two into a single class/object. This keeps all the informaton about an entity (including information on its data structure) in a single class which is what encapsulation is supposed to be about.

So perhaps the crux is it seems some people think an entity should not contain information on its data structure, whereas you believe it should.

When I create a class for an entity this class contains all the information, including business rules, which are relevant to this entity. Part of this information is what I call a $fieldspec array which identifies the names of the columns which exist in the table, and which of those columns constitute the primary key. This array is passed to the DAO along with a separate data array (usually the $_POST array) so that the DAO can construct the SQL query which is relevant for that operation on that table.

Originally Posted by timnz

I don't think (excuse me if I'm speaking out of place here) those who believe it should not contain it, say that what you're doing isn't "encapsulation". I don't think that's the argument against your idea, although they may not agree with your expansion of the term encapsulation to cover that as well.

They think that the entity should not contain the data structure information EVEN if it does not use it itself, the even being the key point.

You have hit the nail on the head! They think that by having such information inside a business object that I am not "achieving the correct separation of concerns", but their understanding of what this means is at total variance with my own. I use the term "separation of responsibilities" (not "concerns") to mean the following:

The presentation layer is responsible for all dialog with the user.

The business layer is responsible for all business rules.

The data access layer is responsible for all communication with the database.

So even though my business object contains some information about the structure of the associated database table this is totally irrelevant as it is the DAO which is responsible for using this information to communicate with the database. Responsibility means doing something with the information, not simply holding it for subsequent transfer to another object.

In my view I do not need to take this small amount of information out of my business object and hold it anywhere else as there is no justification. On the other hand, if I did move it to a separate object I would be breaking the principle of encapsulation as I would be holding information about a business entity in TWO places instead of ONE.

How anybody can become confused over such simple logic is beyond me. Are they born like it, or do they take special lessons?

How anybody can become confused over such simple logic is beyond me. Are they born like it, or do they take special lessons?

I'm new to posting on these forums, but have lurked here for quite some time and am very familiar with your act. You have the uncanny ability to bring down the quality of an entire forum thread with this type of garbage (not to mention the shameless, non-stop pimping of your website).

I'd beg to differ; You have SQL within the Presentation layer which actually in fact belongs within the Model layer to my mind of understand MVC - or nTier for that matter

Also I might add that I personally am not arrogant; I read the posts on these forums and I actually learn from them. I like to think that folks are helping me out, and I am indeed trying to help you out as well but you are ignoring the advice.

If my advice is wrong, then sure enough someone will point that out, and again I'll take note of my error, but I think your layering is wrong, and a few other members think your layering is wrong as well, so surely we cannot all be wrong huh?

Are you going to be arrogant enough to say we are eh? Your SQL is in the wrong place for the love of God, like how many different ways can we put that to you? Doesn't matter is it's fragments of SQL or whatever, it's still in the wrong place.

For the Martin Fowler quote, that is something I'm not familuar with; maybe you can post the url where the quote is

I know better than to bother to explain anything to you because you will just come back with the same broken assertions.

Yer, I'm kind of finding it extremely difficult to find any sense in replying to Tony's posts as well now, the lad just doesn't listen; It's like he knows everything there is to know, and personally I cannot be doing with people who are ba' heeded

There are some comments here that is really close to get this thread closed. I guess I don't have to point them out for you all. Another incident, event the smallest one, will result in closing.
If you're not adult enough to keep this civilized, then stay out of the discussion!