I just wanted to thank both of you for working through this and figuring it 
out. Nearly five years later, CakePHP still has this issue with version 2 
and this code worked flawlessly. You guys rock!

On Wednesday, December 17, 2008 1:04:52 PM UTC-5, Martin Westin wrote:
>
> thanks for the modifications. I am happy it works for you too. 
>
> /Martin 
>
> On Dec 17, 5:56 pm, Matt Huggins <[email protected]> wrote: 
> > Your solution worked flawlessly!  I ended up making two small 
> > changes.  First, I changed your references for 'id' to $this->primaryKey 
> so that it can work with any model.  Second, I put the 
> > 
> > afterFind/_afterFind into app_model.php so that it will call the 
> > doAfterFind of any model that implements it, as per the following: 
> > 
> > class AppModel extends Model { 
> >         /** 
> >          * sigh... $primary doesn't work as designed in CakePHP RC2 :( 
> >          * this hack will manually go through and tear shit up 
> >          */ 
> >         public function afterFind($results, $primary = false) { 
> >                 if (method_exists($this, 'doAfterFind')) { 
> >                         if ($primary) { 
> >                                 foreach ($results as $key => $val) { 
> >                                         if (isset($val[$this->alias])) { 
> >                                                 
> $results[$key][$this->alias] = $this->doAfterFind 
> > ($results[$key][$this->alias]); 
> >                                         } 
> >                                 } 
> >                         } else { 
> >                                 if (isset($results[$this->primaryKey])) 
> { 
> >                                         $results = 
> $this->doAfterFind($results); 
> >                                 } else { 
> >                                         foreach ($results as $key => 
> $val) { 
> >                                                 if 
> (isset($val[$this->alias])) { 
> >                                                         if 
> (isset($val[$this->alias][$this->primaryKey])) 
> > { 
> >                                                                 
> $results[$key][$this->alias] = $this->doAfterFind 
> > ($results[$key][$this->alias]); 
> >                                                         } else { 
> >                                                                 foreach 
> ($results[$key][$this->alias] as $key2 
> > => $val2) { 
> >                                                                         
> $results[$key][$this->alias][$key2] = 
> $this->doAfterFind($results[$key][$this->alias][$key2]); 
> > 
> >                                                                 } 
> >                                                         } 
> >                                                 } 
> >                                         } 
> >                                 } 
> >                         } 
> >                 } 
> >                 return $results; 
> >         } 
> > 
> > } 
> > 
> > On Dec 17, 5:36 am, "[email protected]" 
> > 
> > <[email protected]> wrote: 
> > > Hi Matt, 
> > > I ended up creating a special set of functions for this. 
> > 
> > > afterFind() calls _afterFind() 
> > > _afterFind() locates the data and calls doAfterFind() 
> > 
> > > This works for what I use afterFind for. 
> > > I will only have one place to edit if the data-structires change or I 
> > > find I have missed something. 
> > > It makes my models a lot more readable. 
> > 
> > > The relevant code if you should find it useful: 
> > 
> > > in SomeModel: 
> > 
> > > // this just calls the "real" afterFind 
> > > function afterFind($data, $primary) { 
> > >     return $this->_afterFind($data, $primary); 
> > 
> > > } 
> > 
> > > // receives data as a flat array of fields, no Modelname or anything. 
> > > // run from _afterFind splits datetime-field sendat into senddate and 
> > > sendtime 
> > > function doAfterFind($data) { 
> > 
> > >     if ( !isset($data['senddate']) ) { 
> > >         $timestamp = strtotime($data['sendat']); 
> > >         $data['senddate'] = date('Y-m-d', $timestamp); 
> > >         $data['sendtime'] = date('H', $timestamp); 
> > >     } 
> > 
> > >     return $data; 
> > 
> > > } 
> > 
> > > // AppModel::_afterFind() 
> > > function _afterFind($data, $primary) { 
> > 
> > >     if ( $primary ) { 
> > 
> > >         foreach ( $data as $key => $val ) { 
> > >             if ( isset($val[$this->alias]) ) { 
> > >                 $data[$key][$this->alias] = $this->doAfterFind( $data 
> > > [$key][$this->alias] ); 
> > >             } 
> > >         } 
> > 
> > >     } else { 
> > 
> > >         if ( isset($data['id']) ) { 
> > >             $data = $this->doAfterFind( $data ); 
> > >         } else { 
> > 
> > >             foreach ( $data as $key => $val ) { 
> > >                 if ( isset($val[$this->alias]) ) { 
> > >                     if ( isset($val[$this->alias]['id']) ) { 
> > >                         $data[$key][$this->alias] = $this->doAfterFind 
> > > ( $data[$key][$this->alias] ); 
> > >                     } else { 
> > >                         foreach ( $data[$key][$this->alias] as $key2 
> > > => $val2 ) { 
> > >                             $data[$key][$this->alias][$key2] = 
> $this->doAfterFind( $data[$key][$this->alias][$key2] ); 
> > 
> > >                         } 
> > >                     } 
> > >                 } 
> > >             } 
> > >         } 
> > 
> > >     } 
> > >     return $data; 
> > 
> > > } 
> > 
> > > On Dec 17, 12:55 am, Matt Huggins <[email protected]> wrote: 
> > 
> > > > I'm having the same issue, and I have yet to find a solution.  The 
> > > > Cake documentation is wrong and/or the implementation is incorrect. 
> > 
> > > > On Oct 23, 1:58 am, "[email protected]" 
> > 
> > > > <[email protected]> wrote: 
> > > > > I compiled a list of the variations I have encountered in 
> different 
> > > > > associations. I have not checked how behaviors are called. 
> > 
> > > > > When primary is set this is the structure I get just as in the 
> > > > > Cookbook: 
> > > > > array( 
> > > > >     '0' => array( 
> > > > >         'Model' => array( 
> > > > >             'id' => 1 
> > > > >         ) 
> > > > >     ) 
> > > > > ) 
> > 
> > > > > When primary is not set I get a subset of these for each 
> association: 
> > 
> > > > > hasOne 
> > > > > array( 
> > > > >     'id' => 1 
> > > > > ) 
> > 
> > > > > habtm 
> > > > > array( 
> > > > >     '0' => array( 
> > > > >         'id' => 1 
> > > > >     ) 
> > > > > ) 
> > 
> > > > > hasOne, hasMany, belongsTo 
> > > > > array( 
> > > > >     '0' => array( 
> > > > >         'Model' => array( 
> > > > >             'id' => 1 
> > > > >         ) 
> > > > >     ) 
> > > > > ) 
> > 
> > > > > habtm, hasMany 
> > > > > array( 
> > > > >     '0' => array( 
> > > > >         'Model' => array( 
> > > > >             '0' => array( 
> > > > >                 'id' => 1 
> > > > >             ) 
> > > > >         ) 
> > > > >     ) 
> > > > > ) 
> > 
> > > > > This makes the number of ifs and fors quite many in order the 
> catch 
> > > > > them all. And since more than one is sometimes called for the same 
> > > > > record in the same request, you also have to check is you have 
> already 
> > > > > manipulated your data. At least if you do something "destructive" 
> to 
> > > > > it like encryption/decryption or serialization. 
> > 
> > > > > My orignal question still stands. What is the best way to write an 
> > > > > afterFind in order to: 1. not miss converting data in some queries 
> 2. 
> > > > > not double-convert the data ? 
> > 
> > > > > regards, 
> > > > > /Martin 
> > 
> > > > > On Oct 22, 5:16 pm, "[email protected]" 
> > 
> > > > > <[email protected]> wrote: 
> > > > > > Hi, 
> > > > > > I thought I'd ask this here. (see why below) 
> > > > > > How do I write afterFind() to modify a field. 
> > 
> > > > > > For example just something simple like this (just an example): 
> > 
> > > > > > function afterFind($data) { 
> > > > > >     foreach ($data as $key => $val) { 
> > > > > >         if ( isset($val[$this->alias]['name']) ) { 
> > > > > >             $data[$key][$this->alias]['name2'] = 
> $val[$this->alias] 
> > > > > > ['name']; 
> > > > > >         } 
> > > > > >     } 
> > > > > >     debug($data); 
> > > > > >     return $data; 
> > 
> > > > > > } 
> > 
> > > > > > What I want to know is how to pick out the field from the passed 
> data 
> > > > > > array. There are so many different ways the data is formatted 
> that I 
> > > > > > end up with a quite messy series of for's and if's and I still 
> don't 
> > > > > > fell 100% sure I got them all. I feel there must be some 
> sure-fire way 
> > > > > > to write these. 
> > 
> > > > > > The Cookbook is not complete compared to what I get.
> http://book.cakephp.org/view/681/afterFind 
> > 
> > > > > > The API does not mention much about this. 
> > 
> > > > > > I did not find any test in the core that helped me. 
> > 
> > > > > > I did not find anything on Google that dealt with anything but 
> basic 
> > > > > > "primary" data. 
> > 
> > > > > > I noticed that sometimes afterFind() is called more than once 
> with 
> > > > > > different data-structure each time. I asked about that here:
> http://groups.google.com/group/cake-php/browse_thread/thread/c83e5f40... 
> > 
> > > > > > I'd love some clarification of this callback. Thans in advance. 
> > > > > > /Martin

-- 
Like Us on FaceBook https://www.facebook.com/CakePHP
Find us on Twitter http://twitter.com/CakePHP

--- 
You received this message because you are subscribed to the Google Groups 
"CakePHP" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/cake-php?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to