Static Variable Not Working

HI Guys i am trying to increase a variable value whenever a function is called from Main page.

Function something()

{

 $count++;

}

I have declared $count as a static stil whenever i call this function it reassigned the value.Same for Session.

Need Help.

Thanks in Advance.

Hi shivansh,

Static variables should work as expected. Try calling your "something" function 2 or 3 times from the different places of the main page (from the header, the body and the footer, for example), then you will notice that $count is counted up one by one.

But note that the PHP’s life cycle is very short. It starts when the server has received a request and ends when the server has sent back the response. Another request, then another life cycle. :)

I’m sure what you want to do is not accomplished with static variables, but with some persistent storage that will continue to exist after one life cycle of PHP.

You can use CWebUser::setState and CWebUser::getState for individual users.

http://www.yiiframework.com/doc/api/1.1/CWebUser#getState-detail

Or you may want to use CApplication::setGlobalState and CApplication::getGlobalState for a global variable across the users.

http://www.yiiframework.com/doc/api/1.1/CApplication#getGlobalState-detailor

Thanks

Didn’t work for me.Can any body share some example here.

Try this

First Initialize:




if(!Yii::app()->user->hasState('static_count')) {

  Yii::app()->user->setState('static_count', 0);

}



Then as usual get and increase:




// Get count

$count_val = (int) Yii::app()->user->static_count;

// Increase count

Yii::app()->user->setState('static_count', $count++);



Those are silly suggestions, you simply forgot self::




function something()

{

  self::$count++;

}



If it wasn’t static it would be $this->count++;

Ah, you might be right. I didn’t notice the missing of “self::”

But, well, as $count++ didn’t seem to cause a syntax error for shivanshu, then it should be a local variable. Or a global one? I don’t know. Anyway, it’s useless to say something without looking at the real source code of “something”.

[EDIT]

A static variable can be declared inside a function, as you see in the PHP manual.

http://www.php.net/manual/en/language.variables.scope.php

Sure it can, but that would be useless for his purpose. He needs to declare it in the class.

I wonder why you think so.

If he wanted to count up $count every time he calls that function (within a single life cycle), it would have been the perfect solution. I don’t think that he had to declare it in the class. And if he wanted the value to be persistent across requests, then a class level static variable was also useless.

What purpose did you think he had?

Hi Guys thanks for your discussion here,that will surely gonna help me.




<?php


class MediaController extends Controller

{

	/**

	 * @var string the default layout for the views. Defaults to '//layouts/column2', meaning

	 * using two-column layout. See 'protected/views/layouts/column2.php'.

	 */

	public $layout='//layouts/column2';

        private $dataProvider;

        

	/**

	 * @return array action filters

	 */

	public function filters()

	{

		return array(

			'accessControl', // perform access control for CRUD operations

			'postOnly + delete', // we only allow deletion via POST request

		);

	}


	/**

	 * Specifies the access control rules.

	 * This method is used by the 'accessControl' filter.

	 * @return array access control rules

	 */

	public function accessRules()

	{

		return array(

			array('allow',  // allow all users to perform 'index' and 'view' actions

				'actions'=>array('index','view'),

				'users'=>array('*'),

			),

			array('allow', // allow authenticated user to perform 'create' and 'update' actions

				'actions'=>array('create','update'),

				'users'=>array('@'),

			),

			array('allow', // allow admin user to perform 'admin' and 'delete' actions

				'actions'=>array('admin','delete'),

				'users'=>array('admin'),

			),

			array('deny',  // deny all users

				'users'=>array('*'),

			),

		);

	}


	/**

	 * Displays a particular model.

	 * @param integer $id the ID of the model to be displayed

	 */

	public function actionView($id)

	{

		$this->render('view',array(

			'model'=>$this->loadModel($id),

		));

	}


	/**

	 * Creates a new model.

	 * If creation is successful, the browser will be redirected to the 'view' page.

	 */

	public function actionCreate()

