PHP, Web Development, Yii Framework

Stop Newrelic from recording slow AJAX/general calls in Yii2

I recently had to stop Newrelic from recording my long polling tactics so I came up with:

<?php

namespace common\components;

use Yii;
use yii\base\Component;
use yii\base\BootstrapInterface;
use yii\web\Application;
use yii\web\Controller;

class Newrelic extends Component implements BootstrapInterface
{
	public $ignoreRoutes = [];
	
	public function bootstrap($app)
	{
		// delay attaching event handler to the view component after it is fully configured
		$app->on(Controller::EVENT_BEFORE_ACTION, function () use ($app) {
			$this->beforeAction($app);
		});
	}
	
	public function beforeAction($app)
	{
		if(extension_loaded('newrelic')){
			if(in_array(Yii::$app->getUrlManager()->parseRequest($app->request)[0], $this->ignoreRoutes)){
				newrelic_ignore_transaction();
			}
		}
	}
}
PHP, Yii Framework

Getting Yii2 debug to show on user role instead of IP

I recently had to get Yii2 debug to show based on whether I was an admin user or not due to not connecting to the site using static IPs.

Having the debug in production run for the admin user is really useful for fixing those problems which are not easily, or possibly, replicated down to development.

So I overrode the Module class for debug but found some problems with view paths. I ended up with:


<?php

namespace common\components;

use Yii;
use yii\debug\Module as DebugModule;
use common\models\User;

class Module extends DebugModule
{
	private $_basePath;
	
	protected function checkAccess()
	{
		$user = Yii::$app->getUser();

		if(
			$user->identity && 
			$user->can('admin')
		){
			return true;
		}
		return parent::checkAccess();
	}
	
	/**
	 * Returns the root directory of the module.
	 * It defaults to the directory containing the module class file.
	 * @return string the root directory of the module.
	 */
	public function getBasePath()
	{
		if ($this->_basePath === null) {
			$class = new \ReflectionClass(new yii\debug\Module('debug'));
			$this->_basePath = dirname($class->getFileName());
		}
	
		return $this->_basePath;
	}
}

PHP, Web Development, Yii Framework

Definition of Yii2 Aliases

Following on from this good article by @KartikV: Yii 2.0: Yii 2 list of path aliases available with default basic and advanced app – I recently needed to use this list to understand what goes into each alias so that I could dupe it for compression in the console. Unfortunately I found no reference for understanding this and the descriptions in that article are not very useful so here is my attempt.

There are a few assumptions made here:

– I have a url of “http://localhost.com/yii” as my base URL
– My app root is at “/srv/www/webapp” in my OS (Linux)

So here is my list:

– @app = /srv/www/webapp/frontend
– @vendor = /srv/www/webapp/frontend/config/../../vendor
– @runtime = /srv/www/webapp/frontend/runtime
– @web = /yii (from “http://localhost.com/yii“)
– @webroot = /srv/www/webapp/frontend/web
– @common = /srv/www/webapp/common
– @frontend = /srv/www/webapp/frontend
– @backend = /srv/www/webapp/backend
– @console = /srv/www/webapp/console

PHP, Yii Framework

Disable Yii2 CSRF on specific actions

I needed to disable the Yii2 CSRF on specific actions recently, mainly due to the action being called from an external source.

What I did was extend the Request object like so:

<?php

namespace common\components;

use Yii;

class Request extends \yii\web\Request
{
	public $noCsrfRoutes = [];
	
	public function validateCsrfToken()
	{
		if(
			$this->enableCsrfValidation && 
			in_array(Yii::$app->getUrlManager()->parseRequest($this)[0], $this->noCsrfRoutes)
		){
			return true;
		}
		return parent::validateCsrfToken();
	}
}

and then added the request component to my config like so:

		'request' => [
			'class' => 'common\components\Request',
			'noCsrfRoutes' => [
				'order/calculate-ns-shipping'
			]
		],

And that works.

PHP, Yii Framework

Using Yii2 RBAC PHP Auth Manager without having to use assign()

I had a problem recently where, after upgrading Yii2 to latest, I had to give auth assignments where previously I did not. I found this cumbersome, mainly since it would mean adding 100,000 entries to the rbac.php file when my auth system is as simple as a single role to a user in a field called role in a row in a user table.

So I looked around to bring back the old functionality, I didn’t get far so then I decided to recode PhpManager to do it for me:

<?php
namespace common\components;

use Yii;

class PhpManager extends \yii\rbac\PhpManager
{
	public function init()
	{
		parent::init();
	}
	
	public function getAssignments($userId)
	{
		if(!Yii::$app->user->isGuest){
			$assignment = new \yii\rbac\Assignment;
			$assignment->userId = $userId;
			$assignment->roleName = Yii::$app->user->identity->role;
			return [$assignment->roleName => $assignment];
		}
	}
}

Feel free to use and abuse.