You are facing the same dilemma I faced about 6 months ago. If you
search back in the archives for "Another Model Design Thread" from the
9th December, there is some related info about whether it's better for
models to be an "is a" or "has a" relationship with Zend_Db_Table_Row
(ZR from now on).
I did exactly what you proposed in your second idea, and made __get
and __set throw exceptions. However, this throws up another problem
when you extend the class as you cannot just call parent::__get/__set
in your extended class.
Your first solution will indeed provide you with BC, and yes it could
be seen as misleading that you are invoking a method when you are
accessing properties, but some languages actually provide a mechanism
for doing just that and is also a big part of OO programming in that
your other classes calling upon said property need not be aware of
what goes on inside the other class.
I also think that ZR is a bad way to implement anything more than
models for trivial database access. It completely evades the reason
for using Private, Protected and Public access. For example, as I
mentioned in the other thread, why would you want any other part of
your program to accidentally (or deliberately) change an id column in
the database (especially if it was an auto increment / sequence)?
The solution I finally chose was to not use Zend_Db_Table_Row in my
models at all. I created my models directly from my business logic
whilst keeping the database in the back of my mind. So I had read only
id and last_updated values using protected properties and public get
methods. Then to facilitate the loading of these protected values from
the database (or any other external source) was to allow the passing
of a data array into the constructor. Loading and saving was handled
by another factory type class (ie, my User model was loaded and saved
by a Users class, normally with static methods).
Now that I have much longer to think about the solution, I would
probably modify it to use an instance of ZR in the constructor (or
create a new instance) instead of and array - thus cutting out one
level of assignments. This would also allow you to use the ZR instance
to store your class properties instead of creating each one separately
and then having to map them back to the ZR instance when you save.
Hope this makes sense, kind of rushed the last bit as I am heading out.
Paul
On 16 Jan 2009, at 08:54, Jaka Jančar wrote:
> Hi!
>
> We all know that getting object vars directly usually isn't a good
> thing, but for Zend_Db_Table_Row this has somehow managed to elude
> us. Almost everyone (incl. me) just uses the $row->field syntax.
>
> The situation I'm now is is that I want to hook some extra behavior
> to rows, when a field changes. So for a field "name", I add a
> setName setter. The problem is that $row->name" may still be used
> directly from the outside, which I don't like.
>
> What is the recommended approach?
>
> I thought about modifying __set and __get in My_Db_Table_Row to
> check for a setter/getter and automatically use that, if available.
> This would maintain BC for code using my rows, but is quite
> misleading since it looks like you're accessing a simple property,
> when in fact you're invoking a method (which might cause side
> effects).
>
> Another idea was to modify __set and __get to just disallow direct
> manipulation if a setter/getter is present and throw an exeption,
> which would be functionally equivalent to making the property
> protected/private (except that it can't be used from within a class
> either).
>
> Will anything be done in this direction in ZF?
>
> Regards,
> Jaka
没有评论:
发表评论