	{

		$model=new Media;


		// Uncomment the following line if AJAX validation is needed

		// $this->performAjaxValidation($model);


		if(isset($_POST['Media']))

		{

                        $dir = Yii::getPathOfAlias('application.uploaded');

                        

                        //$dir = Yii::app()->request->baseUrl."/protected/uploaded";

                        $file = CUploadedFile::getInstance($model,'path');

                        $model->attributes=$_POST['Media'];

                        $file===NULL?$model->validate():$model->path = $dir."\\".$model->name;

                        

                        if($model->validate())

                        {

                                if($model->save())

                                {   

                                    $uploded = $file->saveAs($dir."/".$model->name.".mp3");

                                    Media::model()->associateMediaToGenre($model->id,$model->genre);

                                    $this->redirect(array('view','id'=>$model->id));

                                }

                        }

		}


		$this->render('create',array(

			'model'=>$model,

		));

	}


	/**

	 * Updates a particular model.

	 * If update is successful, the browser will be redirected to the 'view' page.

	 * @param integer $id the ID of the model to be updated

	 */

	public function actionUpdate($id)

	{

		$model=$this->loadModel($id);

                $this->getSelectedGenre($id);

                $selectedGenre = Media::model()->selectMediaToGenre($id);

                

                for($i=0;$i<count($selectedGenre);$i++)

                {

                    foreach($selectedGenre[$i] as $genId)

                    $model->genre[$i+1] = $genId;

                }

                //var_dump($model->genre);exit;

		// Uncomment the following line if AJAX validation is needed

		// $this->performAjaxValidation($model);


		if(isset($_POST['Media']))

		{

			$dir = Yii::getPathOfAlias('application.uploaded');

                        $file = CUploadedFile::getInstance($model,'path');

		

                        $model->attributes=$_POST['Media'];

                        $model->path = $dir."\\".$model->name;

                        

			if($model->save())

                        {

                                if(is_object($model->path))

                                $uploded = $file->saveAs($dir."\\".$model->name.".mp3");

                                Media::model()->associateMediaToGenre($model->id,$model->genre);

				$this->redirect(array('view','id'=>$model->id));

                        }

		}


		$this->render('update',array(

			'model'=>$model,

		));

	}


	/**

	 * Deletes a particular model.

	 * If deletion is successful, the browser will be redirected to the 'admin' page.

	 * @param integer $id the ID of the model to be deleted

	 */

	public function actionDelete($id)

