Strange Variable Behavior

Hello All,

I am trying to use the afterAjaxUpdate function for a cgridview.

In the javascript file that I call after the ajax update my php variable values seem to change on their own.

I have this:




  <?php error_log($used_bytes);?>

      alert(<?php echo $used_bytes;?>);



the value of $used_bytes in the error_log output is 0 (like it should be) but the value of $used_bytes when printed in the alert is 6498188 (its value before the ajax update)

how can this be?

Am I missing something?

I am pulling my hair out over this and any help would be greatly appreciated. Thanks

My experience with afterAjaxUpdate is pretty smooth and the behavior you describe doesn’t ring a bell.

Can you post more code please? Also, what’s your Yii version?

Thanks for the reply!

I am using version 1.1.10. As far as more code goes:

This is my view:




<?php

$this->breadcrumbs=array(

	'Files',

);


$this->menu=array(

	array('label'=>'Create File', 'url'=>array('create')),

	array('label'=>'Manage File', 'url'=>array('admin')),

);

?>





<h3 class="sectionHeader">Files</h3>

<span class="shortURL">Your uploaded files</span>

</br>


<?php echo CHtml::submitButton('Upload a new file', array('submit'=>'create', 'class'=>'upload_button'));?>


<?php





$this->widget('zii.widgets.grid.CGridView', array(

    'dataProvider'=>$dataProvider,

    'htmlOptions'=>array("width"=>"10"),

    'enablePagination'=>true,

    'emptyText'=>'You do not have any uploaded files',

    'afterAjaxUpdate'=> 'js:function(){updateBytes()}',

    'columns'=>array(

        // array(

            // 'name'=>'#',

            // 'value'=>function($data,$row){

                // return $data->file_id;

            // },

            // 'type'=>'raw',

	    // 'htmlOptions'=>array("width"=>"5%", "align"=>"center"),

        // ),

        array(

            'name'=>'File Name',

            'value'=>function($data,$row){

                return $data->file_name;

            },

            'type'=>'raw',

	    'htmlOptions'=>array("width"=>"35%", "align"=>"center"),

        ),

        array(

            'name'=>'URL',

            'value'=>function($data,$row){

                return "<a href= http://$data->file_url>".$data->file_url .'</a>';

            },

            'type'=>'raw',

	    'htmlOptions'=>array("width"=>"55%", "align"=>"center")

        ),

        array(

                    'class'=>'CButtonColumn',

                    'template'=>'{delete}',

		    //'footer'=>"the narwhal bacons at midnight",

		    'deleteButtonImageUrl'=>Yii::app()->request->baseUrl."/images/btn_small_del.png",

                    'htmlOptions'=>array("width"=>'5%', "align"=>"center"),

                ),

        ),

	

    )

);


?>


<?php

    $user_id = Yii::app()->user->selectedUser->id;

    $remaining_bytes = File::get_remaining_bytes($user_id, Yii::app()->db);

    $total_mbytes = Storage::model()->find("storage_user_id=$user_id")->storage_size;

    $used_bytes = ($total_mbytes*1024*1024) - $remaining_bytes;

    $percent_used = round((($used_bytes/($total_mbytes*1024*1024))*100),1);

?>


<table class = 'info_table'>

	<tr>

		<th colspan="4">Storage</th>

	</tr>

	<tr>

		<td id='used_bytes'>

			<?php error_log($remaining_bytes . " " . $total_mbytes . " " . $used_bytes . " " );

			echo "USED: ".round(($used_bytes/1024/1024),1)." MB</br>"; ?>

		</td>

		<td>

			<?php echo "FREE: ".round(($remaining_bytes/1024/1024),1)." MB</br>"; ?>

		</td>

		<td>

			<?php echo "TOTAL: ".$total_mbytes." MB</br>"; ?>

		</td>

		<td>

			<?php echo "You have used ". $percent_used . "% </br> of your total file space"; ?>

		</td>

	</tr>

</table>


</br>




