last week I have spend on creating a dynamic DB-to-OOP mapping engine in PHP.
It works pretty well. You define your DB, make PHP classes with same names, call one method, it generates the SQL, fetches the result, and creates the appropriate objects from it.
You can apply different query filters, it automatically joins parent tables, translation tables (for multi-language db), value tables (which don't have classes on PHP side), it has a build-in filter validator (so only valid sql are passed to the db) etc. etc. etc.
It is nothing revolutionary, but with some careful table/class naming it gets the job done pretty well.
Later on, I opened my cPanel and had a look at PEAR modules, and I can see there are many modules that deal with databases. I'm new to PEAR, haven't used it before.
Can anyone tell me if there is a module that does something similar, like I described above?
Just to make things clear, I'm not looking for a proxy generator, which will generate the code for the classes, but a dynamic mapper, which does everything pretty much on-fly.
http://www.doctrine-project.org/ Is this what you're looking for? An ORM?
Pear::DB?
Related
I have a design discussion with a collegue.
We are implementing a PHP MySQL database application. In the first instance we have written the Insert Get Update Delete, SelectAll and Search functions for a particular table, writting the table and fieldnames in the code, with several php files, one for the object class, one to draw the HTML table for that table, one for editing a row of that table, one containing the above functions, etc.
The disagreement comes as I have now written generic functions that read/write from the database and draw the HTML taking the table name as a parameter, letting these functions discovers the fieldnames from the database or class. So now that code can be used for any table, with any fields without having to manually go in change each function that needs alteration. I understand there will be cases where more table specific functionality is needed, and this I think that should be done as requirements arise, integrating common parts where possible.
My collegue on the other hand is adamant we should keep a set of files separate for each table, i.e. around 5 php files for each table. The read/write functions written differently in each case, with the need for any changes required for all tables to be affecting 5 x number of tables amount of times.
I can certainly say there will be more than main 15 tables in the database that will at least need basic funcionality.
What approach do you think is most appropriate?
One of the important principles in programming is DRY : Don't Repeat Yourself. So, everything common to several usecases should be written once, in a single location.
Now, I've never had to develop an application where each database table had the same, generic, crud pages. If it were the case, it wouldn't be a functional application, but a database management application. Are you sure you aren't redeveloping phpMyAdmin?
If you need the same code to handle several base operations on several tables, I would say you shouldn't write that code more than once : no need to repeat yourself :
it would take more time writing the application
it would take more time (and possible cause more bugs) when maintaining it
A possible solution could be to put as much common code as possible into a single class, common to many tables ; and, then, have a specific class for each table, that would extend that common class.
This way :
The common code would be written only once
Each table could have its specific code
The common code could be overridden for a specific table, if necessary.
About that, see the Object Inheritance section of the manual.
About that common class idea, you could even go farther, and write pretty much no code at all, if your CRUD is generic enough : there are ORM frameworks that might do that for you.
For instance, you might want to take a look at Doctrine.
We're on the first stages of development, and we don't have the complete functional specifications for the web application we're developing. Yes, we know, but it's not our fault.
So, we're building some parts keeping them pretty simple and straight-forward so we can build on top of that when we have more details on what to build.
We have a section for clients, for ads, for users, ... and I wanted to keep things separate because we don't know what's coming in the future. Yes, at the moment we have only a few fields and some basic listings and editing pages, but all that will grow.
It's not that I don't want to implement some generic code that we can reuse. It's that we don't know yet what will be the limitations in the near future, and I don't want to write generic code that we'll have to parametrize intensely.
For example, Alex built a generic Update method to which you pass an object and it will create an UPDATE SQL statement and execute it. OK, that's cool, but that doesn't work for the Users section of the web app because we store the password encoded. First, it won't encode the password. Second, if you edit a user and don't enter anything on the password and password-confirmation fields, the old password will remain. So, we have a problem with the generic Update method, and as I see it there are two possible solutions:
a) Parametrize the Update method so if it is modifying a user, keep the password if the password on the object is blank. And encode the password, of course.
b) Override the Update method for the child class.
Alex's implementation didn't use inheritance and he used the generic methods in a static class he'd call this way DataAccess::Update($object);. The method takes the table name from the class name as he modified the database to make them match (I prefer "Clients" for the table and "Client" for the class). So, option b is not possible with Alex's implementation.
The way I was trying to build it was keeping separate Update methods for each table. Yes, I was repeating myself but, as I said before, we don't have a full specification, so we don't know how it's going to grow. We have an idea, but we don't have the exact details.
So, the point here is that I don't want to write generic code until we have a much more detailed specification so we can evaluate what can and what cannot be shared between the parts.
Not all sections of the web app work the same and, as JB Nizet said: "If it were the case, it wouldn't be a functional application, but a database management application."
And I can tell you for sure this is not a database management application, even though Alex would say "we're just building a database app." Well, maybe, but a database application is not only showing/modifying the tables. And now, views won't solve all problems.
Again, as JB Nizet said: "If it were the case, it wouldn't be a functional application, but a database management application."
And now I'm repeating myself again, but this time there's no reason for that.
Thanks for your time.
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.
Is there a tool or script that generates and syncs database out of PHP models, just the way like Django does it for Python?
I'm aware of tools that generate databases out of XML, YAML, etc... I don't want it. I want to write production code on PHP, describing models, then run "syncdb" and get the database, that is ready to work with described models.
I remember playing with http://redbeanphp.com/ a while ago. You'd create your classes in PHP, add relationships to them via class variables, and it would take care of creating the database and keeping it updated.
There is no such thing as "PHP Models". There are various ways to describe a database model, but none of them are standardized, so it's not possible for such tool to exist.
There are, however, tools that generate database tables out of models in some frameworks. However, those are specific to the framework's models (usually written in xml or yaml, by the way).
And anyway, database design is usually a more complicated issue than just "making it work with models", so unless you have a rather verbose model (describing indexes, data types, relations etc.), a tool automatically generating tables wouldn't be useful in production.
Yii framework has something similar, called Gii. It auto generates other stuff too and you can add your own custom generators.
More info here: http://www.yiiframework.com/doc/guide/topics.gii
Can anyone recommend a good PHP paging class?
I have searched google, but have not seen anything that matches my requirements. Rather than "rolling my own" (and almost surely reinventing the wheel), I decided to check in here first.
First some background:
I am developing a website using Symfony 1.3.2 with Propel ORM on Ubuntu 9.10. I am currently using the Propel pager, which is OK, but I recently started using memcache to speed things up a little. At this point, the Propel pager is of little use, as it (AFAIK), only works with Propel objects.
What I need is a class th:t meets the following requirents
Has clean interface, with separation of concerns, so that the logic to retrieve records from the datasource (e.g. database) is encapsulated in a class (or at least a separate file).
Can work with arrays of objects
Provides pagination links, and only fetches the data required for the current page. Also, the pagination should 'split' the available page links if there are too many. For example, if there are potentially 1000 possible page links, the pages displayed should be something like FIRST 2,3 ....999 LAST
Can return the number of all the records in the table being queried, so that the following links are available FIRST, LAST (this requirement is actually already covered in the previous requirement - but I just wanted to re-emphasise it).
Can anyone recommend such a library, if they have used it succesfully in the past?
Alternatively, someobe may have 'hacked' (e.g. derived from) the current Propel pager, to get it to do the things I listed about - please let me know.
Not sure if this will fit the bill, but both sfPropelPager and sfDoctrinePager extend from the sfPager class, which provides forward/back motion and paging etc. You should be able to either use sfPager directly, or extend from it in the same way as Doctrine and Propel do with your array of elements to provide paging.
Typically, as this looks to be a "non-standard" use-case, there's zero docs on the Symfony site about it save for the API documentation, but the API docs look pretty comprehensive, and I'm sure the Doctrine/Propel examples will be able to guide you in the right direction!
I've been using and recommend the PEAR::Pager package which is able to do what you need.
You need to down into the sfPropelPager (or sfPager directly) code, understand how it works internally, where dynamic data is used and how you can get it working with memcache.
I don't know memecached but can't you cache propel records directly ? (I know they're huge :D)
My answer point by point :
1 : sfPager is DB agnostic as it is used by both sfDoctrinePager and sfPropelPager, you can use it for a working and tested base.
2 : sfPager should with work with arrays, the model class property referenced in it is not used anywhere. Cf source
3 : Providing pagination links is against separation of concerns, it paginates on objects and links are generated elsewhere (view file, helper, etc.).
You can display them as you want without modyfing the pager class or its descendents
4 : First and last access are provided by sfPager class
I know I can sound like symfony preacher, but this is the way we usually od things working with such a framework. As you wrote, do not reinvent the wheel !