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.