<script type="text/javascript">

    function updateBytes(){

      <?php error_log($used_bytes);?>

      alert(<?php echo $used_bytes;?>);

 

       

    };

</script>






This is the controller for that view:




<?php


define('DOWNLOAD', 'dlf=');

define('USER', '&u=');

//define('website')


class FileController 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'.

		

	   NATE:   I commented this out to that the view would only fill the right half of the app

		instead of openeing a whole new page with just the list of files

	 */

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

	

	


	/**

	 * @return array action filters

	 */

	public function filters()

	{

		return array(

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

		);

	}


	/**

	 * 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', 'update' and 'delete' actions

				'actions'=>array('create','update','delete','upload','yesoverwrite','nooverwrite'),

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

			),

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

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

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

			),

			array('deny',  // deny all users

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

			),

		);

	}


	public function actionTest(){

		error_log("in test");

	}




	/**

	 * 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),

			//'storage'=>Storage::model()->find("'storage_user_id'=>$id")

		

		));

	}


	/**

	 * Creates a new model.

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

	 */

	public function actionCreate()

	{

		$model=new File;

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

        {


        	//error_log('isset if');

			

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

            

            $model->image=CUploadedFile::getInstance($model,'image');

            error_log('IMAGE: '.$model->image); 

            //if($model->save())

            //{

               $user_id=Yii::app()->user->selectedUser->id;

			   

			   //if the user does not have their own directory (by their id) make one for them

			   $folders = scandir(Yii::app()->basePath . '/../assets/Files/');

			   if(!in_array($user_id, $folders)){

			      mkdir(Yii::app()->basePath . '/../assets/Files/'.$user_id);

			   }

			   			   

			   

			   

			   $file_hashed = $this->hashFileName($model->image);

			   	   

			  

			   if(file_exists(Yii::app()->basePath . '/../assets/Files/'.$user_id.'/' . $file_hashed)){

					//$this->addError($attribute, 'You have already uploaded a file with that name, change the name and try again');

					error_log("FILE EXISTS");

					

					//create the user a temp folder if they do not have one

					if(!is_dir(Yii::app()->basePath . '/../assets/Files/'.$user_id.'/' . 'temp')){

						mkdir(Yii::app()->basePath . '/../assets/Files/'.$user_id.'/' . 'temp');

					}

					

					//delete any existing temp files

					// $tempFiles = scandir(Yii::app()->basePath . '/../assets/Files/'.$user_id.'/' . 'temp');

					// foreach ($tempFiles as $tf) {

						// unlink(Yii::app()->basePath . '/../assets/Files/'.$user_id.'/' . 'temp/'.$tf);

					// }

					

					

					//save the image to the temp folder

					$model->image->saveAs(Yii::app()->basePath . '/../assets/Files/'.$user_id.'/temp/' . $model->image);

					

					

					$this->actionOverwrite($model);

			   }else{

			   		//file_name

			   		error_log('IMAGE: '.$model->image); 

       		   		$model->file_name = $model->image;

					error_log('saved file name');

					//file_hashed

					$model->file_hash = $file_hashed;

					

			   		//file_user_id

			 		$model->file_user_id = $user_id;

			   		

					

					//company name

					$cmpname = Yii::app()->user->selectedUser->user_company_name;

			   		$model->file_owner_cmpname = $cmpname;

			   		

			   		

					//url

					

					//////////////////////////////////////////////////////////

					//THIS LINE NEEDS TO CHANGE WHEN IT GOES ONTO THE SERVER//

					//////////////////////////////////////////////////////////

					//$url = pinpoint.bigredpin.com/download.php?.DOWNLOAD.$file_hashed.USER.$user_id;

			   		$url = '192.168.1.28/pinpoint/download.php?'.DOWNLOAD.$file_hashed.USER.$user_id;

					//////////////////////////////////////////////////////////

					//////////////////////////////////////////////////////////

					//////////////////////////////////////////////////////////

					

			   		error_log($url);

			   		$model->file_url = $url;

					error_log("right before save" . $model->file_name);

					//save the file

			   		if($model->save()){

					       $file_name = $model->image;

					   

			               //hash the file name (remove the extension, hash the name, re-append the extension)

						   $f_name = substr($file_name, 0, strpos($file_name, '.'));

						   $ext = substr($file_name, strpos($file_name, '.'));

						   //echo "FILENAME - EXT: ".$f_name.'</br>';

						   //echo "EXT: ".$ext.'</br>';

						   $file_name_hashed = md5($f_name);

						   $file_hashed = $file_name_hashed.$ext;

						   //echo "HASED FILE NAME ".$file_hashed."</br>";

					    	

		               		$model->image->saveAs(Yii::app()->basePath . '/../assets/Files/'.$user_id.'/' . $file_hashed);

					    	error_log("hey its saved");

					    	// redirect to success page

		               		

		               		

		               		$this->redirect('index');

            

				    } else {

						error_log("no save");

					}

			   		 

			   }	

                

        }

        $this->render('create', array('model'=>$model));

	}


	public function saveFile($file){

		$model = new File;

	}




	public function wipeUserTempDir($user_id){

		error_log("Wiping user data");	

		$dirPath = 	Yii::app()->basePath . '/../assets/Files/'.$user_id.'/' . 'temp';

		

			

		if (! is_dir($dirPath)) {

        	throw new InvalidArgumentException('$dirPath must be a directory');

	    }

	    if (substr($dirPath, strlen($dirPath) - 1, 1) != '/') {

	        $dirPath .= '/';

	    }

	    $files = glob($dirPath . '*', GLOB_MARK);

	    foreach ($files as $file) {

		        unlink($file);

    	}

    	rmdir($dirPath);

	}

	

	

	public function hashFileName($filename){

		 //file_hash

		$f_name = substr($filename, 0, strpos($filename, '.'));

		$ext = substr($filename, strpos($filename, '.'));

		$file_name_hashed = md5($f_name);

		$file_hashed = $file_name_hashed.$ext;

		return $file_hashed;

	}




	public function actionYesoverwrite(){

		$user_id = Yii::app()->user->selectedUser->id;

		error_log($user_id);

		error_log("PATH: ". Yii::app()->basePath . '/../assets/Files/'.$user_id.'/temp');

		$files = scandir(Yii::app()->basePath . '/../assets/Files/'.$user_id.'/temp',1);

		$file = $files[0];

		

		$file_hashed = $this->hashFileName($file);

		

		

		//delete the old file

		unlink(Yii::app()->basePath . '/../assets/Files/'.$user_id.'/'.$file_hashed);

		

		//copy the file to its new home

		copy(Yii::app()->basePath . '/../assets/Files/'.$user_id.'/temp/'.$file, Yii::app()->basePath . '/../assets/Files/'.$user_id.'/'.$file_hashed);

		

		//wipe the users temp dir

		$this->wipeUserTempDir($user_id);

		$this->redirect('index');

	}


	public function actionNooverwrite(){

			//delete the temp dir and all the files in it

			$user_id = Yii::app()->user->selectedUser->id;

			$this->wipeUserTempDir($user_id);

			$this->redirect('create');

			

		

	}

	

	

	public function actionOverwrite($model){

		$this->render('overwrite',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);


		// Uncomment the following line if AJAX validation is needed

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


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

		{

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

			if($model->save())

				$this->redirect(array('view','id'=>$model->file_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)

	{

		error_log("Hey, now we are in delete");

		error_log("in action delete");

		

		// we only allow deletion via POST request

		if(Yii::app()->request->isPostRequest)

		{

			

			error_log("ID: " . $id);

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

			$filename = $model->file_name;

			$f_name = substr($filename, 0, strpos($filename, '.'));

			   $ext = substr($filename, strpos($filename, '.'));

			   $file_name_hashed = md5($f_name);

			   $file_hashed = $file_name_hashed.$ext;

			 

			

			$user_id = $model->file_user_id;

			error_log("Trying to delete ".$user_id.'/'.$file_hashed);

			

			$folders = scandir(Yii::app()->basePath . '/../assets/Files/');

			    if(in_array($user_id, $folders)){

			      

			   	   $files = scandir(Yii::app()->basePath.'/../assets/Files/'.$user_id);

				  	if(in_array($file_hashed, $files)){

				  		error_log("unlinking");

				  		unlink(Yii::app()->basePath.'/../assets/Files/'.$user_id.'/'.$file_hashed);

				  	}else{

				  		

				  		error_log('that file does not exist');

						error_log(Yii::app()->basePath.'/../assets/Files/'.$user_id.'/'.$file_hashed);

				  	}	

			  	}else{

			  		error_log('user does not have a folder');

			  	}	

		

			

			//this deletes the db entry

			$model->delete();

			

			//now we need to delete the actual file in the assets/Files folder

			

			

			

			

			


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

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

				error_log("HERE");

				error_log("It is an AJAX request!!!!!");

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

			}

		}

		else

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

		$dataProvider=new CActiveDataProvider('File');

        

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

			'dataProvider'=>$dataProvider,

			'id'=>$id,

		));

	}


	/**

	 * Lists all models.

	 *

	 * The first method called in FileController.  

	 */

	public function actionIndex(){

		$user_id = Yii::app()->user->selectedUser->id;

		if(!(Yii::app()->user->isAdmin())){

			error_log("This is a regular user");

			//in the case of a regular user we only want to display the files that he/she has uploaded

			$dataProvider=new CActiveDataProvider('File', array('criteria'=>array('condition'=>'file_user_id='.$user_id)));

		}else{

			error_log("This is an admin user");

			$dataProvider=new CActiveDataProvider('File');

		}

		error_log(Yii::app()->user->selectedUser->id);

		//$model->pin_userid = $user_id;

		

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

			'dataProvider'=>$dataProvider,

		));

		

		

	}


	/**

	 * Manages all models.

	 */

	public function actionAdmin()

	{

		error_log("Whoaaaa, watchout we got an admin over here!!!");

		$model=new File('search');

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

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

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


		$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=File::model()->findByPk($id);

		if($model===null)

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

		return $model;

	}


	

	public function actionUpload() {

        $model = new File();

		error_log("BASE PATH: ".Yii::app()->getBasePath());

    	error_log("PATH: ".Yii::app()->getBasePath().'../themes.bigredpin.views.file.uploadForm');

        

    	 $form = new CForm('uploadForm', $model);

		if ($form->submitted('submit') && $form->validate()) {

            $form->model->image = CUploadedFile::getInstance($form->model, 'image');

            //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

            //do something with your file here

            //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

            Yii::app()->user->setFlash('success', 'File Uploaded');

            $this->redirect(array('upload'));

        }

        $this->render('upload', array('form' => $form));

    }

	

	

	

	

	/**

	 * Performs the AJAX validation.

	 * @param CModel the model to be validated

	 */

	protected function performAjaxValidation($model)

	{

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

		{

			echo CActiveForm::validate($model);

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

		}

	}

	

	

	

	

}



Anything else that might help?

Your alert() updateBytes js function is static, ie your php variable is parsed on first render. Yes, even if the ajax request loads the whole view (so the PHP is parsed again, and the actual JS code is updated), the JS function keeps unchanged.

An easy way to check that it


alert(<?php echo time();?>)

A (the?) solution is to use the ajaxUpdate property in combination to update another div that would hold the (updated) result of your variable. And you would alert that div content. Like:


<div id="mySuperSpecialDiv" style="display:none">

<?php

echo time() . ' ' . $used_bytes;

// time() just to make sure it updates :-)

?>

</div>

…

<?php $this->widget('zii.widgets.grid.CGridView', array(

    …

    'ajaxUpdate' => 'mySuperSpecialDiv',

… ?>

<script type="text/javascript">

    function updateBytes(){

      <?php error_log($used_bytes);?>

      alert(<?php echo $used_bytes;?>);

      // new way of doing it:

      alert($('#mySuperSpecialDiv').html());       

    };

</script>