Yii Framework Forum: Dynamic Yii Table Controller/modell - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Dynamic Yii Table Controller/modell Rate Topic: -----

#1 User is offline   lugaru 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 9
  • Joined: 13-July 11

Posted 10 April 2013 - 09:40 AM

Hey,

i have to create the following Application:

A CRUD Design to dynamically create a whole Table / Controller Model. So that i can create a Profile with dynamic Fields ( For Example Name, Surname, Telephone etc) and on another Copy of the Application i also want to have the field Telefax or other Stuff).

I Already have written a controller and Model for that, so on each change, this change will also be applied to the linked table.

Now my question is how to generate the Controller & Modell (All CRUD options) to read each field from the Database Table or from the describing table.

Cheers
Lugaru
0

#2 User is offline   AustinGeek 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 173
  • Joined: 22-September 12

Posted 10 April 2013 - 10:06 AM

I might suggest looking at how Gii or Giix generate CRUD and Models.
0

#3 User is offline   le_top 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 386
  • Joined: 08-June 10
  • Location:France (Ile-de-France/Val d'Oise)

Posted 10 April 2013 - 02:38 PM

I have done such a thing in my application.
I have a 'User' table (actually more than a User table) in which each user has 'Properties'.
These properties are for most of them in a 'Properties' table.

The User model has overloaded '__get' and '__set' methods to automatically get these properties from the properties table. The rest of the application does not even have to know that these properties are in another table.
I had to move one of the properties from the property table to the User table for performance reasons (the name of the user) - with a migration that change went pretty smooth.

There is some complexity in writing this up because one has to cope with new properties for an existing record or for a new record and only save them when the User is saved to make the object and its properties look as a single object.
0

#4 User is offline   lugaru 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 9
  • Joined: 13-July 11

Posted 11 April 2013 - 02:36 AM

View Postle_top, on 10 April 2013 - 02:38 PM, said:

I have done such a thing in my application.
I have a 'User' table (actually more than a User table) in which each user has 'Properties'.
These properties are for most of them in a 'Properties' table.

The User model has overloaded '__get' and '__set' methods to automatically get these properties from the properties table. The rest of the application does not even have to know that these properties are in another table.
I had to move one of the properties from the property table to the User table for performance reasons (the name of the user) - with a migration that change went pretty smooth.

There is some complexity in writing this up because one has to cope with new properties for an existing record or for a new record and only save them when the User is saved to make the object and its properties look as a single object.


Hey le top,

sounds interesting. Could you maybe post a bit of code or send me some code per PM? i would really appreciate that!

thanks!
0

#5 User is offline   le_top 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 386
  • Joined: 08-June 10
  • Location:France (Ile-de-France/Val d'Oise)

Posted 11 April 2013 - 03:08 AM

Ok, I'll share some of the code. There are still some print instructions in branches that should never be reached, which is not a priority to improve in my project.
The class defines a relation '_properties' representing the properties. It is prefixed with '_' because it is intended to be used internally only.

This will give you an idea of what has to be done.


class Entity extends CActiveRecord {
  // ...

    /* (non-PHPdoc)
     * @see CActiveRecord::__get()
    *
    * Extend getter to retrieve generic properties for the entity.
    */
    public function __get($name) {
        if(!parent::__isset($name)) {
            return $this->getProperty($name);
        }
        // Default case:
        return parent::__get($name);
    }

    public function __set($name,$value) {
        try {
            parent::__set($name, $value);
        } catch(Exception $e) {
            $this->setProperty($name, $value);
        }
    }




    /**
     * Scope to limit selection to entities that have the given property.
     * @param string $property
     * @return Entity
     */
    public function property($property) {
        $this->getDbCriteria()->compare('_properties.property_identifier',$property);
        return $this;
    }


    /**
     * Scope to constrain the entity to have a specific property value.
     *
     * @param string $property
     * @param string $value
     */
    public function property_equals($property,$value) {
        $relationAlias=$this->aliasId();
        $this->getDbCriteria()->mergeWith(
                array(
                        'with'=>array(
                                '_properties'=>array(
                                        'alias'=>$relationAlias,
                                        'condition'=>"`$relationAlias`.`property_identifier`=:property and `$relationAlias`.`property_value`=:value",
                                        'params'=>array(':property'=>$property, ':value'=>$value),
                                ),
                        ),
                )
        );
        return $this;
    }


    private $propertiesToSet=array();
    private $propertiesType=array();

    /**
     * Gets a property for the Entity.
     *
     * Looks for the given property amongst available properties (usually from EntityProperties).
     *
     * @param string $property
    */
    public function getProperty($property) {
        if(array_key_exists($property, $this->propertiesToSet)) {
            return $this->propertiesToSet[$property];
        } else {
            $props=parent::__get('properties');
            if(array_key_exists($property, $props)) {
                return $this->properties[$property]->property_value;
            } else {
                return null;
            }
        }
    }


    /**
     * Set an entity property.
     * @param string $property
     * @param mixed $value
     * @param integer $type  The type of the property {@link EntityProperties::TYPE_STRING}
     */
    public function setProperty($property,$value,$type=EntityProperties::TYPE_STRING) {
        if($this->isNewRecord) {
   	        $this->propertiesType[$property]=$type;
   	        $this->propertiesToSet[$property]=$value;
        } else {
            $param=self::PARAM_PREFIX.self::$paramCount++;
            $alias=self::TBL_PREFIX.self::$paramCount++;
            $found=array();
            if($this->hasRelated('properties')) {
                foreach($this->properties as $p) {
                    if($p->property_identifier===$property) {
                        $found[] = $p;
                        break;
                    }
                }
            } else {
                $found=$this->properties(
                        array(
                                'alias'=>$alias,
                                'condition'=>"`$alias`.`property_identifier`=$param",
                                'params'=>array($param=>$property),
                                'joinType'=>'INNER JOIN', // Links through entity_property_link which is left outer join.
                        ));
            }
            if(empty($found)) {
                $this->addNewProperty($property,$value,$type,$this->isAttributeSafe($property));
            } else {
                foreach($found as /* @var $p EntityProperties */ $p) {
                    $p->property_value = $value;
                    if(!$p->save()) {
                        print "Saving $property $value failed";
                        print CHtml::errorSummary($p);
                    }
                }
            }
        }
        return $value;
    }


    /**
     * (non-PHPdoc)
     * @see CActiveRecord::save()
     */
    public function save($runValidation=true,$attributes=null) {
        $this->getAttributes(array('is_active'));
        if($result=parent::save($runValidation, $attributes)) {
[size=2]            if(!empty($this->properties)) {[/size]
                $result_i=true;
                foreach($this->properties as $p) {
                    $result_i&=$p->save();
                    if(!$result_i) {
                        $this->addErrors($p->getErrors());
                    }
                    $result&=$result_i;
                }
            }
            //print $result?"ok":"nok";
            if(!empty($this->propertiesToSet)) {
                $lresult=true;
                foreach($this->propertiesToSet as $property=>$value) {
                    $result&=$this->addNewProperty($property,$value,$this->propertiesType[$property],true);
                }
                if($lresult) {
                    $this->propertiesToSet = array();
                    $this->propertiesType = array();
                }
                $result&=$lresult;
            }
            //print $result?"ok":"nok";
        } else {
            echo Yii::trace("Skip1:".CVarDumper::dumpAsString($this),'vardump');
        }
        return $result;
    }



1

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users