How to write your own action in Yii2 and reuse it in different controllers

How to write your own action in Yii2 and reuse it in different controllers

Before developing any relatively large product using a framework, I would recommend deeply exploring its capabilities.

Today, we’ll talk about actions — but not the ones that are “hardcoded” into our controllers. Instead, we’ll look at actions that can be reused across different controllers by registering them through the controller’s actions() method:

public function actions()
{
	$actions = parent::actions();
	
	$actions['aj-avatar-upload'] = [
		'class' => 'commonactionuserAjaxAvatarUploadAction',
	];
	$actions['aj-avatar-delete'] = [
		'class' => 'commonactionuserAjaxAvatarDeleteAction',
	];
	
	return $actions;
}

You’ll encounter such "actions" early on, when looking at the configuration file where the error action is defined:

'errorHandler' => [
	'errorAction' => 'site/error',
],

Now, more details on usage. I didn’t invent the wheel here — and unfortunately, I hadn’t seen this approach earlier — but these types of actions are very convenient for creating reusable templates for standard operations (especially in admin panels):

  • record listing
  • creation
  • editing
  • deletion (including file or files)
  • sorting

Below, I’ll just show examples of two actions — creation and deletion.

Action for creating a record:

use Yii;
use yiibaseAction;

class AddAction extends Action
{
	public $Model;
	public $model_config = [];
	public $view = '@backend/actions/object/view/add';
	public $view_model = 'ModelForm';
	public $flash;
	public $text = [];
	
	public function init()
	{
		parent::init();
		
		if($this -> flash === NULL)
		{
			$this -> flash = Yii::t('app','Object created');
		}
		
		if(isset($this -> text['title']) == false)
		{
			$this -> text['title'] = Yii::t('app', 'Creating Object');
		}
	}
	
	/**
	 * Add
	 * @return mixed
	 */
	public function run()
    {
		$LocalModel = $this -> Model;
		
		$ModelForm = new $LocalModel($this -> model_config);

		if($ModelForm -> load(Yii::$app -> request -> post()) && $ModelForm -> save())
		{
			return $this -> controller -> setFlash(['edit', 'id' => $ModelForm -> id], $this -> flash);
		}

		//View
		$this -> controller -> setBreadcrumbs($this -> text['title']);
		$this -> controller -> setTitle($this -> text['title']);
		return $this -> controller -> render($this -> view, [
			$this-> view_model => $ModelForm,
		]);
	}
}

Action configuration is done within the controller’s actions() method. If a custom view is needed, you can set the view property to point to your own view file. By “default view” I mean a layout that can be reused across different cases (without removing or adding custom form fields). For example — a form with only one Title field for creating list-type records, such as categories, regions, etc.

Action for deleting a record from the database:

use Yii;
use yiibaseAction;
use yiiwebNotFoundHttpException;

class DeleteAction extends Action
{
	public $Model;
	public $field_delete = NULL;
	public $flash = NULL;
	
	public function init()
	{
		parent::init();
		
		if($this -> flash === NULL)
		{
			$this -> flash = Yii::t('app','Object deleted');
		}
	}
	
	/**
	 * Delete row in DB
	 * @param int $id
	 * @return mixed
	 * @throws NotFoundHttpException
	 */
	public function run($id)
    {
		$LocalModel = $this -> Model;
		
		$Model = $LocalModel::findOne([
			'id' => (int) $id
		]);
		if($Model === NULL)
		{
			throw new NotFoundHttpException();
		}

		if(method_exists($Model, 'deleteFile'))
		{
			$field_delete_ar = (array) $this -> field_delete;
			foreach ($field_delete_ar as $field_delete)
			{
				$Model -> deleteFile($Model -> {$field_delete});
			}
		}
		$Model -> delete();
		
		return $this -> controller -> setFlash(['index'], $this -> flash);
	}
}

If the model defines a deleteFile method, then when this action is triggered, it will attempt to delete files from the specified fields.

Are you having problems with your Yii2 framework website? Do you need additional functionality?
>Then write to me via the feedback form, and I will try to help you.

Write a comment

Your email address will not be published. Required fields are marked *