SitePoint Sponsor |
|
User Tag List
Results 1 to 4 of 4
-
Apr 4, 2009, 17:05 #1
- Join Date
- Jul 2006
- Location
- Augusta, Georgia, United States
- Posts
- 4,194
- Mentioned
- 17 Post(s)
- Tagged
- 5 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* ) ) ) ) ) ) ) ) )
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]);
}
}
}
}
}
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
-
Apr 4, 2009, 17:58 #2
- Join Date
- Jul 2006
- Location
- Augusta, Georgia, United States
- Posts
- 4,194
- Mentioned
- 17 Post(s)
- Tagged
- 5 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));
}
}
}
}
-
Apr 4, 2009, 18:04 #3
- 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
-
Apr 4, 2009, 22:13 #4
- Join Date
- Jul 2006
- Location
- Augusta, Georgia, United States
- Posts
- 4,194
- Mentioned
- 17 Post(s)
- Tagged
- 5 Thread(s)
Yeah, after thinking about it clone wouldn't work.
Bookmarks