Joomla Custom API Routes for Components
Ας πούμε ότι το component σου λέγεται test.
1. Webservices Plugin
Path: plugins/webservices/test/test.php
class PlgWebservicesTest extends CMSPlugin
{
private $router;
public function onBeforeApiRoute(&$router)
{
$this->router = $router;
$router->createCRUDRoutes('v1/test/orders', 'orders', ['component' => 'com_test']);
// Custom route for fetching orders assigned to a specific driver
$this->createDriverOrdersRoute('v1/test/orders/driver', 'orders', ['component' => 'com_test']);
}
/**
* Create route for fetching orders assigned to a specific driver
*
* @param string $baseName The base route name
* @param string $controller The controller name
* @param array $defaults Default route parameters
*
* @return void
*
* @since 1.0.1
*/
private function createDriverOrdersRoute($baseName, $controller, $defaults)
{
$publicGets = false;
$getDefaults = array_merge(['public' => $publicGets], $defaults);
$routes = [
new Route(['GET'], $baseName . '/:id', $controller . '.getDriverOrders', ['id' => '(\d+)'], $getDefaults),
];
$this->router->addRoutes($routes);
}
}
Key Line
new Route(['GET'], $baseName . '/:id', $controller . '.getDriverOrders', ['id' => '(\d+)'], $getDefaults);
getDriverOrdersείναι η συνάρτηση που καλείται από τον controller στοapi/components/com_test/Controller/OrdersController.php.- Η default συνάρτηση για εμφάνιση λίστας είναι
displayList— αν χρησιμοποιήσεις αυτή αντί για custom, θα φορτώσει ό,τι επιστρέφει ηgetListQueryτουcom_test/src/Model/OrdersModel.php.
2. API Controller (Χρήση Model Filter)
Path: api/components/com_test/Controller/OrdersController.php
namespace Test\Component\Test\Api\Controller;
\defined('_JEXEC') or die;
use Joomla\CMS\MVC\Controller\ApiController;
use Joomla\CMS\Response\JsonResponse;
use Joomla\CMS\Filter\InputFilter;
use Joomla\CMS\Uri\Uri;
use Tobscure\JsonApi\Exception\InvalidParameterException;
use Joomla\CMS\Language\Text;
class OrdersController extends ApiController
{
protected $contentType = 'orders';
protected $default_view = 'orders';
/**
* Orders list view with filtering of data based on driver
*
* @return static A BaseController object to support filtering drivers.
*
* @since 4.0.0
* @throws InvalidParameterException
*/
public function getDriverOrders()
{
$filter = InputFilter::getInstance();
// Set filter for the model
$driverId = $this->input->getInt('id', 0);
if ($driverId > 0) {
$this->modelState->set('filter.driver', $filter->clean($driverId, 'INT'));
} else {
$error = Text::sprintf('JLIB_FORM_VALIDATE_FIELD_INVALID', 'id');
throw new InvalidParameterException($error, 400, null, 'registrationDateStart');
}
// Call the orders model list
return parent::displayList();
}
}
Αυτό ορίζει ένα filter που το πιάνει η getListQuery στο model.
3. Component Model
Path: components/com_test/src/models/OrdersModel.php
protected function getListQuery()
{
$db = $this->getDbo();
$query = $db->getQuery(true);
$query->select(
$this->getState('list.select', 'DISTINCT a.*')
);
$query->from($db->quoteName('#__test_orders', 'a'));
// Filter by search in title
$search = $this->getState('filter.search');
if (!empty($search)) {
if (stripos($search, 'id:') === 0) {
$query->where('a.id = ' . (int) substr($search, 3));
} else {
$search = $db->Quote('%' . $db->escape($search, true) . '%');
$query->where('( a.name LIKE ' . $search . ' )');
}
}
// Filtering driver
$filter_driver = $this->state->get("filter.driver");
if ($filter_driver) {
$query->where("a.driver = '" . $db->escape($filter_driver) . "'");
}
// Only new or processing orders
$query->where('a.status!=2 AND a.status!=5');
// Add the list ordering clause
$orderCol = $this->state->get('list.ordering', 'id');
$orderDirn = $this->state->get('list.direction', 'DESC');
if ($orderCol && $orderDirn) {
$query->order($db->escape($orderCol . ' ' . $orderDirn));
}
return $query;
}
Το βασικό κομμάτι για φιλτράρισμα βάσει driver:
// Filtering driver
$filter_driver = $this->state->get("filter.driver");
if ($filter_driver) {
$query->where("a.driver = '" . $db->escape($filter_driver) . "'");
}
4. Εναλλακτικά: Full Custom Response (Χωρίς Model)
Αν δεν θέλεις να χρησιμοποιήσεις το Joomla component model, μπορείς να χειριστείς τα πάντα απευθείας στον controller.
Path: api/components/com_test/Controller/OrdersController.php
namespace Test\Component\Test\Api\Controller;
\defined('_JEXEC') or die;
use Joomla\CMS\MVC\Controller\ApiController;
use Joomla\CMS\Factory;
use Joomla\CMS\Response\JsonResponse;
use Joomla\CMS\Filter\InputFilter;
use Joomla\CMS\Uri\Uri;
use Tobscure\JsonApi\Exception\InvalidParameterException;
use Joomla\CMS\Language\Text;
class OrdersController extends ApiController
{
protected $contentType = 'orders';
protected $default_view = 'orders';
public function getDriverOrders()
{
$this->app->getSession()->set('application.queue', $this->app->getMessageQueue());
header('Content-Type: application/json');
// Uncomment these 3 lines for test purposes to check the response
// $response_data = null;
// echo new JsonResponse($response_data, 'Check', true);
// $this->app->close();
// Get the input
$input = $this->input;
$driverId = $input->getInt('id', 0);
// Get the database object
$db = Factory::getDbo();
// Build the query to get orders assigned to the specified driver_id
$query = $db->getQuery(true)
->select('*')
->from($db->quoteName('#__test_orders'))
->where($db->quoteName('driver') . ' = ' . $db->quote($driverId));
// Execute the query
$db->setQuery($query);
$orders = $db->loadObjectList();
// Return the result as JSON response
echo new JsonResponse($orders, 'Check', false);
$this->app->close();
}
}
API - Postman
Θα δεις λίγο το API του Joomla πώς δουλεύει. Έχει μια εφαρμογή Postman μέσα στον υπολογιστή. Αποσυνδέσου και φτιάξε δικό σου account ή άστο ως έχει.
Πατάς κάτω "Run in Postman".