	{

		$this->loadModel($id)->delete();


		// if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser

		if(!isset($_GET['ajax']))

			$this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('admin'));

	}


	/**

	 * Lists all models.

	 */

	public function actionIndex($params=null)

	{

                if(isset($_POST['q']))

                    $this->searchSong($_POST['q']);

                

                if(isset($params))

                {

                      if($params=="pop")

                          $ordr = "views";

                      elseif($params =="fav") 

                          $ordr = "top";

                      else

                        throw new CHttpException(400,'Invalid request. Please do not repeat this request again.');

                    

                }

                else $ordr="null";

                

                $criteria = new CDbCriteria();

                $criteria->order= "$ordr".' DESC,id DESC';

                $criteria->with = array('tblGenres');

                $criteria->limit = 1;		

                $this->dataProvider=new CActiveDataProvider('Media',array(

                                    'criteria'=>$criteria,

                                    ));

                

                $this->render('index',array(

			'dataProvider'=>$this->dataProvider

		));

                

	}


	/**

	 * Manages all models.

	 */

	public function actionAdmin()

	{

		$model=new Media('search');

		$model->unsetAttributes();  // clear any default values

		if(isset($_GET['Media']))

			$model->attributes=$_GET['Media'];


		$this->render('admin',array(

			'model'=>$model,

		));

	}


	/**

	 * Returns the data model based on the primary key given in the GET variable.

	 * If the data model is not found, an HTTP exception will be raised.

	 * @param integer the ID of the model to be loaded

	 */

	public function loadModel($id)

	{

		$model=Media::model()->findByPk($id);

		if($model===null)

			throw new CHttpException(404,'The requested page does not exist.');

		return $model;

	}


	/**

	 * Performs the AJAX validation.

	 * @param CModel the model to be validated

	 */

	protected function performAjaxValidation($model)

	{

		if(isset($_POST['ajax']) && $_POST['ajax']==='media-form')

		{

			echo CActiveForm::validate($model);

			Yii::app()->end();

		}

	}

        

        /**

         *

         * @return type URL.

         * Return Path URL of video.

         */

        Public function actionPlayer($param=null)

        {       

                $count=0;

                $criteria = new CDbCriteria();

                $criteria->order= 'id DESC';

                $criteria->with = array('tblGenres');

                $criteria->limit = 10;		

                $this->dataProvider=new CActiveDataProvider('Media',array(

                                    'criteria'=>$criteria,

                                    ));

                

                $VideoPath=$this->dataProvider->getData();

                foreach($VideoPath as $model)

                $_pathUrl[]=$model->path;

                

                if($param==NULL){

                    return substr($_pathUrl[0].".mp3",'24');

                }

                //As you can see i am trying to change my track when click on 

                //previous and next button.For that i want to store my current value.

                [b]else if($param=="pre")

                {   

                    $count--; 

                    return substr($_pathUrl[$count].".mp3",'24');

                }

                else if($param=="next")

                {   

                    $count++;

                    return substr($_pathUrl[$count].".mp3",'24');

                }[/b]

            

        }

        

        /**

         * Search song by Title.

         */

        Private function searchSong($q)

        {

                $criteria = new CDbCriteria();

                     

                $criteria->compare('name', $q, true);

                $criteria->order= 'views DESC,id DESC';

                $this->dataProvider=new CActiveDataProvider("Media", array('criteria'=>$criteria));

                

                $this->render('index',array(

                    'dataProvider'=>$this->dataProvider,

                ));  

        }

        

}




I am not able to store value for $count so that i can decrease or increase when i call pre or next. i

This is the way i am calling actionPlayer().




<script>

                    function playerHandler(str){

                       var audio = document.getElementById('audioPlayer');

                       

                       if(str=="play"){

                            audio.play();

                       }

                       else if(str=="stop"){

                            audio.pause();

                       }

                       else if(str=="pre"){

                               var pre = "<?php echo addcslashes($this->actionPlayer('pre'),'\\') ; ?>";

                               audio.src= pre;

                       }

                       else if(str=="next"){

                               var next = "<?php echo addcslashes($this->actionPlayer('pre'),'\\') ; ?>";

                               audio.src= next;

                       }

                      /* function callAjax(){

                           $.ajax({

                               'url':<?php echo $this->actionPlayer('pre') ; ?>

                               

                           })

                            //var pre = "<?php echo addcslashes($this->actionPlayer('pre'),'\\') ; ?>";

                            //audio.src= pre;

                       }*/

                       

                    }

                    

                </script>



That will be very very helpful if you can tell me the best way to store that value.If i am not bothering you then i have few more question here.

1)How to store $count

2)In actionPlayer() function limit is not working here too :(.

3)I had to write same code in search(), is there any way so that store that value $this->dataProvider=new CActiveDataProvider(‘Media’,array(

                                'criteria'=&gt;&#036;criteria,


                                ));.

Note:-Can not define private static $count=0; in class having error .

As VINEY and I have pointed out, you can use CWebUser::getState() and CWebUser::setSate().




        Public function actionPlayer($param=null)

        {       

                // get the count from the user state. defaults to 0

                $count = Yii::app()->user->getState("palyer-count", 0);

                ...


                else if($param=="pre")

                {   

                    $count--; 

                    // write the count to the user state.

                    Yii::app()->user->setState("palyer-count", $count);

                    return substr($_pathUrl[$count].".mp3",'24');

                }

                else if($param=="next")

                {   

                    $count++;

                    // write the count to the user state.

                    Yii::app()->user->setState("palyer-count", $count);

                    return substr($_pathUrl[$count].".mp3",'24');

                }

            

        }



But be careful, it might be a silly suggestion.

:P @Tsunami

