Erro with scope

Hello friends

I’m Studying scope on model, I make a test but returned this error message:

[b]

CDbCommand failed to execute the SQL statement: SQLSTATE[42S22]: Column not found: 1054 Unknown column ‘administrativo’ in ‘where clause’. The SQL statement executed was: SELECT * FROM usuarios t WHERE nivel=administrativo

/var/www/yii/framework/db/CDbCommand.php(516)

504 return $result;

505 }

506 catch(Exception $e)

507 {

508 if($this->_connection->enableProfiling)

509 Yii::endProfile(‘system.db.CDbCommand.query(’.$this->getText().$par.’)’,‘system.db.CDbCommand.query’);

510 $errorInfo = $e instanceof PDOException ? $e->errorInfo : null;

511 $message = $e->getMessage();

512 Yii::log(Yii::t(‘yii’,‘CDbCommand::{method}() failed: {error}. The SQL statement executed was: {sql}.’,

513 array(’{method}’=>$method, ‘{error}’=>$message, ‘{sql}’=>$this->getText().$par)),CLogger::LEVEL_ERROR,‘system.db.CDbCommand’);

514 if(YII_DEBUG)

515 $message .= '. The SQL statement executed was: '.$this->getText().$par;

516 throw new CDbException(Yii::t(‘yii’,‘CDbCommand failed to execute the SQL statement: {error}’,

517 array(’{error}’=>$message)),(int)$e->getCode(),$errorInfo);

518 }

519 }

520

521 /**

522 * Builds a SQL SELECT statement from the given query specification.

523 * @param array $query the query specification in name-value pairs. The following

524 * query options are supported: {@link select}, {@link distinct}, {@link from},

525 * {@link where}, {@link join}, {@link group}, {@link having}, {@link order},

526 * {@link limit}, {@link offset} and {@link union}.

527 * @return string the SQL statement

528 * @since 1.1.6

[/b]

This is my model:




<?php


/**

 * This is the model class for table "usuarios".

 *

 * The followings are the available columns in table 'usuarios':

 * @property integer $id

 * @property string $usuario

 * @property string $senha

 * @property string $nome

 * @property string $nivel

 * @property string $data

 */

class Usuarios extends CActiveRecord

{

    const GERENTE = 'gerente';

    const ADMINISTRATIVO = 'administrativo';

    const MANUTENCAO = 'manutenção';

    const CAIXA = 'caixa';

	/**

	 * Returns the static model of the specified AR class.

	 * @return Usuarios the static model class

	 */

	public static function model($className=__CLASS__)

	{

		return parent::model($className);

	}


	/**

	 * @return string the associated database table name

	 */

	public function tableName()

	{

		return 'usuarios';

	}


	/**

	 * @return array validation rules for model attributes.

	 */

	public function rules()

	{

		// NOTE: you should only define rules for those attributes that

		// will receive user inputs.

		return array(

			array('usuario, senha, nome, nivel', 'required'),

			array('usuario, nome', 'length', 'max'=>255),

			array('senha, nivel', 'length', 'max'=>50),

			array('data', 'safe'),

			// The following rule is used by search().

			// Please remove those attributes that should not be searched.

			array('id, usuario, senha, nome, nivel, data', 'safe', 'on'=>'search'),

		);

	}


	/**

	 * @return array relational rules.

	 */

	public function relations()

	{

		// NOTE: you may need to adjust the relation name and the related

		// class name for the relations automatically generated below.

		return array(

		);

	}


	/**

	 * @return array customized attribute labels (name=>label)

	 */

	public function attributeLabels()

	{

		return array(

			'id' => 'Id',

			'usuario' => 'Usuario',

			'senha' => 'Senha',

			'nome' => 'Nome',

			'nivel' => 'Nivel',

			'data' => 'Data',

		);

	}


	/**

	 * Retrieves a list of models based on the current search/filter conditions.

	 * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.

	 */

	public function search()

	{

		// Warning: Please modify the following code to remove attributes that

		// should not be searched.


		$criteria=new CDbCriteria;


		$criteria->compare('id',$this->id);


		$criteria->compare('usuario',$this->usuario,true);


		$criteria->compare('senha',$this->senha,true);


		$criteria->compare('nome',$this->nome,true);


		$criteria->compare('nivel',$this->nivel,true);


		$criteria->compare('data',$this->data,true);


		return new CActiveDataProvider('Usuarios', array(

			'criteria'=>$criteria,

		));

	}

        

