Yii2: when adding dynamic attribute to a model that does not exists in database it do not value of that attribute even defining get and set function for attribute

Created on 8 Jan 2015  路  10Comments  路  Source: yiisoft/yii2

Hi below is my code

when adding dynamic attribute to a model that does not exists in database it do not value of that attribute even defining get and set function for attribute phone

namespace common\models;
use common\models\VenueType;
use common\models\VenueMap;
use common\models\AttributeVenue;
use common\models\Attributes;
use Yii;
use yii\helpers\Json;
use yii\helpers\HtmlPurifier;
use common\component\AppActiveRecord;

//use common\validators;

/**
 * This is the model class for table "tc_venue".
 *
 * @property integer $Id
 * @property string $name
 * @property integer $categoryId
 * @property integer $cityId
 * @property integer $zoneId
 * @property integer $localityId
 * @property string $address
 * @property string $landmark
 * @property string $phone
 * @property string $tollfree
 * @property string $mobile
 * @property double $gpsLat
 * @property double $gpsLong
 * @property integer $venueType
 * @property string $facility
 * @property integer $capacity
 * @property string $description
 * @property string $contactName
 * @property string $email
 * @property string $url
 * @property string $facebookUrl
 * @property string $seatType
 * @property string $reservationInfo
 * @property string $audiVsCapcity
 * @property string $startTime
 * @property string $endTime
 * @property string $ip
 * @property integer $IsReccomended
 * @property integer $status
 * @property integer $flag
 * @property string $oldGuid
 * @property string $guid
 * @property string $createdOn
 * @property integer $createdBy
 * @property string $updatedOn
 * @property integer $updatedBy
 * @property string $csvRemarks
 * @property integer $csvUpload
 */
class Venue extends AppActiveRecord
{  
    use MediaTagTrait;

    public $mediaImage;