It’s probably because you are joining ‘tblGenres’.

You don’t need to join ‘tblGenres’ here, as you are just retrieving the paths of the files.




        Public function actionPlayer($param=null)

        {       

                // get the count from the user state. defaults to 0

                $count = Yii::app()->user->getState("palyer-count", 0);

                $criteria = new CDbCriteria();

                $criteria->order= 'id DESC';

                // $criteria->with = array('tblGenres');

                $criteria->limit = 10;		

                $this->dataProvider=new CActiveDataProvider('Media',array(

                                    'criteria'=>$criteria,

                                    ));

                ...



I guess the ‘tblGenres’ is a HAS_MANY relation and you have specified ‘together’ option to true in its definition. When you have joined a HAS_MANY relation with ‘together’ option being true, OFFSET and LIMIT will not work as expected.

I don’t think it’s a good idea to store a data provider instance across requests. It’s not an array of retrieved data, but rather a query executor.

I would instead store the search parameters for the data provider.

As for "static" variables, please note that:

  1. You can declare it as a property of a class:



class Foo

{

    public static $count = 0;

    ...



And you have to access it specifying its scope:




// within Foo class

    self::$count++;

// within a Foo derived class

    parent::$count++;

// outside of Foo class

    Foo::$count++;



  1. But it will be reset every time the web server has started PHP to respond to a request. Don’t forget that an ajax request is not an exception.

Thansk a lot dude.You are awesome…Really appreciated.

Hi guys …not working. Please help me stucked here.

You have to tell us what is not working.

Please give us the minimum code which describes your issue.

Hi,

As suggested i am using




 Public function actionPlayer($param=null)

        {       

                $count = Yii::app()->user->getState("palyer-count", 0);

               

                $criteria = new CDbCriteria();

                $criteria->order= 'id DESC';

                //$criteria->with = array('tblGenres');

                $criteria->limit = 1;		

                $this->dataProvider=new CActiveDataProvider('Media',array(

                                    'criteria'=>$criteria,

                                    ));

                

                $VideoPath=$this->dataProvider->getData();

                foreach($VideoPath as $model)

                $_pathUrl[]=$model->path;

                if($param==NULL){

                    return substr($_pathUrl[0].".mp3",'24');

                }

                else if($param=="pre")

                {   

                   // if($count!=0)

                    // $count--;

                    //Yii::app()->user->setState("palyer-count", $count);

                    //return substr($_pathUrl[$count].".mp3",'24');

                }

                else if($param=="next")

                {

                    $count++;

                    // write the count to the user state.

                 Yii::app()->user->setState("palyer-count",$count);

                    return substr($_pathUrl[$count].".mp3",'24');

                }

            

        }



And this the way i am calling it.




<script>

function callAjax(){

                        var audio = document.getElementById('audioPlayer');

                        $.ajax({

                                success:function(data){

                                audio.src= "<?php echo addcslashes($this->actionPlayer('next'),'\\') ; ?>";

                                alert(audio.src);

                                    //console.log(data);

                                },

                                error:function(resp){

                                    console.log(resp);

                                }

                        })

                    }

                </script>

NOw the issue is count increases only when i refresh the page.The no of time i refresh the page $count gets increases.It should increase when i call callAjax() method.

This ajax call will update "audio.src" and change the music to the next one, just once. It will fail in the 2nd try and after.

It’s because the expression “<?php echo addcslashes($this->actionPlayer(‘next’),’\\’) ; ?>” has been evaluated in the server side in the initial loading of the page, and is now a fixed text (something like “http://your.domain/music/a-song.mp3”) in the client browser.

The song counter in the server will be counted up every time you call ajax, but because you have failed to pass the new file name from the server to the client via ajax, the music won’t go to the next one any more.

Ok so what should i do in this case …what is the best way?

Fetch the next music file name via ajax.




<script>

function callAjax(){

    var audio = document.getElementById('audioPlayer');

    $.ajax({

        success:function(data){

            audio.src= data.nextsong;

            alert(audio.src);

            //console.log(data);

...