        public function scopes() 

        {

            return array('gerente' => array('condition' => 'nivel='.self::GERENTE),

            'administrativo' => array('condition' => 'nivel='.self::ADMINISTRATIVO),

            'manutencao' => array('condition' => 'nivel='.self::MANUTENCAO),

            'caixa' => array('condition' => 'nivel='.self::CAIXA));

        }

}



This is my controller:




<?php


class UsuariosController 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';


	/**

	 * @var CActiveRecord the currently loaded data model instance.

	 */

	private $_model;


	/**

	 * @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

	 */

   

        protected function getAdministradores() 

        {

            $m = array();

            $adms = Usuarios::model()->administrativo()->findAll();

            foreach($adms as $k => $adm) { $m[] = $adm->usuario; }

            return $m;

        }

        

	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('index','view','create','update'),

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

			),

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

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

				'users'=>array($this->getAdministradores()),

			),

			array('deny',  // deny all users

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

			),

		);

	}


	/**

	 * Displays a particular model.

	 */

	public function actionView()

	{

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

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

		));

	}


	/**

	 * Creates a new model.

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

	 */

	public function actionCreate()

	{

		$model=new Usuarios;


		// Uncomment the following line if AJAX validation is needed

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


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

		{

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

			if($model->save())

				$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.

	 */

	public function actionUpdate()

	{

		$model=$this->loadModel();


		// Uncomment the following line if AJAX validation is needed

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


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

		{

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

			if($model->save())

				$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 'index' page.

	 */

	public function actionDelete()

	{

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

		{

			// we only allow deletion via POST request

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


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

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

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

		}

		else

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

	}


	/**

	 * Lists all models.

	 */

	public function actionIndex()

	{

		$dataProvider=new CActiveDataProvider('Usuarios');

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

			'dataProvider'=>$dataProvider,

		));

	}


	/**

	 * Manages all models.

	 */

	public function actionAdmin()

	{

		$model=new Usuarios('search');

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

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

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


		$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.

	 */

	public function loadModel()

	{

		if($this->_model===null)

		{

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

				$this->_model=Usuarios::model()->findbyPk($_GET['id']);

			if($this->_model===null)

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

		}

		return $this->_model;

	}


	/**

	 * Performs the AJAX validation.

	 * @param CModel the model to be validated

	 */

	protected function performAjaxValidation($model)

	{

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

		{

			echo CActiveForm::validate($model);

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

		}

	}

}




I don’t know where I wrong, somebody knows?

I would try this

[s]‘administrativo’ => array(‘condition’ => ‘nivel="’.self::ADMINISTRATIVO).’"’,

[/s]

Typo fixed




'administrativo' => array('condition' => 'nivel="'.self::ADMINISTRATIVO.'"'),



/Tommy

Thank’s for the help, but did not work. It show this error:

[b]

Trying to get property of non-object

/var/www/yii/framework/db/schema/CDbCriteria.php(451)

439 * two options cannot be merged (e.g. LIMIT, OFFSET).

440 * @param CDbCriteria $criteria the criteria to be merged with.

441 * @param boolean $useAnd whether to use ‘AND’ to merge condition and having options.

442 * If false, ‘OR’ will be used instead. Defaults to ‘AND’. This parameter has been

443 * available since version 1.0.6.

444 * @since 1.0.5

445 */

446 public function mergeWith($criteria,$useAnd=true)

447 {

448 $and=$useAnd ? ‘AND’ : ‘OR’;

449 if(is_array($criteria))

450 $criteria=new self($criteria);

451 if($this->select!==$criteria->select)

452 {

453 if($this->select===’*’)

454 $this->select=$criteria->select;

455 else if($criteria->select!==’*’)

456 {

457 $select1=is_string($this->select)?preg_split(’/\s*,\s*/’,trim($this->select),-1,PREG_SPLIT_NO_EMPTY):$this->select;

458 $select2=is_string($criteria->select)?preg_split(’/\s*,\s*/’,trim($criteria->select),-1,PREG_SPLIT_NO_EMPTY):$criteria->select;

459 $this->select=array_merge($select1,array_diff($select2,$select1));

460 }

461 }

462

463 if($this->condition!==$criteria->condition)

[/b]

Keep debugging. If still no luck, you should also show the call stack from the exception and the method where you apply the scope.

/Tommy

So a make many tests, and don’t solve de problem, see my code:

this is te call:

model




<?php


/**

 * This is the model class for table "usuarios".

 *

 * The followings are the available columns in table 'usuarios':

 * @property integer $id

 * @property string $usuario

 * @property string $senha

 * @property string $nome

 * @property string $nivel

 * @property string $data

 */

class Usuarios extends CActiveRecord

{

    const GERENTE = 'gerente';

    const ADMINISTRATIVO = 'administrativo';

    const MANUTENCAO = 'manutenção';

    const CAIXA = 'caixa';

	/**

	 * Returns the static model of the specified AR class.

	 * @return Usuarios the static model class

	 */

	public static function model($className=__CLASS__)

	{

		return parent::model($className);

	}


	/**

	 * @return string the associated database table name

	 */

	public function tableName()

	{

		return 'usuarios';

	}


	/**

	 * @return array validation rules for model attributes.

	 */

	public function rules()

	{

		// NOTE: you should only define rules for those attributes that

		// will receive user inputs.

		return array(

			array('usuario, senha, nome, nivel', 'required'),

			array('usuario, nome', 'length', 'max'=>255),

			array('senha, nivel', 'length', 'max'=>50),

			array('data', 'safe'),

			// The following rule is used by search().

			// Please remove those attributes that should not be searched.

			array('id, usuario, senha, nome, nivel, data', 'safe', 'on'=>'search'),

		);

	}


	/**

	 * @return array relational rules.

	 */

	public function relations()

	{

		// NOTE: you may need to adjust the relation name and the related

		// class name for the relations automatically generated below.

		return array(

		);

	}


	/**

	 * @return array customized attribute labels (name=>label)

	 */

	public function attributeLabels()

	{

		return array(

			'id' => 'Id',

			'usuario' => 'Usuario',

			'senha' => 'Senha',

			'nome' => 'Nome',

			'nivel' => 'Nivel',

			'data' => 'Data',

		);

	}


	/**

	 * Retrieves a list of models based on the current search/filter conditions.

	 * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.

	 */

	public function search()

	{

		// Warning: Please modify the following code to remove attributes that

		// should not be searched.


		$criteria=new CDbCriteria;


		$criteria->compare('id',$this->id);


		$criteria->compare('usuario',$this->usuario,true);


		$criteria->compare('senha',$this->senha,true);


		$criteria->compare('nome',$this->nome,true);


		$criteria->compare('nivel',$this->nivel,true);


		$criteria->compare('data',$this->data,true);


		return new CActiveDataProvider('Usuarios', array(

			'criteria'=>$criteria,

		));

	}

        

        public function scopes() 

        {

            return array('gerente' => array('condition' => 'nivel='.self::GERENTE),

            'administrativo' => array('condition' => 'nivel="'.self::ADMINISTRATIVO).'"',

            'manutencao' => array('condition' => 'nivel='.self::MANUTENCAO),

            'caixa' => array('condition' => 'nivel='.self::CAIXA));

        }

}




conteller:





class UsuariosController extends Controller

{

  ...

protected function getAdministradores() 

        {

            $m = array();

            $adms = Usuarios::model()->administrativo()->findAll();

            foreach($adms as $k => $adm) { $m[] = $adm->usuario; }

            return $m;

        }

          

	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('index','view','create','update'),

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

			),

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

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

				'users'=>array($this->getAdministradores()),

			),

			array('deny',  // deny all users

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

			),

		);


	}

...

}




The complete code is on my first post above

this is the complete error message:

Edit: A second look at the stack trace reveals that the error occurs when calling the administrativo scope. I don’t have a ready solution, would have to try this myself. Perhaps later, or somebody else may have the answer.

First thing to do would be to remove the nested array

Change




'users'=>array($this->getAdministradores()),



to




'users'=>$this->getAdministradores(),



Next, verify what value you will return from the method




print_r($m);die;



/Tommy

I couldn’t reproduce the error but now I noticed I have a misplaced parenthesis in #2.

(I have corrected my previous post.)

/Tommy

Thank you Tri for help

This answer solve the problem, I nees fix this to solve


'administrativo' => array('condition' => 'nivel="'.self::ADMINISTRATIVO. '"'),

and


'users'=>$this->getAdministradores(),