Created
January 7, 2012 14:33
-
-
Save yjeroen/1574900 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class foo extends CActiveRecord | |
class User extends foo | |
class Post extends foo | |
userController User Post | |
========== === === | |
{ | |
function actionThatAddsUserAndPosts | |
{ | |
$userModel = new User; | |
$userModel->save() | |
{ | |
$relatedToUser = new Post | |
$relatedToUser->save() | |
{ | |
stuff | |
} | |
stuff | |
} | |
stuff | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
[15:23] <tom[]> yjeroen: so the scenario we are worried about is...
[15:23] <tom[]> controller calls foo::save()
[15:24] <tom[]> foo::save() calls foo::save() ?
[15:24] yes, foo::save() calls relatedSave() (in my case), relatedSave() can call save() again in some cases to save a related model
[15:25] == csalvato [~csalvato@c-98-202-67-16.hsd1.ut.comcast.net] has quit [.net .split]
[15:25] == Sil4nc4 [raelter@bluestar.aelter.be] has quit [.net *.split]
[15:25] foo::save() need to use transactions internally, but it should not be affected if a transaction is already started in the controller
[15:25] == csalvato [~csalvato@c-98-202-67-16.hsd1.ut.comcast.net] has joined #yii
[15:25] == Sil4nc4 [raelter@bluestar.aelter.be] has joined #yii
[15:25] == rookie84 [779a2641@gateway/web/freenode/session] has joined #yii
[15:25] <tom[]> in oop, are we allowed to say "call" or do we have to say "invoke"?
[15:26] pff, teach me
[15:26] == rookie84 [779a2641@gateway/web/freenode/session] has quit [Changing host]
[15:26] == rookie84 [779a2641@gateway/web/freenode/ip.119.154.38.65] has joined #yii
[15:26] hi tom, yjeroen
[15:26] I have no idea whats the right usage/wording
[15:27] hi rookie
[15:29] tom[], correct me if Im wrong.. If I think about it: I think you call it "calling a method" if you call it outside its class, and invoking if you call a method inside its own class?
[15:30] I have no idea on the precise right terminology
[15:30] <tom[]> yjeroen: https://gist.github.com/1574882
[15:30] <tom[]> i remember when people were inventing oop and the struggle they had to find terminology
[15:31] <tom[]> so can we use that diagram as a model? does it suffice?
[15:31] how old are you tom[], if i may ask?
[15:31] <tom[]> me 47
[15:31] in your diagram, are foo, bar and CAR instances of a class, or different classes?
[15:31] <tom[]> and my mother taught me to program computers
[15:32] <tom[]> yjeroen: sure
[15:32] hmm then your probably 27 :p
[15:32] sure, which? :P
[15:33] <tom[]> lets say for now that the are both instances of Baz
[15:34] <tom[]> my mother was a peofessional programmer in the 1960s
[15:35] ill change it around and make the classname foo, so its the same as in the other code discussion
[15:35] ill fork your github
[15:35] <tom[]> no need
[15:35] <tom[]> it's justa diagram
[15:36] <tom[]> whiteboard
[15:36] !api Yii::setPathOfAlias
[15:36] Yii::setPathOfAlias() Create a path alias. http://www.yiiframework.com/doc/api/1.1/YiiBase#setPathOfAlias-detail
[15:36] <tom[]> blacknoard
[15:37] <tom[]> rookie84: and my fatehr taught me to build computers with this kit: http://www.nascomhomepage.com/
[15:37] Can path be relative? Getting bullshit that the file can't be found
[15:37] tom[]: how are you doing?
[15:37] I am currently migrating the 1.1.9 documentation
[15:38] <tom[]> swell!
[15:38] <tom[]> you?
[15:38] and I am going to migrate the return value the signature and the source link of the methodsw
[15:39] <tom[]> brilliant!
[15:39] tom[]: was she a designer or weaver?
[15:40] <tom[]> it involved both back then
[15:40] tom[] thats great ! :)
[15:40] <tom[]> to edit a punhed paper tape involved sticky tape and a small hand-held hole punch
[15:41] http://www.youtube.com/watch?v=P12r8DKHsak
[15:41] <tom[]> the day the tape reader was upgraded from a mechanical device to an optical one caused trouble because my mother had been using transparent sticky tape.
[15:42] tom[]: mom is still alive?
[15:42] <tom[]> sadly not.
[15:42] Since when is 255, 255, 255 black?
[15:42] sorry to hear that
[15:43] <tom[]> yeah. lymphoma. too young
[15:44] tom[], I think the diagram would be like this: https://gist.github.com/1574900
[15:44] <tom[]> great
[15:45] yjeroen: WOW ! thanks :) I managed to fix it:) both submitting the form and showing a success message! :) yey
[15:46] Sampa: great! :)
[15:46] <tom[]> we have to allow for either User or Post to either A: return false on detection of validation error or B: throw an exception?
[15:46] tom[], i forgot to add the parent::save()'s
[15:46] Is there something like Yii 2 in the works?
[15:46] <tom[]> !faq yii2
[15:46] People here know nothing about the status of Yii 2, its features, release schedule or degree of backwards compatibility. But they have confidence in one thing: the uncertainty in when Yii 2 will be ready for production use is big. They do not recommend you wait for it. Use the current version of 1.1.
[15:47] !faq yii1.2
[15:47] Something i do not know about.
[15:47] Ah, bot fail
[15:47] tom[], if either User or Posts doesnt validate, then the User needs to return false to the controller (with all val errors)
[15:47] but
[15:47] <tom[]> there's some info here:http://www.yiiframework.com/download/ and here: http://www.yiiframework.com/forum/index.php?/forum/42-design-discussions-for-yii-20/
[15:48] if a transaction is started outside the foo::save (ie in the controller), then User needs to rethrow the exception
[15:49] <tom[]> hold on
[15:49] <tom[]> we haven't got any exceptions yet
[15:49] <tom[]> one step at a time
[15:50] ok
[15:50] want me to add other stuff? or you want to go first?
[15:50] <tom[]> let's focus on Post::save
[15:50] <tom[]> sqy it detects that an exception IS active
[15:50] <tom[]> say
[15:51] an exception or a validation error?
[15:51] <tom[]> nonsense
[15:51] <tom[]> saw Post::save() detects that a transaction is already active
[15:51] <tom[]> *say
[15:51] <tom[]> damn my triping
[15:52] Post::save WILL detect that the transaction is active, because User::save started it
[15:52] == adlersd_ [~adlersd@189.29.69.203] has joined #yii
[15:53] <tom[]> if that is known to always be the case then there is no need for detection logic
[15:53] sure it is, because the save code is inside foo, not inside Post
[15:54] <tom[]> three outcomes: 1 happy. 2: validation error but Post::save knows it hasn't touched the DB state and 3: an exception is thown while it touches the DB
[15:55] yes thats true
[15:55] == adlersd [~adlersd@189.29.69.203] has quit [Ping timeout: 248 seconds]
[15:55] <tom[]> [that's not a need for detection logic. that's cruft leftover from the design.]
[15:56] <tom[]> [but no matter]
[15:56] <tom[]> [makes no difference for now]
[15:56] [ok]
[15:57] <tom[]> take 3 first
[15:57] <tom[]> an exception comes up from CAR in Post's try{}
[15:57] <tom[]> it's catch re-throws it
[15:57] <tom[]> right?
[15:58] whats CAR?
[15:58] <tom[]> CActiveRecord
[15:58] ah yes
[15:58] i thought the one that drives
[15:58] == freeayu [~quassel@115.172.207.134] has quit [Ping timeout: 240 seconds]
[15:59] i agree it should rethrow
[15:59] <tom[]> it has no sensible alternative
[16:00] But only in case #3 should it rethrow
[16:00] <tom[]> this is happening inside User::save()'s try{}
[16:01] <tom[]> and when this exception is caught by User's catch there are two possible cases, either Post owns a transaction or it does not.
[16:01] yes
[16:02] i dont understand what you mean by that last part
[16:02] <tom[]> Post throw an exception
[16:02] <tom[]> so we are now in User's catch
[16:02] <tom[]> OK?
[16:02] yes
[16:03] <tom[]> and User may or may not have begin a transaction
[16:03] yes
[16:04] <tom[]> if it did, it rolls it back. otherwise it must re-throw
[16:05] clear
[16:06] <tom[]> so we have covered the design in so far as handling exceptions that must lead to rollback
[16:06] That was all of case 3 right?
[16:06] <tom[]> yes
[16:06] so now case 2, rollback if any model isnt validated
[16:06] <tom[]> hold on
[16:06] <tom[]> summarize
[16:06] <tom[]> we have a simple nesting
[16:07] <tom[]> we could recurs this nesting as far as the stack is deep
[16:07] Yes, this would be the simple if($transaction) rollback else rethrow
[16:07] <tom[]> and all we need is local method variables and the connection's transaction state variables
[16:08] agreed
[16:08] <tom[]> good. i think we can now also say that case 1 is covered
[16:08] you mean case 3? case 1 was the happy case
[16:08] <tom[]> "also"
[16:09] What VCS do you guys use?
[16:09] oh also
[16:09] yes oc :)
[16:10] <tom[]> now about validation errors. inside a try{} somewhere in the chain of calls something detects a validation error and decides it cannot proceed. it hasn't touched the DB so it returns false insteaad of throwing anything
[16:11] yes, but because we call multiple saves, it still needs a rollback
[16:11] <tom[]> what it?
[16:11] <tom[]> you move too fast for me
[16:11] ah sorry
[16:11] lets save CAR::save in Post doesnt validate
[16:12] then Post isnt saved
[16:12] <tom[]> if Post returns false, it is saying that as far as Post is concerned, there is no need for a rollback
[16:12] but User is, because that validated true
[16:12] <tom[]> it is then up to User to decide if it knows if a rollback is needed
[16:13] so User needs to rollback if Post:save is false
[16:13] <tom[]> think generally:
[16:14] <tom[]> we would prefer to find a design pattern, not just a design
[16:15] == xwurf [b2bed15a@gateway/web/freenode/ip.178.190.209.90] has quit [Quit: Page closed]
[16:15] <tom[]> if, when user receives the false return from Post it has touched the DB state, it must throw. if not, it should return false
[16:15] <tom[]> u=>U
[16:16] huh? If Post returns false, then it wouldnt have touched the DB state right?
[16:17] <tom[]> if Post returned false that Post is saying that it did not touch the DB
[16:17] it = Post
[16:17] yea
[16:17] <tom[]> but in general, in the caller of Post, at that point, that caller may or may not have touched the DB
[16:18] <tom[]> in this scenario the caller is User
[16:18] yes
[16:18] <tom[]> in your diagram User has not touched the DB before calling Post::save()
[16:19] <tom[]> but that's just one of the two cases
[16:19] <tom[]> in general, User shoudl return false if it hasn't touched the DB and should throw if it has
[16:20] The fact that Post->getErrors need to be send to User as well, do you want to include that now or later?
[16:20] <tom[]> once you have said OK
[16:21] ok, i agree on that as well
[16:21] <tom[]> swell
[16:22] <tom[]> so in regard to all the flow control we have discussed so far, User is the same as Post
[16:22] <tom[]> they are instances of the same thing
[16:22] yes
[16:22] <tom[]> i still don't see any call for state other than method-locals
[16:23] <tom[]> as far as passing validation errors up is concerned...
[16:23] <tom[]> imagine that we didn't need any transactional logic. that none of that was important to the application
[16:23] <tom[]> hypothetically
[16:24] what do you mean by transactional logic
[16:24] <tom[]> what would imagine that transactions didn't exist
[16:24] <tom[]> that you had never heard of them
[16:24] oh , yes
[16:24] <tom[]> becuase they weren't invented
[16:25] Then User could be saved, while Post would not. Or the other way around
[16:25] <tom[]> now, how would User pass validation error messages from Post up to contrller?
[16:25] <tom[]> forget about that stuff
[16:25] <tom[]> forget about databases for a moment
[16:26] <tom[]> how would User pass validation error messages from Post up to controller?
[16:26] The controller looks for errors in the User model.
[16:27] <tom[]> and would find Post validation errors in it?
[16:27] so the errors in the User model must also include the list of errors of the Post model
[16:27] yes
[16:27] <tom[]> does User need to do anything to achive this?
[16:27] <tom[]> or does Yii handle it?
[16:28] yii handles the part that the view displays the errors of the User model (because its userController)
[16:29] What I do now is:
[16:30] if(!Post->save()) $this->addError($post->errors())
[16:30] == erez_ [2e791f53@gateway/web/freenode/ip.46.121.31.83] has quit [Ping timeout: 258 seconds]
[16:31] if(!$post->save()) $this->addError($post->errors())
[16:32] <tom[]> if(!$post->save()) { $this->addError($post->errors()); return false; }
[16:32] Ok, agreed
[16:33] <tom[]> hot diggity
[16:33] <tom[]> we got ourselves a design pattern!
[16:33] <tom[]> ditch the behavior
[16:33] And I see where my thoughts went the wrong way!
[16:33] wait
[16:33] hmm
[16:33] <tom[]> oh no
[16:34] <tom[]> it's the "no, wait..:
[16:34] There is a complication
[16:36] the 'stuff' that saves the related model, also does $command->delete's
[16:36] so it always touches the db
[16:36] If I create a Main.php in the models would that just work?
[16:37] <tom[]> that's a simplification, not a complication
[16:37] enlighten me :)
[16:37] <tom[]> it's a special case of the pattern
[16:37] <tom[]> it means one of the instances of the pattern doesn't need to bother with the decision between validation error and DB exception
[16:38] you sure?
[16:38] lets take this case
[16:38] <tom[]> think not in terms of save and update etc
[16:38] Both User and Post arent validated
[16:39] as far as we talked about, there is no rollback
[16:39] <tom[]> think just in terms