We will be creating a custom API for our custom module in Drupal 9 to perform basic CRUD operations using API. We will perform the operations on our custom content type.
Step 1: Creating new folders in the Custom Module
We will create a new folder in our custom module folder (candidates) as the following structure. We will place the API codes in this folder.
Step 2: Creating CandidatesController.php file
In this folder, we will create a new file called 'CandidatesController.php'.
<?php
/**
* @file
* Contains \Drupal\candidates\Controller\CandidatesController.
*/
namespace Drupal\candidates\Controller;
use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Drupal\user\Entity\User;
use Drupal\node\Entity\Node;
use Drupal\Core\Entity;
use Drupal\taxonomy\Entity\Term;
//Controller routines for candidates routes
class CandidatesController extends ControllerBase {
}
Step 3: Writing the APIs for CRUD operations
Now, we will write the different APIs for adding, fetching, editing & deleting the records.
Get All Candidates Details API: get_candidate_detail
Add Candidates Details API: add_candidate_detail
Fetch Single Candidate Details after adding: fetch_candidate_detail
Edit Candidates Details API: edit_candidate_detail
Delete Candidates Details API: delete_candidate
<?php
/**
* @file
* Contains \Drupal\candidates\Controller\CandidatesController.
*/
namespace Drupal\candidates\Controller;
use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Drupal\user\Entity\User;
use Drupal\node\Entity\Node;
use Drupal\Core\Entity;
use Drupal\taxonomy\Entity\Term;
//Controller routines for candidates routes
class CandidatesController extends ControllerBase {
/**
* Get All Candidates Details API
*/
public function get_candidate_detail(Request $request) {
global $base_url;
try{
$content = $request->getContent();
$params = json_decode($content, TRUE);
$uid = $params['uid'];
$user = User::load($uid);
$all_candidates = array();
$query_string = "SELECT node_field_data.langcode AS node_field_data_langcode, node_field_data.created AS node_field_data_created, node_field_data.nid AS nid
FROM {node_field_data} node_field_data
WHERE (node_field_data.status = '1') AND (node_field_data.type IN ('candidate'))
ORDER BY node_field_data_created ASC";
$candidate_fetch_details = \Drupal::database()->query($query_string)->fetchAll();
foreach($candidate_fetch_details as $key => $node_id){
$nodeid = $node_id->nid;
$node = Node::load($nodeid);
$candidate_details['candidate_id'] = $nodeid;
$candidate_details['candidate_name'] = $node->get('title')->value;
$date = date_create($node->get('field_birth_date')->value);
$birth_date = date_format($date, "d/m/Y");
$candidate_details['candidate_dob'] = $birth_date;
$candidate_details['candidate_gender'] = $node->get('field_gender')->value;
$candidate_details['candidate_mobile'] = $node->get('field_mobile')->value;
$candidate_details['candidate_email'] = $node->get('field_email_id')->value;
$candidate_details['candidate_city'] = $node->get('field_city')->value;
$candidate_details['candidate_country'] = $node->get('field_country')->value;
$candidate_details['candidate_description'] = $node->get('field_description')->value;
array_push($all_candidates, $candidate_details);
}
$final_api_reponse = array(
"status" => "OK",
"message" => "All Candidate Details",
"result" => $all_candidates
);
return new JsonResponse($final_api_reponse);
}
catch(Exception $exception) {
$this->exception_error_msg($exception->getMessage());
}
}
/**
* Add Candidates Details API
*/
public function add_candidate_detail(Request $request){
global $base_url;
try{
$content = $request->getContent();
$params = json_decode($content, TRUE);
$uid = $params['uid'];
$user = User::load($uid);
$date = explode('/', $params['candidate_dob']);
$birth_date = $date[2] . "-" . $date[1] . "-" . $date[0];
$newCandidate = Node::create([
'type' => 'candidate',
'uid' => 1,
'title' => array('value' => $params['candidate_name']),
'field_birth_date' => array('value' => $birth_date),
'field_gender' => array('value' => $params['candidate_gender']),
'field_mobile' => array('value' => $params['candidate_mobile']),
'field_email_id' => array('value' => $params['candidate_email']),
'field_city' => array('value' => $params['candidate_city']),
'field_country' => array('value' => $params['candidate_country']),
'field_description' => array('value' => $params['candidate_description']),
]);
// Makes sure this creates a new node
$newCandidate->enforceIsNew();
// Saves the node, can also be used without enforceIsNew() which will update the node if a $newCandidate->id() already exists
$newCandidate->save();
$nid = $newCandidate->id();
$new_candidate_details = $this->fetch_candidate_detail($nid);
$final_api_reponse = array(
"status" => "OK",
"message" => "Candidate Details Added Successfully",
"result" => $new_candidate_details,
);
return new JsonResponse($final_api_reponse);
}
catch(Exception $exception) {
$this->exception_error_msg($exception->getMessage());
}
}
public function fetch_candidate_detail($nid){
if(!empty($nid)){
$node = Node::load($nid);
$date = date_create($node->get('field_birth_date')->value);
$birth_date = date_format($date, "d/m/Y");
$candidate_details['candidate_name'] = $node->get('title')->value;
$candidate_details['candidate_dob'] = $birth_date;
$candidate_details['candidate_gender'] = $node->get('field_gender')->value;
$candidate_details['candidate_mobile'] = $node->get('field_mobile')->value;
$candidate_details['candidate_email'] = $node->get('field_email_id')->value;
$candidate_details['candidate_city'] = $node->get('field_city')->value;
$candidate_details['candidate_country'] = $node->get('field_country')->value;
$candidate_details['candidate_description'] = $node->get('field_description')->value;
$final_api_reponse = array(
'candidate_detail' => $candidate_details
);
return $final_api_reponse;
}
else{
$this->exception_error_msg("Candidate details not found.");
}
}
/**
* Edit Candidates Details API
*/
public function edit_candidate_detail(Request $request){
global $base_url;
try{
$content = $request->getContent();/* reads json input from login API callback */
$params = json_decode($content, TRUE);
$uid = $params['uid'];
$user = User::load($uid);
$nid = $params['nid'];
$date = explode('/', $params['candidate_dob']);
$date_of_birth = $date[2] . "-" . $date[1] . "-" . $date[0];
if(!empty($nid)){
$node = Node::load($nid);
$node->set("field_birth_date", array('value' => $date_of_birth));
$node->set("field_gender", array('value' => $params['candidate_gender']));
$node->set("field_mobile", array('value' => $params['candidate_mobile']));
$node->set("field_email_id", array('value' => $params['candidate_email']));
$node->set("field_city", array('value' => $params['candidate_city']));
$node->set("field_country", array('value' => $params['candidate_country']));
$node->set("field_description", array('value' => $params['candidate_description']));
$node->save();
$final_api_reponse = array(
"status" => "OK",
"message" => "Candidate Details Updated Successfully",
);
}
else{
$final_api_reponse = array(
"status" => "FAIL",
"message" => "Candidate ID is reqired",
);
}
return new JsonResponse($final_api_reponse);
}
catch(Exception $exception) {
$this->exception_error_msg($exception->getMessage());
}
}
/**
* Delete Candidates Details API
*/
public function delete_candidate(Request $request){
global $base_url;
try{
$content = $request->getContent();
$params = json_decode($content, TRUE);
$nid = $params['nid'];
if(!empty($nid)){
$node = \Drupal::entityTypeManager()->getStorage('node')->load($nid);
$node->delete();
$final_api_reponse = array(
"status" => "OK",
"message" => "Candidate record has been deleted successfully",
);
}
return new JsonResponse($final_api_reponse);
}
catch(Exception $exception) {
$web_service->error_exception_msg($exception->getMessage());
}
}
}
Step 4: Adding the API in routing.yml
Now we will add the API paths in the candidates.routing.yml file
get_candidate_detail:
path: 'api/get_candidate_detail'
defaults: { _controller: '\Drupal\candidates\Controller\CandidatesController::get_candidate_detail' }
methods: [POST]
requirements:
_permission: 'access content'
add_candidate_detail:
path: 'api/add_candidate_detail'
defaults: { _controller: '\Drupal\candidates\Controller\CandidatesController::add_candidate_detail' }
methods: [POST]
requirements:
_permission: 'access content'
edit_candidate_detail:
path: 'api/edit_candidate_detail'
defaults: { _controller: '\Drupal\candidates\Controller\CandidatesController::edit_candidate_detail' }
methods: [POST]
requirements:
_permission: 'access content'
delete_candidate :
path: 'api/delete_candidate'
defaults: { _controller: '\Drupal\candidates\Controller\CandidatesController::delete_candidate' }
methods: [POST]
requirements:
_permission: 'access content'
Step 5: Using the APIs
Using Postman, we can use the different APIs to add, edit, delete & fetch data from our custom content type.
We will have to set the header Content-Type as application/json & method POST.
The following params can be used to add candidate data:
{
"candidate_name" : "Rahul Khan",
"candidate_dob" : "10/12/1990",
"candidate_gender" : "male",
"candidate_mobile" : "9876543210",
"candidate_email" : "rahul@khan.com",
"candidate_city": "Bangalore",
"candidate_country" : "India",
"candidate_description" : "Hello. Test description."
}
For editing, we can use the above params to edit data. For deleting a record, we will need to pass candidate_id (nid).
Top comments (2)
Here, some clarifications are required.
1) A content type might be made with the required fields those are shown in the POST method.
2)
entityManager
will beEntityTypeManager
as it has been deprecated.I have created a custom content type to store the data & it is mentioned in my previous post & the link is mentioned in this article above. And, thank you for pointing out about the 'entityManager' function.
dev.to/rahulk1011/custom-module-in...