    public $imagePath = 'venue';
   public $phone;
   public $mobile;
   public $contactName;
   public $email;



    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return '{{%venues}}';
    }

    public function afterDraft() {
        parent::afterDraft();
        Yii::$app->session->setFlash("venue_notification", Yii::t("app", "Venue saved as Draft!"));
    }

    public function afterPublishReady() {
        parent::afterPublishReady();
        Yii::$app->session->setFlash("venue_notification", Yii::t("app", "Venue Send  to Published"));
    }

    public function afterPublish() {
        parent::afterPublish();
        Yii::$app->session->setFlash("venue_notification", Yii::t("app", "Venue Published!"));
    }

    public function afterUnPublish() {
        parent::afterUnPublish();
        Yii::$app->session->setFlash("venue_notification", Yii::t("app", "Venue Unpublished!"));
    }

    /*
    public function scenarios(){
        return [
          'unpublish' => ['reason', 'reasondesc','redirecturl'],
          'delete' => ['reason', 'reasondesc'],
      ];
    }
    //*/

    /**
     * @inheritdocredirecturl
     */
    public function rules()
    {
        return [
            [['name', 'city_id', 'zone_id', 'locality_id', 'venuetype_id','address','latitude', 'longitude'], 'required'],
            [['city_id','status','created_by', 'updated_by','verified_flag'], 'integer'],
            [['description'], 'string'],
            [['created_on', 'updated_on','state','verified_time','match_score','create_reason','phone'], 'safe'],
            [['name', 'address', 'landmark'], 'string','min'=>6, 'max' => 128],
            [['website', 'facebook_url','url',], 'string','min'=>6, 'max' => 100],
            [['ip'], 'string', 'max' => 20],
            [['name'], 'filter', 'filter' => 'trim'],
            //[['name'], 'string','min'=>3 ,'max' => 60],
            ['name', 'common\validators\AlphanumericValidator'],
            //['email','email'],
            [['latitude'], 'number','max'=>91],
            [['longitude'], 'number','max'=>181],
            ['longitude', 'common\validators\GpsValidator'],
            ['longitude', 'common\validators\GpsValidator'],
            ['website','url'],
            ['facebook_url','url'],
            //['phone', 'common\validators\PhoneValidator'],   //custom class we made it for phone           
            //['mobile', 'common\validators\MobileValidator'], //custom class we made it for mobile
            [['name','description'], 'filter', 'filter' => function ($value) {

                // here we are using HTML purifier
                return HTMLPurifier::process($value);
                }
            ],
            ['reason','required','on'=>['unpublish','delete']],
            ['reasondesc','required','on'=>['unpublish','delete','statusupdate']],
            ['reasondesc','string','on'=>['unpublish','delete','statusupdate']],
            ['redirecturl','url','on'=>['unpublish','delete']],
            ['status','required','on'=>['statusupdate']],

        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'name' => 'Name',
            'city_id' => 'City',
            'zone_id' => 'Zone',
            'localityId' => 'Locality',
            'address' => 'Address',
            'landmark' => 'Landmark',
            'phone' => 'Phone',
            'email' => 'Email',
            'mobile' => 'Mobile',
            'contactName' => 'Contact Name',
            'latitude' => 'Latitude',
            'longitude' => 'Longitude',
            //'tag'      => 'Tags',
            'venuetype_id' => 'Venue Type',
            //'facility' => 'Facility',
            'description' => 'Description',
            'website' => 'Website',
            'facebook_url' => 'Facebook Url',
            'ip' => 'Ip',
            'status' => 'Status',
            'state' => 'State',
            'url' => 'Url',
            'created_on' => 'Created On',
            'created_by' => 'Created By',
            'updated_on' => 'Updated On',
            'updated_by' => 'Updated By',
            'entityType' => 'Entity Type',
            'state' => 'Status',
            'reason' => 'Reason',
            'reasondesc' => 'Reason Description',
            'redirecturl' => 'Redirect Url',
            'entity_type' => 'Entity Type',
            'verified_flag' => 'Verified Flag',
            'verified_time' => 'Verified Time',
            'match_score' => 'Match Score',
            'create_reason' => 'Create Reason'
          ];
    }

    /**
     * @inheritdoc
     */
    public function fields() {
        return [
            'id',
            'name',
            'city_id',
            'cityname',
            'zone_id',
            'zonename',
            'locality_id',
            'localityname',
            'address',
            'landmark',
            'latitude',
            'longitude',
            'tags',
            'venuetype_id',
            'venueTypeName',
            'facility',
            'description',
            'phonedata',
            'mobiledata',
            'contact',
            'emailvenue',
            'url',
            'facebook_url',
            'status',
            'url',            
            'media',
            'website',
            'phone'
            //'events'
        ];
    }

    public function extraFields() {
        return [            
            'events'
        ];
    }



    public function getType(){
        return $this->hasOne(VenueType::className(), ['id' => 'venuetype_id']);
    }


    public function getVenueTypeName(){
        return $this->type->name;
    }

    /**
     * @return array
     */
    public function getPhonedata(){

       $data = $this->attributeVenue;
       $phoned = [];
       foreach($data as $model){
           if($model->attribute_id==3)
           {
            $phoned[] = $model->value;
           } 
       }
       return $phoned;


    }


    public function setPhone($val) {
        Yii::info("in setphone function");
        $this->_phone = $this->getPhonedata();
    }

    public function getPhone($val) {
        Yii::info("in getphone function");
        return $this->_phone;
    }

    /**
     * @return array
     */
    public function getMobiledata(){
       $data = $this->attributeVenue;
       $phone = [];

       foreach($data as $model){
           if($model->attribute_id==4)
           {
             $phone[] = $model->value;
           }
       }

       return $phone;
    }

    public function getContact(){

        $data = $this->attributeVenue;
       $contact = '';

       foreach($data as $model){
           if($model->attribute_id==1)
           {
             $contact= $model->value;
           }
       }
       return $contact;

    }




    public function getEmailvenue(){
       $data = $this->attributeVenue;
       $email = '';

       foreach($data as $model){
           if($model->attribute_id==2)
           {
             $email = $model->value;
           }
       }

      return $email;              
    }


    public function getTagData(){

       $data = $this->toArray();
       $tags = [];


        $facilityDataArray=$data['tags'];
        $facilityString='';
        for($i=0;$i<count($facilityDataArray);$i++)
        {
            $tags[]=$facilityDataArray[$i]['name'];
        }



       return $tags;
    }


    /**
     * @return array
     */
    public function getFacility(){

       return $this->hasMany(Features::className(), ['id' => 'facility_id'])->via('venueMap');
    }

    /**
     * @return array
     */
    public function createUrl()
    {
       $data = $this->toArray();
       $url='';
       $url='/'. $this->urlFilter($data['cityname']) .'/venue/' . $this->urlFilter($data['name']) . '/'.$data['id'] ;
       return $url;
    }

    /**
     * @return array
     */
    public function getMedia() {
        return [
            'images' => $this->images,
            'video' => $this->video,
        ];
    }


    public function saveUrl($runValidation=true)
    {

       $this->url=$this->createUrl();
       $result = parent::save($runValidation);
    }

    /*
     * @retun string return how many form field in data
     */
    public function multipleFormField($formstring,$dataArray)
    {

        $foString='';
        if(count($dataArray)>0)
        {

            for($i=0;$i<count($dataArray);$i++)
            {
                if($i>0)
                {
                $foString.='<div class="form-group">
                            <label>'.ucwords($formstring).' '.($i+1).'</label>
                                <input type="text" class="form-control" name="Venue['.$formstring.'][]" value="'.$dataArray[$i].'" />
                        </div>';
                }
                else
                {
                     $foString.='<div class="form-group">
                            <label>'.ucwords($formstring).'</label>
                                <input type="text" class="form-control" name="Venue['.$formstring.'][]" value="'.$dataArray[$i].'" />
                        </div>';

                }

            }
        }
        else
        {
            $foString='<div class="form-group">
                            <label>'.ucwords($formstring).'</label>
                                <input type="text" class="form-control" name="Venue['.$formstring.'][]"/>
                        </div>';

        }
        return $foString;
    }   

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getVenueMap(){
        return $this->hasMany(VenueMap::className(), ['venue_id' => 'id']);
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getAttributeVenue(){
        return $this->hasMany(AttributeVenue::className(), ['venue_id' => 'id']);
    }



    /**
     * 
     * @param boolean $runValidation whether to perform validation before saving the record.
     * If the validation fails, the record will not be saved to database.
     * @param array $attributeNames list of attribute names that need to be saved. Defaults to null,
     * meaning all attributes that are loaded from DB will be saved.
     * @param array $data Data Array
     * @return boolean whether the saving succeeds
     */
    public function save($runValidation = true, $attributeNames = null,$data=[]){

        //echo "rajanish";

        if (!$this->beforeTrancSave()) {
            return false;
        }
        $db = static::getDb();
        $transaction = $db->beginTransaction(); 
        //Yii::info("in save function");
        try {
            $this->loadDefaultValues();
            //$result = parent::save(false);
            $result = parent::save($runValidation,$attributeNames);
            if(!$result){
               $transaction->rollBack();
                return false;
            }


            $length = 0;


            $datakey = [
                'phone',
                'mobile',
                'contactName',
                'email',
                'media',
                'video',
                'tag',
                'facility',
            ];


            $map = [
                'facility'            => 'facility_id',
            ];




            if(count($data)<1) {
                $req = Yii::$app->getRequest()->getBodyParams();
                //Yii::info('rajanish');
                $postdata = isset($req[$this->formName()]) ? $req[$this->formName()] : $req;
                //print_r($postdata);
                $data = [];
                foreach($datakey as $key){
                    if(isset($postdata[$key])){
                        $data[$key] = $postdata[$key];
                    }
                }
            }
             //var_dump($data);
             foreach($data as $key=>$arval){
                if(is_array($arval) && ($ar_count = count($arval))){
                    if($ar_count>$length) $length = $ar_count;
                }
            }

            $mapAR = $this->venueMap;    //it will provide relational AR Array if there is any record. else it will be none.
            //var_dump($mapAR);
            $ar_count = count($mapAR);
            //echo $length;
            for ($check_start=0; $check_start<$length; $check_start++){
                   //echo "ra.......<br>";
                foreach($map as $key=>$mapkey){
                    //Yii::info("data for".$key.':'.  var_dump($data[$key][$check_start]));
                    //var_dump($data[$key][$check_start]);
                    $doc[$mapkey] = (isset($data[$key][$check_start]) && $data[$key][$check_start]!== null  && $data[$key][$check_start]!= "") ? $data[$key][$check_start] : 0;
                }

                $isdata = false;
                foreach($doc as $doc_data){
                    if($doc_data){ $isdata = true; break;}                    
                }
                if(!$isdata){
                    continue;
                }

                $doc['order'] = $check_start+1;

                if(($ar_count>0) && isset($mapAR[$check_start])){  //need to update
                    $armodel = $mapAR[$check_start];
                }else{          //create new record
                    $armodel = new VenueMap;
                }

                //Yii::info("doc after load:".print_r($doc,true));
                 //print_r($doc);
                $armodel->load($doc, '');
                $armodel->save($runValidation);
                $this->link('venueMap', $armodel);
            }

            if($ar_count > $length){
                for($length;$length<$ar_count;$length++){
                    $mapAR[$length]->delete();
                }
            }

            $assetDataar = ['media' => $this->ClassSortNeme().'_image_'.  $this->id,'video' => $this->ClassSortNeme().'_video_'.  $this->id];
            $this->saveAsset($assetDataar, $data,$runValidation);

            $attrbuteArray=['email'=>$data['email'],'contactName'=>$data['contactName'],'phone'=>$data['phone'],'mobile'=>$data['mobile']];

           // Yii::info("doc:".print_r($attrbuteArray,true));

            $this->saveVenueAttributes($attrbuteArray,$runValidation);        



            $this->saveTags($data['tag'],$runValidation);
            $this->saveUrl($runValidation);


            $transaction->commit();   
            $this->afterTrancSave();
            return true;           
        } catch (\Exception $e) {
            Yii::info($e,__METHOD__);
            $transaction->rollBack();
            return false;
        }
    }

    /**
     * 
     * @param string $jsonDOC
     * @return boolean
     */
    public function import($jsonDOC){
        //echo $jsonDOC."\n";
        $docObj = Json::decode($jsonDOC, true);

        $mappingVanue = [
            "_id"=>"Id",
            "venue_name"=>"name",
            "venue_cat"=>"categoryId",
            "city_id"=>"cityId",
            "zone_id"=>"zoneId",
            "locality_id"=>"localityId",
            "city_name"=>false,
            "zone_name"=>false,
            "locality_name"=>false,
            "address1"=>"address",
            "address2"=>false,
            "landmark"=>"landmark",
            "phone"=> false,
            "toll_no"=>"tollfree",
            "mobile"=> false,
            "gps"=>false,
            'gpsLat'=> 'gpsLat',
            'gpsLong'=> 'gpsLong',
            "venue_brands"=>"brand",        //to be added
            "venue_mall"=>"mall",           //to be added
            "venue_type"=>"venueType",
            "venue_facility"=>false,
            "venue_capacity"=>"capacity",
            "venue_desc"=>"description",
            "venue_contact_person"=>"contactName",
            "venue_email"=>"email",
            "venue_url"=>"url",
            "venue_fb_url"=>"facebookUrl",
            "venue_seat_type"=>"seatType",
            "venue_tags"=> false,               //to be added
            "reservation_info"=>"reservationInfo",
            "start_time"=>"startTime",
            "end_time"=>"endTime",
            "IP"=>"ip",
            "venue_is_reccomended"=>"IsReccomended",
            "status"=>"status",
            "insert_date" => "createdOn",
            "flag"=>"flag",
            "oldguid"=>"oldGuid",
            "guid"=>"guid",
            "created_by"=>"createdBy",
            "modified_by"=>"updatedBy",
            "modified_date"=>"updatedOn",
            "deleted_by"=>false,
            "deleted_date"=> false,
            "moderated_by"=>false,
            "moderation_status"=>false,
            "video_flag"=>false,
            "image_flag"=>false,
            "is_editable"=>false,
            "assigned_to"=>false,
            "csv_remarks"=>"csvRemarks",
            "is_csv_upload"=>"csvUpload",
            "tmp_venue_landline"=>false,
            "tmp_venue_mobile"=>false,
            "imagesArr"=>false,
            "venue_type_name"=>false,
            'state' => 'state',
        ];

        $mappingfunction = [
            "name" => function($data,$row){ return addslashes(str_replace("\'","",$row['venue_name']));},
            "address" => function($data,$row){ return addslashes(str_replace("\'","",$row['address1']));},
            "description" => function($data,$row){ return addslashes(str_replace("\'","",$row['venue_desc']));},
            "landmark" => function($data,$row){ return addslashes(str_replace("\'","",$row['landmark']));},        
            "insert_date" => function($data,$row){ return date('Y-m-d H:i:s',$data['sec']);},            
            "modified_date"=> function($data,$row){ return date('Y-m-d H:i:s',$data['sec']);},
            "gpsLat"=> function($data,$row){ if(isset($row['gps']) && $row['gps']!=''){$gps = explode('||',$row['gps']); return $gps[0];}else{ return '';}},
            "gpsLong"=> function($data,$row){if(isset($row['gps']) && $row['gps']!=''){$gps = explode('||',$row['gps']); return $gps[1];}else{ return '';}},
            "state"             => function ($data,$row){
                switch ((int)$row['status']){
                    case 1: $ret = AppActiveRecord::STATUS_PUBLISH; break;
                    case 0: $ret = AppActiveRecord::STATUS_DELETE; break;
                    default : $ret = AppActiveRecord::STATUS_UNPUBLISH; break;
                }
                return $ret;
            }
        ];


        $data = [
            'media'         => Import::importMediaData($docObj['extrafields']['images']['entity'], $this->imagePath),            
            //'video'         => Import::importvideoData($docObj['extrafields']['images']['menu']),
            'phone'         => $this->converttoArray($docObj['phone']),
            'mobile'        => $this->converttoArray($docObj['mobile']),
            'tag'           => $this->converttoArray($docObj['venue_tags']),
            'facilityId'    => explode(',',$docObj['venue_facility'])
        ];

        return Import::importData($this, $docObj, $mappingVanue, $mappingfunction,$data);
    }

    //return similar venues based on lat,long in specified radius.
    public function getVenueByLatLong($lat,$long,$radius = 2,$limit = 20){
            $response = [];
            $sql = "    SELECT `id`,`name`,`address`,`latitude`, `longitude`, SQRT(
                        POW(69.1 * (latitude - ".$lat."), 2) +
                        POW(69.1 * (".$long." - longitude) * COS(latitude / 57.3), 2)) AS distance
                        FROM tc_venues HAVING distance <= ".$radius." ORDER BY distance limit ".$limit;
            //echo $sql;die;
            $res = $this->findBySql($sql)->all();
            foreach($res as $r){
                $response [] = $r->toArray();
            }
            return $response;
    }

    public function getVenuePincode($pincode){

    }
}

