Caching AuthItems

While profiling my app I found out, that all AuthItems are called from Db each time a ‘checkAccess’ request is raised and the result is not cached within CWebUser.

I don’t think the items will change within one request, so I wrote a small improvement to cache these items within the CDbAuthManager object.




	protected $authItems = array(); // new array


	public function checkAccess($itemName,$userId,$params=array())

	{

		if(!empty($this->defaultRoles) && $this->checkDefaultRoles($itemName,$params))

			return true;


		// items are only called once from db

		if(empty($this->authItems)) { 

			$sql="SELECT name, type, description, t1.bizrule, t1.data, t2.bizrule AS bizrule2, t2.data AS data2 FROM {$this->itemTable} t1, {$this->assignmentTable} t2 WHERE name=itemname AND userid=:userid";

			$command=$this->db->createCommand($sql);

			$command->bindValue(':userid',$userId);

			$this->authItems = $command->queryAll();

		}


		// check directly assigned items

		$names=array();

		foreach($this->authItems as $row)

		{

			Yii::trace('Checking permission "'.$row['name'].'"','system.web.auth.CDbAuthManager');

			if($this->executeBizRule($row['bizrule2'],$params,unserialize($row['data2']))

				&& $this->executeBizRule($row['bizrule'],$params,unserialize($row['data'])))

			{

				if($row['name']===$itemName)

					return true;

				$names[]=$row['name'];

			}

		}

		...

	}



Is there a reason why they are called each time from Db which I’ve missed?

Regards.

When you call Yii::app()->user->checkAccess(‘your_operation’)

then the result is already cached within the same request, see:

Docu

Though on the next request everything is fetched from the database again.

In my application I had about 50 DB requests for every click, a solution I posted here:

RBAC caching

I hope this helps.

Maybe my solution or something similar should be included in the Yii core.

Your solution looks nice. But I’m describing another problem.

The same request to ‘checkAccess’ is cached within CWebUser but for different requests the following query is called each time.




 $sql="SELECT name, type, description, t1.bizrule, t1.data, t2.bizrule AS bizrule2, t2.data AS data2 FROM {$this->itemTable} t1, {$this->assignmentTable} t2 WHERE name=itemname AND userid=:userid";



My improvement caches the resultset of this query so it’s called only once.

Your code might give some additional performance for directly assigned items.

When checking for descendant items the getItemChildren function still fires some sql statements.

I needed a complete caching solution to get rid of all DB calls.

I guess a complete Auth rights loading on login and session storering would be the best way to solve this problem.