When developing bigger systems in team, often, there are separate guys for implementing application and database stuff. In such cases, database design and implementation appears first: database developer designs and creates tables with some modeling tool. As an application developer, you are tempted to create and add the rules from scratch in your app code. However, then you are duplicating the work, because actual column type and length restrictions are already set in every DB table. Also, if database developer is responsible and is updating the DB then there might happen bugs when you forget to update the rules in app side. So, you just need to grab those rules from existing database schema tables and "mount" to your input validation (or model) classes.
So, the question is are there any general approaches (and examples), libraries or frameworks that show how this should be done. I'v looked at Codeigniter framework that has rules, but those rules are not captured from existing db, you need to define them explicitly.
PS. Most preferable would be simple (but sufficient) solutions because I already use a lightweight Codeigniter-like framework, and I don't want to rely on heavyweight approaches.
You could try Zend_Db_Table_Abstract. While the Zend framework requires some initial setup, you can use only the pieces you require for your project (as opposed to some other PHP frameworks). You can use the describeTable() method to discover something about the table structure, and you can overload the insert() function to explicitly check types, or do whatever other validation you require.
Another potential option is fSchema, part of the flourish library. I have had good experiences with flourish in the past.
Both are modular, well documented, and easy to use.
Related
We are developing a substantial PHP web application using the Zend framework.
At this time, the product is starting to stabilize and we are moving away from quick-and-dirty setups in order to avoid regressions. In particular, we are now working on top of a single shared database that everyone edits. We want to get rid of this ASAP.
The Zend framework does not seem to support the classic RAD (Djangoish) mechanism where you define your data models and then it creates the tables for you. So we are thinking of using an external ORM tool that will do this.
We could have our schemas and initial fixtures defined in plain SQL but this is a) verbose b) error prone c) too low level and d) problematic because we must maintain different versions for every supported database backend.
So we are thinking of using an ORM like Doctrine or Propel to define our models and create tables with their initial data using the chosen framework's dialect. The application uses the Zend tool for ORMing so consistency between both tools would have to be maintained manually, but since changes are more gradual now this doesn't seem like much of a problem.
So, far, we are evaluating Doctrine and Propel for this task. Any suggestions about other ORMs that we missed? Maybe a different approach altogether for the task at hand?
Thanks!
Gonzalo
I really love RedBean. You keep your database models in pure php and it keeps track of everything.
RedBeanPHP is an open source ORM tool
for PHP. It focuses on simplicity and
ease of use. What makes RedBean unique
is that it creates your database
schema on-the-fly. It scans your data
and adjusts the column types to fit
your object properties. If your models
are stabilized you can freeze the
database. This way RedBean is easy to
develop with but is also extremely
fast on production servers.
Since I've found this ORM, I don't use doctrine any more.
http://redbeanphp.com/
We are evaluating some PHP Frameworks for a productive website. CakePHP looks pretty interesting but we have no clue if it fits our needs.
Basically when you check the documentation and the tutorials for CakePHP it looks really promising. Nevertheless there were always some things that bugged me with frameworks so far, maybe someone who already used CakePHP in a productive project could answer this questions for me?
Writing/Reading data for single records looks pretty neat in CakePHP. What happens if you want to read data from multiple tables with complex conditions, group by, where clauses? How does CakePHP handle it?
Scaffolding looks pretty nice for basic administration interfaces. How easy is it to customize this stuff. Let's say I have a foreign key on one of my tables. When I create a scaffolding page, does CakePHP automatically create a dropdown list for me with all the possible items? What if I want to filter the possible items? Let's say I want to combine two fields into one field in the view part, but when I edit it, I should be able to edit both of those fields individually. Does this work?
Do you think you were faster in development with CakePHP than with let's say plain PHP?
I've used CakePHP, Zend Framework and I've also written applications "from the ground up" with nothing more than homegrown classes and such. To that I'd like to mention that I use CakePHP regularly so, take that as you will.
(Writing/reading data, complex conditions) You can certainly do everything you mentioned. Others are correct in that it attempts to abstract away SQL operations for you. I've yet to have a query that I couldn't translate into Cake's "parlance"; complex geospatial queries, joins, etc.
(Scaffolding, complex conditions) The scaffolding is really only meant to serve as a "jump start" of sorts to help make sure your model associations and such are setup correctly and should not be used as a permanent solution. To that end, yes it will do a fairly good job at introspecting your relationships and providing relevant markup.
(Faster development) Of course. There is a large community with a vast number of plugins or examples out there to help get you started. Regardless of what you pick, choosing a framework will almost certainly make you "faster" if only for handling the minutiae that comes with setting up an application.
It really depends on your definition of "large". Are you referring to big datasets? A very complex domain model? Or just lots and lots of different controllers/actions?
Writing/Reading data.
Anything you can do with plain SQL you can do in CakePHP. It may not always be very nice to do, but at it's worst it's no worse than straight SQL.
But you really shouldn't be thinking about queries. You should be thinking about your domain model. CakePHP implements the active record pattern. It works very well if your domain model maps nicely to an active record pattern. But if it does not, then I would not recommend CakePHP. If your domain model doesn't map to Active Record then you will spend a lot of time fighting the Cake way of doing things. And that's no fun. You would be much better off with a framework that implements a Data Mapper pattern (e.g. Zend).
Scaffolding
Scaffolding is temporary. It does handle foreign keys (if you define them in the model as well as in the database) but that's it. You can't modify the scaffolding. But, you can bake them!
When you bake a controller or view then you're basically writing the scaffold to a file as a jump-off point for your own implementation. After baking, you can do anything that you want. The downside of baking is that it doesn't update anymore when the models or database changes. So, if you bake a controller and views and you add fields to your model, then you need to add those fields manually to your controller and view code.
speed of development
In my case, I'm a lot faster developing a website in CakePHP then in plain code. But only if Active Record suits the application! See my first point. Even then, Cake is probably still faster, but I would be faster still with a better suiting framework.
Some other thoughts
large datasets
If you have very large datasets and big query results then Cake can be a problem. A find() operation wants to return an associative array, so all the rows are read, parsed and converted to arrays. If your result set is too large you will run out of memory. CakePHP does not implement ResultSet objects like many other Active Record implementations and that is a definite downside. You end up manually paging through your own data with subqueries. Yuck. Wich brings me to my next point:
arrays
Learn to love them because CakePHP does. Everything is an array and often they are large, complex and deep. It gets really annoying after a while. You can't add functions to arrays so your code is more messy than if CakePHP would have used nested object instances. The functions you can add to those objects can help keep your code clean.
oddities and inconsistencies
CakePHP has some real nasty stinkers hidden deep within. If Active Record suits your application then you will probably never run into them, but if you try to mold CakePHP into something more complex, then you will have to fight these. Some examples:
HABTM through a custom model uses the definition from the other side of the relationship that you're working on.
Some really odd places where your before/after triggers aren't called (e.g. not from an updateAll)
odd Model->field() behavior. It always queries from the database. So, be careful about updating model data without immediately saving it to the database. Some CakePHP functions fetch data from Model->$_data and some use Model->field(). The result may be entirely different resulting in some very hard to track down bugs.
In short
I would highly recommend CakePHP even for "large" sites, as long as your domain model fits nicely on top of Active Record. If not, pick a different framework.
Since you are asking for opinions, then I have to say that I advise AGAINST CakePHP.
My biggest gripe with it, is that it's still using PHP4 (written in and code generated). So, why go backwards? It is compatible for PHP5, but the framework itself revolves around PHP4.
I would recommend taking a look at Symfony or Zend. Symfony being the best if you want more structure in place - it forces you to adhere to the MVC structure that it has established.
The alternative is Zend, but it's more of a 'do-it-yourself' framework, or rather more of a set of libraries. You need to put it all together yourself, and it doesn't have any strict structure like Symfony.
There are obviously other frameworks, but I recommend the fore-said. Another one that you may want to look at is Codeigniter.
CakePHP tries to abstract away the database, so you write very little SQL (however, you write a lot of SQL snippets).
The basic process is to define your models, then define the relationship between models (hasOne, belongsTo, hasMany, hasAndBelongsToMany). You can put any conditions or default ordering on these associations you like. Then, whenever you fetch a row from the database, any associated rows are automatically fetched with it. It's very easy and powerful.
Everything comes with a bunch of configuration options, giving further flexibility. For example, when fetching data there is a recursion option which takes an integer. This value is how many associations deep Cake should fetch data. So if you wanted to fetch a user with all their associated data, and all the joined data to THAT, it's trivial.
Pretty much anything can be overridden on defined on the fly, and you can always fall back to writing your own SQL, so there's nothing Cake prevents you from doing...
I've not found much use for scaffolding. The answer to your question is yes, it'll auto populate joined dropdowns, etc. But I've never used it as a basis to build an interface. I tend to use a database tool to populate data early on rather than scaffolding.
I've built and also maintain several web-apps on CakePHP, and it is without question faster than 'rolling your own'. But I think that's true of any decent framework!
Unfortunately one of the weaker points is the documentation. Often you need to Google for answers as the official documentation is a bit hit-and-miss at times.
Just go with Yii framework, it's the best in this category.
(Note: This is a subjective question. You are asking for opinions. So I hope you don't mind if I give mine.)
(Edit: Ops. I mixed Cake with CI)
I used Code Igniter a while back. It did everything it should and was fairly easy to understand. However, for big projects, it lacked features. Many CI proponents say that this is it's strength as it keeps it fast and can make little RAM. This is true.
However, after developing one application with it, I found myself looking elsewhere so I would not have to write code that must have been written before. I looked at CakePHP and found it too restrictive and automagical. In particular, I needed some kind of ACL functionality. This lead me to Zend Framework. I learned that it is loosely coupled. I can include only the files I need. I can also make use of Zend_Application for large projects. It's object oriented design is a must when developing and maintaining large projects.
Yes, CI and CakePHP helped me to develop faster than with plain PHP. However, there are much more powerful frameworks. I hear and see good things about Symphony. There are quite a few more. I'm sure others will point them out.
I am fond of dbstructure definition of msaccess which lets defining at once and creating the data entry forms, datatables and reports at once easily.
I have been searching for some framework which would generate the data entry forms, data tables and reports easily. I guess the only thing I need to define is complete datatable structure.
Is there any like that or better one than that?
EDIT:
well i am afraid that PHP frameworks have been limited to programmers only. I would like to extend it with some automated functions like autoform in msaccess which would generate data entry form, auto report for data listing. So that my development time would be again some less. I found doctrine nearly matching my specification but not sure as i haven't fully explored doctrine
Cake offers both "hard" (bake) and "soft" scaffolding, which should be very close to what you want. It's still only meant as a quick proof-of-concept tool and to get you up and running faster so you can concentrate on programming the business logic. It's not meant as a hands-off solution nor to be used in production.
What you seem to be looking for is a database frontend like phpMyAdmin or SQL Buddy, not a PHP framework.
Symfony provides an admin generator that builds all the forms on the fly and it will also update itself when you change your db schema. It is based on doctrine which you say you looked at so that would make things a bit easier for you.
My team have to maintain a large php application that was very poorly written. It is a mix of html, javascript and SQL on top of a large poorly designed database (ex. it has a table with few hundreds of columns). The only advantage of the codebase is that it works.
We are constantly bug fixing and rewriting parts of it.
I would like to give a structure to the rewrites we do, so I've though about integrating an mvc framework in to the codebase. Could you suggest any good framework for environment?
Here is a list of things that the I would expect from such framework:
The API must be very stable. We can't afford to rewrite the code on each release.
Custom session management or at least working on standard $_SESSION[] (To be able to talk with old code).
Custom authentication.
Using the raw SQL should be well supported (The database is hard to represent in terms of objects).
It shouldn't assume that I will have a table per controller.
I suggest Zend Framework for this purpose because it is a glue framework. With ZF you are not forced into the harness of how the framework expects you to work with it. You can pick what you want and gradually replace your legacy code with code from ZF. It also supports all the things you mentioned.
In addition, I suggest to run the various QA Tools found at phpqatools.org to support you in debugging and refactoring.
Framework comparisons
http://www.phpframeworks.com/
http://php-frameworks.net/
I'm echoing Zend just to list how it fits your specific requirements:
The API must be very stable. We can't afford to rewrite the code on each release.
As mentioned, the API tends to be stable between minor releases. Major releases with changes shouldn't be hard to integrate.
Custom session management or at least working on standard $_SESSION[] (To be able to talk with old code).
Zend_Session does exactly what you want. The default session store is $_SESSION to which Zend adds a namespace concept. Your existing code should be fine, and any new code can use the Zend object to ensure there are no variable name overlaps.
Custom authentication.
Zend_Auth has a few authentication backends, but it is designed to allow you to implement your own auth.
Using the raw SQL should be well supported (The database is hard to represent in terms of objects).
Zend_DB implements the table gateway pattern which will allow you to access the data via object; however, you can also just use SQL directly and get the results as arrays.
It shouldn't assume that I will have a table per controller.
Zend_Controller and the rest of Zend's MVC implementation make no assumptions about the Model, leaving that completely up to you. I'm sure some people don't like that, but it is the one area of MVC design that varies greatly from project to project - so that's left completely to the developer. You could extend some of the DB classes, or just use the existing DB access code.
That's an example of the pick-and-choose mentality of the Zend Framework. You really can use any of the library by itself. That should work well with your project. For example, you could use Zend_View without the rest of the MVC classes just to move your presentation into templates. Or just use Zend_Auth to replace the existing Auth system. With Zend you can slowly move your project into a more structured state, little by little.
Can someone please derive a concrete example from the following:
http://www.urdalen.com/blog/?p=210
..that shows how to deal with one-to-many and many-to-many relationships?
I've emailed the author some time ago but received no reply. I like his idea, but can't figure out how to implement it beyond simple single table relations.
Note: I don't want to use a full-blown ORM. I like doing my SQL by hand. I would like to improve the design of my app code though. Right now each domain object has its own class full of queries wrapped in static methods. They just return scalar, 1d-array (record) or 2d-array (recordset) depending on the query.
The problem of ORM's (The impedance mismatch, as it's called) is precisely with relations. In an object graph (In-memory objects), relationships are pointers to other objects. In a relational database, relationships are reversed; This makes it impossible to do a simple mapping between the two models, and that is why ORM's are so complex.
If you want to stay close to the database (avoiding an ORM), then you shouldn't try to abstract relationships away. The way I write datamappers is something like the following:
$car42 = $car_gateway->fetch(42);
$wheels = $wheel_gateway->selectByCar($car42);
In contrast to the ORM way:
$car42 = $car_gateway->fetch(42);
$wheels = $car42->selectWheels();
This does mean that the gateways end up in your client-code, but it also keeps things very transparent and close to the database.
If you're looking for a simple and portable DataMapper ORM, have a look at phpDataMapper. It's only dependencies are PHP5 and PDO, and it's very small and lightweight. It supports table relations and some other very nice features as well.
Given your response to Tom's answer, I would recommend that you look at something like Zend Framework. Its ORM has a take it or leave it architecture that can be implemented in stages.
When I came to my present employer, they had an application that had just been completed months previously but had been through one or two prior versions and the current version had been in development six months longer than it was supposed to have been. However, the code base was mess. For example there was no abstraction between the database access logic and the business logic. And, they wanted me to move the site forward building new functionality, extending existing features, and fixing existing bugs in the code. To further complicate things they weren't using any form of sanitation on data inputs or outputs.
As I started to wade into the problem, I realized that I would need a solution to abstract concerns that could be implemented in steps because they obviously weren't going to go for a complete rewrite. My initial approach was to write a custom ORM and DAL that would do the heavy lifting for me. It worked great because it didn't intrude on the existing code base, and so it allowed me to move entire portions of the application to the new architecture in an unobtrusive manner.
However, after having ported a large portion of the user's area of our site to this new structure and having built an entire application on my custom framework (which has come to also include a custom front-end controller and mvc implementation), I am switching to Zend Framework (this is my choice though I am certain that some of the other frameworks would also work in this situation).
In switching to the Zend Framework I have absolutely no concerns about the legacy code base because:
I can build new models and refactor
old models (built on my custom
framework) unobtrusively.
I can refactor the existing
controllers (such as they are) to be
wrapped within a class that behaves
in a manner consistent with Zend's
MVC framework so that it becomes a
minor issue to actually begin using
Zend's Front-End Controller.
Our views are already built in
Smarty so I don't have to worry
about separating controller and view
logic, but I will be able to extend
the Zend Framework so that I can
render existing templates in Smarty
while building new templates in
straight PHP.
Basically, Zend Framework has a take it or leave architecture that makes its a joy to use within existing projects because new code and refactored code doesn't need to intrude on existing code.