I've seen in one framework (I do not remember in which Kohana or Symphony) following approach for AR.
When AR classs is generating always two classes are generated.
First class which is representation of DB structure, second where use can add whatever he wants to AR (e.g. some validations, mapping etc).
This approach is more flexible and there is a one BIG advantage of this approach:
when database is changed (e.g. some fields are added) it is easy to regenerate class which is representation of DB structure without touching second class which may consist a lot of user model data related logic!
Thx @me23. I know that I can achieve the result this way. My proposal was to add this as a default behaviour for framework. You know that programmers are sometimes lazy (sometimes they forget to do obvious things) Two classes approach is IMHO good because it is just safe. You will never overwrite your logic by regenerating new AR class.
Regenerating with yiic is currently not a good idea, and will destroy all changes (relations, validation etc). But since a generated model is quite basic, I currently don't see a reason to regenerate. Adding a field to an existing model is easier.
Yes Maxximus i know that regenerating will destroy relation etc, but thats why i have said, that i extend a "business"-class from the "model"-class and store the relations and validation-rules in "business"-class. Regeneration will only overwrite the "model"-class. On large Projects, on stress or by more team-members the danger is always present to "forget" to add a field in model-class. But the database tell always the truth and so regenerating the model-class is in my opinion safer.
This is a misunderstanding. What the original poster was trying to say is: Symfony - or rather the integrated Propel ORM - creates 4 classes for every DB table:
[font=“Courier New”]BaseFooPeer[/font] - represents table ‘Foo’ structure, contains only static members, overwritten on regeneration
[font=“Courier New”]BaseFoo[/font] - represents a record in table ‘Foo’, overwritten on regeneration
[font="Courier New"]FooPeer[/font] - initially empty, extends BaseFooPeer, kept on regeneration
[font="Courier New"]Foo[/font] - initially empty, extends BaseFooPeer, kept on regeneration
The developer adds his/her extra behaviour/logic to the latter two classes, so it is separated from the generated code and never overwritten.
Just extending yii AR classes in the same way, like me23 suggested, will not do as soon as relations come into play.
Let there be a yiic-generated AR-class ‘Foo’. Now let’s add some custom code to a derived class ‘MyFoo’.
There is also a ‘Bar’ that can belong to a ‘Foo’. Now, if you ask a ‘Bar’ for it’s ‘Foo’, it will give you a ‘Foo’, not a ‘MyFoo’, it won’t even “know” that such thing as a MyFoo exists.
So you have to override the relations()-method for each AR-Class related to an extended AR-class. And you have to update the relations manually from thereon. Just forget one and you will be dealing with a mix of Foos and MyFoos, representing the same thing though acting differently - have fun debugging!
It’s obvious that yii has not been designed for reiterating the different kinds of code-generation. Maxximus doesn’t see the need, I do:
If a project is small and requirements can be precisely assessed up front, then a top-down approach may be appropriate and your DB schema won’t change much throughout the development.
If the project is bigger and you chose an agile approach, your DB schema can and will change a lot. Now if you can’t regenerate, it means you will be writing most of the DB model code by hand, loosing one of the key benefits of ORM in my view.
Let me add my vote to this. I would love to see something along the lines of a base model and an extended model (as described in literal’s post) added to Yii.
I have been working on a long term project with Yii for 6 months now, and have needed to keep pace with Yii upgrades, as well as make modifications to the database structure as the project grows. I think we are currently basing the project on our 4th Yii version, having started on 1.0.10 and currently using 1.1.2.
Having the ability to regenerate base classes without losing custom functions when upgrading the Yii framework or modifying the database would make upgrading AND modifying much quicker, and less painful.
I love Yii, but every time an upgrade comes out I am left wishing I was starting this project with the latest version.
Personally, I think just 2 model classes would be needed. the BaseModel and Model (extends BaseModel), with only the BaseModel file being overwritten on generation.
I very much agree that encapsulating generated table-specific code in its own class would be a substantial improvement. I’d go so far as to say that all generated classes could valuably be split between auto-generated and end-developer maintained layers – I can’t afford the time to sift through Yii upgrades to incorporate would-have-been-generated code, so I presume that I’m not getting the full benefit of upgrading.
Thank you for such a clear reframing of this thread [member=‘literal’].
An approach that I have taken in the past was to create a dynamic model class where the Select statement, or an array could define the construct of the desired object. Taking a dynamic approach, like everything else, has its place in development as it makes prototyping a bit simpler, but could create a bit of overhead at run-time. I am creating one for my own use as a extension for now, but it would be cool -yes, just a want- to see this as a standard option in the framework.
I appreciate that Gii basically does this very mechanism in class generation - a feature that I like allot about Yii and have plans to leverage, but for look-up tables, for views that could be feed by a Query By Example session from a client and, as a matter of a developers personal preference, it could be a great addition to the Yii arsenal.
To note, this layer of class would not need to be generated, would not be a rational target for customizing (as previously discussed) as it would be more naturally for a developer to extend this class, nor would it be subject to being overwritten at at generation time-upon changing a database table and so on…