Adding an API to a Joomla Component
From Joomla! Documentation
This page is intended to document how to integrate the API layer introduced in into your existing Joomla component. This assumes that you are using the default Joomla MVC layer
API integration for weblinks extension as an example
Repository extension: https://github.com/joomla-extensions/weblinks
Pull request: https://github.com/joomla-extensions/weblinks/pull/407
First step[edit]
1. Create a folder src/api
2. Create a class WeblinksController
use Joomla\CMS\MVC\Controller\ApiController;
class WeblinksController extends ApiController
{
protected $contentType = 'weblinks';
protected $default_view = 'weblinks';
}
Override the following fields:
$contentType - will be used as default for $modelName as well when outputting response as type object $default_view - will be used as default for $viewName
3. Create a class JsonapiView.php
use Joomla\CMS\MVC\View\JsonApiView as BaseApiView;
class JsonapiView extends BaseApiView
{
protected $fieldsToRenderItem = [
'id',
'catid',
'title',
'alias',
'url',
'xreference',
'tags',
];
protected $fieldsToRenderList = [
'id',
'title',
'alias',
];
}
Override the following fields:
$fieldsToRenderItem - array of fields to display a single object $fieldsToRenderList - array of fields for listing objects
Second step[edit]
1. Create a folder plugins/webservices/weblinks
2. In the weblinks.php, create the class PlgWebservicesWeblinks
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Router\ApiRouter;
class PlgWebservicesWeblinks extends CMSPlugin
{
public function onBeforeApiRoute(&$router)
{
$router->createCRUDRoutes('v1/weblinks', 'weblinks', ['component' => 'com_weblinks']);
}
}
In the onBeforeApiRoute method, register all the routes that we need for webservice.
3. Create weblinks.xml
<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin" group="webservices" method="upgrade">
<name>plg_webservices_weblinks</name>
<author>Joomla! Project</author>
<creationDate>August 2017</creationDate>
<copyright>(C) 2005 - 2019 Open Source Matters. All rights reserved.</copyright>
<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
<authorEmail>admin@joomla.org</authorEmail>
<authorUrl>www.joomla.org</authorUrl>
<version>4.0.0</version>
<description>PLG_WEBSERVICES_WEBLINKS_XML_DESCRIPTION</description>
<files>
##FILES##
</files>
<languages folder="administrator/language">
##LANGUAGE_FILES##
</languages>
</extension>
4. Create files en-GB/en-GB.plg_webservices_weblinks.ini, en-GB/en-GB.plg_webservices_weblinks.sys.ini with next content:
; Joomla! Project
; Copyright (C) 2005 - 2019 Open Source Matters. All rights reserved.
; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
; Note : All ini files need to be saved as UTF-8
PLG_WEBSERVICES_WEBLINKS="Web Services - Weblinks"
PLG_WEBSERVICES_WEBLINKS_XML_DESCRIPTION="Used to add weblinks routes to the API for your website."
Third step[edit]
1. In the file src/administrator/components/com_weblinks/weblinks.xml add a description for the API files
<api>
<files folder="api/components/com_weblinks">
##API_COMPONENT_FILES##
</files>
</api>
2. In the file src/administrator/manifests/packages/pkg_weblinks.xml add a description for webservice plugin
<files>
...
<file type="plugin" id="weblinks" group="webservices">plg_webservices_weblinks.zip</file>
</files>
Categories[edit]
1. Add categories support for weblinks webservice. Edit the file src/plugins/webservices/weblinks/weblinks.php
class PlgWebservicesWeblinks extends CMSPlugin
{
public function onBeforeApiRoute(&$router)
{
...
$router->createCRUDRoutes(
'v1/weblinks/categories',
'categories',
['component' => 'com_categories', 'extension' => 'com_weblinks']
);
}
}
We use the ready-made component com_categories, just need to pass the parameter 'extension' => 'com_weblinks'
Fields[edit]
1. Add fields and fields groups support for weblinks webservice. Edit the file src/plugins/webservices/weblinks/weblinks.php
class PlgWebservicesWeblinks extends CMSPlugin
{
public function onBeforeApiRoute(&$router)
{
...
$router->createCRUDRoutes(
'v1/fields/weblinks',
'fields',
['component' => 'com_fields', 'context' => 'com_weblinks.weblink']
);
$router->createCRUDRoutes(
'v1/fields/groups/weblinks',
'groups',
['component' => 'com_fields', 'context' => 'com_weblinks.weblink']
);
}
}
2. Override the function save in WeblinksController
class WeblinksController extends ApiController
{
...
protected function save($recordKey = null)
{
$data = (array) json_decode($this->input->json->getRaw(), true);
foreach (FieldsHelper::getFields('com_weblinks.weblink') as $field)
{
if (isset($data[$field->name]))
{
!isset($data['com_fields']) && $data['com_fields'] = [];
$data['com_fields'][$field->name] = $data[$field->name];
unset($data[$field->name]);
}
}
$this->input->set('data', $data);
return parent::save($recordKey);
}
...
}
3. Override the functions displayList, displayItem, prepareItem in Weblinks\JsonapiView
class JsonapiView extends BaseApiView
{
...
public function displayList(array $items = null)
{
foreach (FieldsHelper::getFields('com_weblinks.weblink') as $field)
{
$this->fieldsToRenderList[] = $field->name;
}
return parent::displayList();
}
public function displayItem($item = null)
{
foreach (FieldsHelper::getFields('com_weblinks.weblink') as $field)
{
$this->fieldsToRenderItem[] = $field->name;
}
return parent::displayItem();
}
protected function prepareItem($item)
{
foreach (FieldsHelper::getFields('com_weblinks.weblink', $item, true) as $field)
{
$item->{$field->name} = isset($field->apivalue) ? $field->apivalue : $field->rawvalue;
}
return parent::prepareItem($item);
}
...
}
Pay attention in function prepareItem to
$field->apivalue
If the type of the field is complex, we hope that it will return a value for output in the API component, otherwise we will take
$field->rawvalue
Integration Work Example[edit]
Weblinks[edit]
Get List of Weblinks[edit]
curl -X GET /api/index.php/v1/weblinks
Get Single Weblink[edit]
curl -X GET /api/index.php/v1/weblinks/{weblink_id}
Delete Weblink[edit]
curl -X DELETE /api/index.php/v1/weblinks/{weblink_id}
Create Weblink[edit]
curl -X POST -H "Content-Type: application/json" /api/index.php/v1/weblinks -d
{
"access": "1",
"alias": "",
"catid": "8",
"description": "<p>text</p>",
"images": {
"float_first": "",
"float_second": "",
"image_first": "",
"image_first_alt": "",
"image_first_caption": "",
"image_second": "",
"image_second_alt": "",
"image_second_caption": ""
},
"language": "*",
"metadata": {
"rights": "",
"robots": ""
},
"metadesc": "",
"metakey": "",
"modified": "",
"params": {
"count_clicks": "",
"height": "",
"target": "",
"width": ""
},
"title": "weblink title",
"url": "http://somelink.com/",
"xreference": "xreference"
}
Update Weblink[edit]
curl -X PUT -H "Content-Type: application/json" /api/index.php/v1/weblinks/{weblink_id} -d
{
"catid": "8",
"description": "<p>some new text</p>",
"language": "*",
"title": "new title",
"url": "http://newsomelink.com/"
}
Categories[edit]
Route Weblinks Categories is: "v1/weblinks/categories"
Working with it is similar to Banners Categories.
Fields[edit]
Route Fields Weblinks is: "v1/fields/weblinks"
Working with it is similar to Fields Contact.
Groups Fields[edit]
Route Groups Fields Weblinks is: "v1/fields/groups/weblinks"
Working with it is similar to Groups Fields Contact.