Most helpful comment

add

function attributes()
{
$attributes = parent::attributes();
$attributes[] = 'phone';
return $attributes;
}

All 10 comments

:-1:

dynamical model is not active record and not have table

Issue is not with dynamical model, Problem with $phone Attribute ,

This is not in my database table, I am defining dynamically in model, Where i declare getPhone() and setPhone() function, but if called toArray() function , it is not called.

add

function attributes()
{
$attributes = parent::attributes();
$attributes[] = 'phone';
return $attributes;
}

not working

@rajanishtimes you have an option to also override the fields() to return all the fields you want including your phone

yes i have added but i got blank data

i uses below code
public function setPhone() {
Yii::info("in setphone function");
$this->_phone = $this->getPhonedata();
}

public function getPhone(){

    Yii::info("in getphone function");
    return $this->phone;
}

Plaese use Yii forum for asking.
https://www.facebook.com/groups/yiitalk/ http://www.yiiframework.com/forum/

.

.

Setter and getter only used when no property with that name.

class MyObj extends Object
{
    public $phone;

    public function getPhone()
    {
        // ...
    }

    public function setPhone($value)
    {
        // ...
    }
}

setPhone() and getPhone() never be called when you call $obj->phone.

Was this page helpful?
0 / 5 - 0 ratings