Views: 577
Last Modified: 18.01.2022

Scalar and nonscalar parameters

Let's overview example of AJAX-action with parameters:

public function renameUserAction($userId, $newName = 'guest', array $groups = array(2))
{
	$user = User::getById($userId);
	...
	$user->rename($newName);
	
	return $user;
}

How to retrieve method parameters?

Scalar parameters $userId, $newName, $groups will be retrieved automatically from REQUEST.

  • Parameter association is case-sensitive.
  • When search is unsuccessful, uses default value, if available.
  • First searches in $_POST, then in $_GET.

Failed search without matching results means that action won't be launched; server will send response with error message informing about missing parameter.

How to integrate objects (nonscalar parameters)?

By default, you can integrate:

The parameter name can be arbitrary. Uses class for association:

public function listChildrenAction(Folder $folder, PageNavigation $pageNavigation);
public function listChildrenAction(Folder $folder, PageNavigation $navigation);
public function listChildrenAction(Folder $folder, PageNavigation $nav, \CRestServer $restServer);

Integrating custom types

Let's start with example:

class Folder extends Controller
{
	public function renameAction($folderId)
	{
		$folder = Folder::getById($folderId);
		if (!$folder)
		{
			return null;
		}
		...
	}
	
	public function downloadAction($folderId)
	{
		$folder = Folder::getById($folderId);
		...
	}
	
	public function deleteAction($folderId)
	{
		$folder = Folder::getById($folderId);
		...
	}
}

We have a standard AJAX-controller for a specific Folder. However, all actions are eventually performed for an object, with an attempt to load folder and etc. It's preferable to receive Folder $folder on input.

class Folder extends Controller
{
	public function renameAction(Folder $folder);
	public function downloadAction(Folder $folder);
	public function deleteAction(Folder $folder);
}

And now it is possible:

class Folder extends Controller
{
	public function getPrimaryAutoWiredParameter()
	{
		return new ExactParameter(
			Folder::class, //full name for subclass to be created 
			'folder', //specific parameter name to be integrated
			function($className, $id){ //function that creates object for integration. Retrieves specific class and $id
				return Folder::loadById($id);
			}
		);
	}
}

In JS call:

BX.ajax.runAction('folder.rename', {
	data: {
		id: 1 
	}
});

It's important that closure after $className can indicate unlimited number of parameters needed for created object. Such parameters will be associated with data from $_REQUEST in the same way as scalars in standard action methods.

class Folder extends Controller
{
	public function getPrimaryAutoWiredParameter()
	{
		return new ExactParameter(
			Folder::class, 
			'folder',
			function($className, $entityId, $entityType){
				return $className::buildByEntity($entityId, $entityType);
			}
		);
	}
	
	public function workAction(Folder $folder);
}

In JS call:

BX.ajax.runAction('folder.work', {
	data: {
		entityId: 1,
		entityType: 'folder-type'
	}
});

When you need to describe several parameters to be created:

class Folder extends Controller
{
	/**
	 * @return Parameter[]
	 */
	public function getAutoWiredParameters()
	{
		return [
			new ExactParameter(
				Folder::class, 
				'folder',
				function($className, $id){
					return $className::loadById($id);
				}
			),
			new ExactParameter(
				File::class, 
				'file',
				function($className, $fileId){
					return $className::loadById($fileId);
				}
			),
		];
	}
	
	public function workAction(Folder $folder, File $file);
}

There is one more general method for describing the integration:

new \Bitrix\Main\Engine\AutoWire\Parameter(
	Folder::class, 
	function($className, $mappedId){
		return $className::buildById($mappedId);
	}
);

In detail: first, we have declared class name which subclasses we will attempt to create when encounter them in AJAX-actions. Anonymous function will created an action instance.

  • $className - specific class name, specified type-hinting.
  • $mappedId - value, retrieved from $_REQUEST. Accordingly, searches folderId in this $_REQUEST. Parameter name that we will search in $_REQUEST by default will be created as {variable name} + Id.
  •       Folder $folder   => folderId
          Folder $nene     => neneId
          File $targetFile => targetFileId 
    

    As the result, you can described the type, if the module has class, for example, Model, from which all entities are inherited:

    new \Bitrix\Main\Engine\AutoWire\Parameter(
    	Model::class, 
    	function($className, $mappedId){
    		/** @var Model $className */
    		return $className::buildById($mappedId);
    	}
    );
    

    Subsequently, you can easily use type-hinting in your AJAX-actions, directly handling the entities.




Courses developed by Bitrix24