SitePoint Sponsor

User Tag List

Results 1 to 4 of 4
  1. #1
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,147
    Mentioned
    16 Post(s)
    Tagged
    3 Thread(s)

    Creating a copy of a object in its current state

    What would be the best way to copy object in its current state so that it isn't a reference? I tried using clone in the below code in the add_dependencies function, but I'm still running into a recursion problem.

    PHP Code:
    $user = new User(5);

    $user->addBlogEntry(new BlogEntry(),new BlogEntry(),new BlogEntry());

    save_all(array($user));

    echo 
    '<pre>',print_r($user),'</pre>';

    function 
    save_all($record,$parent=null) {

        if(
    is_null($parent)===false) {
        
            
    add_dependencies($record,$parent);
        
        }
        
        
    save_has_one($record,$parent);
        
    save_has_many($record,$parent);
        
    save_many_to_many($record,$parent);

    }

    function 
    add_dependencies($record,$parent) {

        
    $config ActiveRecordModelConfig::getModelConfig(get_class($record[0]));
        
    $parentConfig ActiveRecordModelConfig::getModelConfig(get_class($parent[0]));
        
        if(
    $config->hasBelongsTo()) {
        
            foreach(
    $config->getBelongsTo() as $model) {
            
                
    $modelClassName Inflector::classify($model);
                
                foreach(
    $record as $ar) {
                
                    if(
    strcmp($parentConfig->getClassName(),$modelClassName)==0) {
                
                        
    $ar->setProperty($model,$parent[0]);
                
                    }
                
                }
            
            }
        
        }

    }


    function 
    save_has_one($record,$parent=null) {

        
    $config ActiveRecordModelConfig::getModelConfig(get_class($record[0]));
        
        if(
    $config->hasOne()) {
        
            foreach(
    $config->getHasOne() as $model) {
            
                
    $modelClass Inflector::classify($model);
                
                foreach(
    $record as $ar) {
                
                    if(
    $ar->hasProperty($mode)) {
                
                        
    save_all(array($ar->getProperty($model)),array($ar));
                
                    }
                    
                }
            
            }
        
        }

    }


    function 
    save_has_many($record,$parent=null) {

        
    $config ActiveRecordModelConfig::getModelConfig(get_class($record[0]));
        
        if(
    $config->hasMany()) {
        
            foreach(
    $config->getHasMany() as $model) {
            
                
    $modelClass Inflector::classify($model);
                
                foreach(
    $record as $ar) {
                
                    if(
    $ar->hasProperty($model)) {
                
                        
    save_all($ar->getProperty($model),array($ar));
                
                    }
                
                }
            
            }
        
        }

    }


    function 
    save_many_to_many($record,$parent=null) {

        
    $config ActiveRecordModelConfig::getModelConfig(get_class($record[0]));
        
        if(
    $config->hasBelongsToAndHasMany()) {
        
            foreach(
    $config->getBelongsToAndHasMany() as $models) {
            
                
    $model is_array($model)?$model[0]:$model;
                
    $modelClass Inflector::classify($model);
                
                foreach(
    $record as $ar) {
                
                    if(
    $ar->hasProperty($model)) {
                    
                        
    save_all($record->getProperty($model),array($ar));
                
                    }
                
                }
            
            }
        
        }



    HTML Code:
    User Object
    (
        [_data:private] => ActiveRecordDataEntity Object
            (
                [_data:private] => Array
                    (
                        [id] => Array
                            (
                                [0] => 5
                            )
    
                        [name] => Array
                            (
                                [0] => ani_fgh
                            )
    
                        [first_name] => Array
                            (
                                [0] => tom
                            )
    
                        [last_name] => Array
                            (
                                [0] => hello
                            )
    
                        [email] => Array
                            (
                                [0] => balah.com
                            )
    
                        [pwd] => Array
                            (
                                [0] => uiHgJ7865$rD
                            )
    
                        [status] => Array
                            (
                                [0] => 1
                            )
    
                        [created] => Array
                            (
                                [0] => 2009-03-19 18:51:40
                            )
    
                        [access] => Array
                            (
                                [0] => 1
                            )
    
                        [site] => Array
                            (
                                [0] => http://www.blah.com
                            )
    
                        [blog_entries] => Array
                            (
                                [0] => Array
                                    (
                                        [0] => BlogEntry Object
                                            (
                                                [_data:private] => ActiveRecordDataEntity Object
                                                    (
                                                        [_data:private] => Array
                                                            (
                                                                [] => Array
                                                                    (
                                                                        [0] => User Object
     *RECURSION*
                                                                    )
    
                                                            )
    
                                                    )
    
                                            )
    
                                        [1] => BlogEntry Object
                                            (
                                                [_data:private] => ActiveRecordDataEntity Object
                                                    (
                                                        [_data:private] => Array
                                                            (
                                                                [] => Array
                                                                    (
                                                                        [0] => User Object
     *RECURSION*
                                                                    )
    
                                                            )
    
                                                    )
    
                                            )
    
                                        [2] => BlogEntry Object
                                            (
                                                [_data:private] => ActiveRecordDataEntity Object
                                                    (
                                                        [_data:private] => Array
                                                            (
                                                                [] => Array
                                                                    (
                                                                        [0] => User Object
     *RECURSION*
                                                                    )
    
                                                            )
    
                                                    )
    
                                            )
    
                                    )
    
                            )
    
                    )
    
            )
    
    )
    Specifically, the problem occurs in the central most line of code in the below function.

    PHP Code:
    function add_dependencies($record,$parent) {



        
    $config ActiveRecordModelConfig::getModelConfig(get_class($record[0]));

        
    $parentConfig ActiveRecordModelConfig::getModelConfig(get_class($parent[0]));

        

        if(
    $config->hasBelongsTo()) {

        

            foreach(
    $config->getBelongsTo() as $model) {

            

                
    $modelClassName Inflector::classify($model);

                

                foreach(
    $record as $ar) {

                

                    if(
    strcmp($parentConfig->getClassName(),$modelClassName)==0) {

                

                        
    $ar->setProperty($model,$parent[0]);

                

                    }

                

                }

            

            }

        

        }




    The user in this case needs to a be a leaf, but if its passed by reference its other associations are updated. I just need a copy of that object that isn't a reference when I pass it to through $ar->setProperty();

    By the way, I haven't defined the __clone() method inside the Active Record class. Is that something that needs to be done in order to create a exact copy that isn't a reference?

    The other option I was thinking was to rebuild the parent record omitting any associations so just including leaf properties. Would that be the best route? The only problem with that is it results in much more code because I need to resolve all composites to a leaf. Which can be done, but I was hoping there might be a simpler answer.

    thanks

  2. #2
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,147
    Mentioned
    16 Post(s)
    Tagged
    3 Thread(s)
    After thinking about it I don't think clone will work. Because if a object is clones that has composites those composites won't be flattened. Not sure there is a better way then to just rebuild a copy and resolve all the composites if present to the appropriate field. The code below seems to that perfectly as a little additional cost that I don't think can be avoided.

    PHP Code:
    function make_flat_copy(ActiveRecord $record) {

        
    $config ActiveRecordModelConfig::getModelConfig(get_class($record));
        
    $class $config->getClassName();
        
    $copy = new $class();
        
        
    resolve_foreign_keys($copy,$record);
        
    resolve_belongs_to_associations($copy,$record);
        
    copy_over_model_fields($copy,$record);
        
        return 
    $copy;

    }

    function 
    resolve_foreign_keys(ActiveRecord $copy,ActiveRecord $record) {

        
    $config ActiveRecordModelConfig::getModelConfig(get_class($copy));
        
        if(
    $config->hasForeignKeys()) {
        
            foreach(
    $config->getForeignKeys() as $index=>$reference) {
            
                
    $relatedClassName is_array($reference)?array_shift($reference):$reference;
                
    $relatedConfig ActiveRecordModelConfig::getConfig($relatedClassName);
                
    $model Inflector::underscore(Inflector::singularize($relatedClassName));
                
                
    $relatedKey is_array($reference) && !empty($reference)?array_shift($reference):$relatedConfig->getPrimaryKey();
                
                if(
    $record->hasProperty($model) && $record->getProperty($model) instanceof $relatedClassName) {
                
                    
    $copy->setProperty($index,$record->getProperty($model)->getProperty($relatedKey));
                
                }
            
            }
        
        }

    }

    function 
    resolve_belongs_to_associations(ActiveRecord $copy,ActiveRecord $record) {

        
    $config ActiveRecordModelConfig::getModelConfig(get_class($copy));
        
        if(
    $config->hasBelongsTo()) {
        
            foreach(
    $config->getBelongsTo as $model) {
            
                if(!
    $copy->hasProperty($model) && $record->hasProperty($model)) {
                
                    
    $relatedClassName Inflector::underscore(Inflector::singularize($model));
                    
    $relatedConfig ActiveRecordModelConfig::getModelConfig($relatedClassName);
                    
                    
    $relatedKey $relatedConfig->getPrimaryKey();
                    
    $index Inflector::foreign_key($config->getClassName(),true,$relatedKey);
                    
                    if(
    $record->getProperty($model) instanceof $relatedClassName) {
                    
                        
    $copy->setProperty($index,$record->getProperty($model)->getProperty($relatedKey));
                    
                    }
                
                }
            
            }
        
        }

    }

    function 
    copy_over_model_fields(ActiveRecord $copy,ActiveRecord $record) {

        
    $config ActiveRecordModelConfig::getModelConfig(get_class($copy));
        
        if(
    $config->hasFields()) {
        
            foreach(
    $config->getFields() as $field) {
            
                if(
    $copy->hasProperty($field)=== false && $record->hasProperty($field)) {
                
                    
    $copy->setProperty($field,$record->getProperty($field));
                
                }
            
            }
        
        }



  3. #3
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    This may be of some use to you

    http://uk3.php.net/manual/en/language.oop5.cloning.php

    Create a __clone() method on every class to clone its object members (each having their methods and so on). That will create fresh, non-reference copies of every level of object members.
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  4. #4
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,147
    Mentioned
    16 Post(s)
    Tagged
    3 Thread(s)
    Yeah, after thinking about it clone wouldn't work.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •