I am trying to make a PHP Application which will have different number of modules which can be enabled disabled at any time. Modules can be anything like news or articles etc. Each module will be application on its own however it will be displayed via a wrapper so that we can have many modules in the same system.
I am stuck now on how to accomplish this. The main problem is how much configurable it should be. For example: I can display main menu with all enabled modules. But what about the links in footer where I want to display things like about us or Community etc.
Should those be configurable? If so how because those links can be part of module, say, cms.
this question often stumps me because I try and make an app as much customizable as possible but in the end it becomes so confusing and hard to change.
Other examples include things like should I have a special data class for each module where it returns me query results? I think answer is yes but then I try to make db data class like “class.news.data.mysql.php” or “class.news.data.mssql.php”. Is that too much? There “might” be chances that some day i might open that app for other DBs but not in near future. But if I don’t do that then I’ll have to work more when I eventually do it.
I am not sure if I listed full information but I think you can see that I am thinking too much and its confusing me.
Use PDO http://fi.php.net/PDO and maybe write a wrapper for it, so you can add missing features afterwards if nessessary.
Use SQL SQL92 standard.
Don’t use database management system specific features.
Optionally you can use SQL-abstraction layer eg. http://framework.zend.com/manual/en/zend.db.select.html (haven’t tried this, so I don’t know if it’s any good)
This way you don’t have to write different sql-classes for every rdbms.
Other examples include things like should I have a special data class for each module where it returns me query results? I think answer is yes but then I try to make db data class like “class.news.data.mysql.php” or “class.news.data.mssql.php”. Is that too much? There “might” be chances that some day i might open that app for other DBs but not in near future. But if I don’t do that then I’ll have to work more when I eventually do it.
You could use creational pattern called “lazy loading” (or lazy initialization).
Basically what it is in terms of PHP is that you include a file containing class you need only when you attempt to create an object that is an instance of that class.
That way, when you deploy new modules or update old ones - there is no worry whether you included the file in the code somewhere or whether you included too many files that you won’t need for particular tasks.
For more information, search php.net for autoload and SPL autoload.
As for pluggable modules and how they are rendered, it really depends on how you constructed the framework that was used to build the application in question. Using MVC architecture, it becomes really easy to create modules that are rendered differently or the same as some other modules. There exist tons of articles about MVC architecture so I won’t try to rediscover hot water here, as you can google for a few of those.
Now, as it was mentioned by Jkos, you could use PDO in order to connect to various databases now and in the future.
However, you’re looking at a problem of different SQL standards and how certain databases resolve certain problems or features - for example, MySQL has SQL_CALC_FOUND_ROWS option for a SELECT statement that will enable you to find out quickly how many rows there would be had there not been a LIMIT clause. Other databases would use count(*) (I might need correcting on this statement tho).
Also, MySQL has the feature of auto_increment option for a primary key and method for retrieving last auto_increment generated. Other databases use triggers to accomplish such feature, and the field is usually called a sequence.
And those are only 2 examples of differences between databases.
So if you intend to enable various / multiple databases - you will be forced to use an SQL abstraction layer that has features of its own, both good and bad as sometimes it might take some time to actually write the code that will get executed across various databases.
The main question is - how far do you want to go with feature support? How much “freedom” do you want to give your client? The more you do so, the more complex the code becomes as you already noticed.
Generally I would certainly avoid a system where only the database class cares which database system is being used. Have a common gateway interface that all classes. given access, can use and whatever input is converted into database commands.
With all probability, if you find yourself with files such as “class.news.data.mysql.php” and “class.news.data.mssql.php” you’re about 3 days from a nervous breakdown. Followed by a code rewrite.
Generally, however, finding yourself coping with multiple database systems is an absolute nightmare. I’ve done it with almost every framework I’ve written and doing so causes problem after problem - stick with PDO.
Well, database abstraction is both the tip of the iceberg and a slightly unique case… insofar as you have to deal with something somewhat beyond your control as a developer, you don’t get to choose how the back end works. I tend to ignore database abstraction beyond using PDO for this reason.
Even if you do have a 100% working DAO that theoretically allows you to use any database, in practice it wont. Different databases have different features, strengths and weaknesses. Query optimisation specifically makes this a nightmare. Compare the optimal use of In()/OR, unions, joins, across databases and the useful features which are only implemented by some (GROUP_CONCAT for instance) means that by trying to make it work on multiple databases, in my opinion is just shooting yourself in the foot.
The better option is to abstract the queries away from the domain logic (probably using an ORM). That way, they’re both reusable, replacable and easy to find if you ever do need to switch databases.
So, I just read up on Domain Logic and looks like this is answer to one of my problems. I found more information at http://onlamp.com/pub/a/php/2004/08/05/dataobjects.html. Although, that example doesn’t still show how to deal with issues like “limit” in MySQL but I’ll be doing more reading on that and see how I can use DataObjects and still be able to use different databases.
I am also using Zend framework in my app so I can also use their DB class for further abstraction.
Hope I understood it as you meant.
The next question that came up is using PDO. I am behind on my PHP knowledge so I’ll be reading up on it. By using PDO, do I not need to worry about whether I am using MySQL or MSSQL? Or do I still need to do proper queries for those (like “limit” in MySQL)? I have read about PDO in many places but I think I am not clear about exactly what it entails.
Thanks all for your help. Any more information that can help with these decision will be great and appreciated.
The simplest method of separating the data access from the domain logic is, as i said an ORM. Mostly they will provide “finders” So you’ll have something like $user->findById(123); which would do the equivalent of SELECT * FROM users WHERE id = 123; Finders can be defined to do anything, limit offset, query, etc. This keeps the data access logic out of the domain logic allowing you to potentially substitute the data source entirely… and your finders are reusable. As there’s no SQL at the domain layer, the $user variable could be referencing an XML file, a web service, etc.
As for PDO, yes it allows you to use any database, theoretically. But if you’re using anything more than basic query features it won’t actually let you port an application at the switch of a button.
I’ll read up on that. And if I am assuming correctly, ORM, DataObject and DAL can go side by side to have the best of both. Or is it overkill?
thanks
EDIT: or maybe something like http://redbeanphp.com/#/Tutorial that I just found from Google. Looks easy to use and by looking at example I can see what you mean (I understand better by example so was having trouble understanding; not sure if that’s good or bad :))