The services module exposes most of Drupal core's data as resources and provides CRUD operations and additional actions for each. In this lesson Joe will look at the available resources, talk about the various CRUD operations and actions and then enable the node resource and demonstrate retrieving node data as JSON from the services endpoint.
Additional resources
JSON Formatter - Chrome plugin to display results of a JSON request in a nicer way.
While cURL may not be the simplest way to interact with a REST API it is the most ubiquitous and the one that is most often referenced in documentation through the web. So to ensure that students have at least a baseline of understanding, and will know how to read the documentation in the future, in this lesson Joe takes a quick look at how to test our API with cURL by retrieving, and creating data.
Example Commands:
`curl http://localhost/demos/services-7x/docroot/api/v1/node/1`
`curl --data '{"title":"hello world!","type":"page"}' --header "Content-Type:application/json" http://localhost/demos/services-7x/docroot/api/v1/node`
Additional resources
Instead of using the CLI to test our API we can use the powerful Chrome REST Console plugin instead. This provides a nice GUI and makes it a little easier to both test and understand what is going on. In this lesson Joe looks at installing the plugin and making basic requests to our API using the REST Console interface.
Additional resources
The Chrome plugin demonstrated in this video is no longer available but there are many alternatives available. Use Postman or search for "REST client" to find tooling options.
In this lesson Joe will demontrate using additional parameters and arguments to refine the returned data when making requests from our API. As well as walking through the code that shows where the various parameters are defined and how you can find what options are available. Finally, we install the services tools module which provides some additional documentation.
Additional resources
Services implements resources for all of core's basic data types but sometimes the information returned in the response is either to much or to little and we want to make changes to the response data. In this lesson Joe will look at how we can write a simple custom module that implments basic hooks provided by the services module to allow us to alter the response returned by a request to the node resource.
Most of the actions we want to perform and data we want to retrieve from an API is likely restricted to authenticated users. This lesson will outline the process of making an authenticated request and walk the user through the configuration that is required for our services endpoint in order to start allowing session based authentication.
In this lesson Joe walks through making authenticated requests to our API with cURL. Although cURL can be a bit verbose when making authenticated requests it serves as a good way to talk about all the headers that are a required and a lowest common denominator for how you could accomplish authentication in just about any language or application.
Example commands
curl http://services-demo.lan/api/v1/user/login -d '{"name":"admin","pass":"admin"}' -H "Content-type: application/json" -H "Accept: application/json"
curl http://services-demo.lan/api/v1/system/connect -X POST
curl http://services-demo.lan/api/v1/system/connect -H "Cookie: SESS60f8c5b86739b7e326223b4ef35867b2=A86XHGJWlnDcMOGcArbOT-qHrsIi5P2NrcoNTXwWluw" -H "X-CSRF-Token: T77haXwD7JKOJsBlKP3p3kLbjQO96bQWvGJAE1_PUZM" -X POST
curl http://services-demo.lan/api/v1/user/login -X POST -H "Content-type: application/json" -H "Accept: application/json"
In this lesson Joe walks through making authenticated requests using the Chrome REST Console Plugin
Additional resources
The Chrome plugin demonstrated in this video is no longer available but there are many alternatives available. Use Postman or search for "REST client" to find tooling options.
All the power of views made available to your API. Really, what else is there to say? In this lesson Joe walks through installation and basic configuration of the services views module which provides the ability to expose views as resources via the services module.
Additional resources
In addition to using views to expose lists of things via our API we can also take advantage of views exposed filters to allow API consumers more control over the data they are receiving in a request. In this lesson Joe looks at accessing views exposed filters via REST requests by adding an exposed filter to both of the perviously created views and then walking through how the configuration of the view changes the behavior of the filter when used via the services API.
In addition to the built in support for core's data and actions the services module also provides a robust framework for exposing the data and actions of our custom modules as an API. In this lesson Joe writes a basic module which creates a custom resource for saving and retrieving a "checked in" status for an authenticated user.
Example commands:
Check a user's status
curl http://localhost/demos/services-7x-test/docroot/api/v1/drupalsquare/1 -H "Accept: application/json"
Check-in a user
curl http://localhost/demos/services-7x-test/docroot/api/v1/drupalsquare/checkin -X POST -H "Content-type: application/json" -H "Accept: application/json" -d '{"uid":1}'
Additional resources
An API that exposes data and actions to a 3rd party is only as good as the documentation for that API. Without good documentation no one will be able to make use of the API you just spent so much energy creating. In this lesson Joe shows some of his favorite API documentation examples and then walks through creating some basic documentation for the resource we created in the previous lesson.
Additional resources
Example - GitHub API Documentation
Example - Recurly Documentation
http://apiary.io - tool to assit in writing good documentation
This lesson takes a look at working with the already existing entities in Drupal such as users and nodes and demonstrates some best practices for working with them in your own custom module. We'll focus on writing code that will work with any entity type and isn't hard coded to work with just nodes or just entities.
Additional notes:
There is a typo in the video. Joe created the variable $types = 'comment'; in one spot and then used it as entity_load($type, ... which obviously wouldn't work because the later is missing an 's' on the end. The downloadable code for this video doesn't have the typo.
Additional resources
This chapter shows how to cluster different form elements into fieldsets as well as how to expand the Forms API renderable array a tree that preserves the structure and hierarchy of the form. We'll expand the Form Fun example module and talk about the #tree property. This video uses krumo() and dsm() functions. You will need to download, install, and enable the devel module to use these functions. These functions allow you to see what variables are available to you. To accomplish the same task without using the devel module, you can add the following snippet to your module: drupal_set_message('' . print_r($vars, true) .'');
Note: There is a typo in the code used in this video. The function form_fun_tree()
is missing a parameter, and should be as follows function form_fun_tree($form, &$form_state)
.
This lesson demonstrates the bare minimum needed to create a custom entity type and to load an Entity from the database. We’ll look at implementing a minimum viable hook_entity_info, talk about the relationship between the Entity API and the Schema API and use entity_load to retrieve a single entity record from the database.
Note, although it would be considered best practices to name the entity with the name of the module, e.g. videoentity_video, we did not include the module name prefix here because it is tedious to type it all out and to say "videoentity_video" without confusing people.
In the next lesson we'll cover the various entity classes and how they work. However, if you just want to get straight to using your entity and doing things like $entity = entity_load();
you'll need to declare a controller for your new entity type. Simply add this 'controller class' => 'EntityAPIController'
in hook_entity_info()
. That will get you started, and well talk about what exactly that line does in the next lesson.
Note: the video doesn't mention the 'primary key'
element in the schema array (although it is in the code). This bit is necessary for the schema to install properly and work with the Entity API so if you're following a long make sure you add that part as well.
Additional resources
This video goes through the process of creating a configuration form in order to save settings to the variables table in the database, and how to integrate those variables into your module.
Correction
The $item
array in the function demo_menu()
should be named $items
, to match the return $items;
line. (Either that or return $items;
should be fixed to return $item;
.) Just make sure the array you are building matches the name of the variable you are returning.
Additional resources
This video walks through the handy devel module from http://drupal.org/project/devel and demonstrates the tools it provides for debugging, inspecting and analyzing the code and SQL queries happening on your site. In this video you'll also learn about some of the helper functions built into the devel module that make it simpler to inspect the large nested arrays that you'll commonly come across when writing code for Drupal.
You may not have heard of the function dsm() before now. It is a legacy function and dpm() is the newer name. The two functions are identical since dsm() is just a wrapper for dpm().
The idea is that dsm() was a poor name for the function, it's short for drupal set message, but what was later decided that drupal print (as in print_r) message was better.
The difference between those two and kpr() is that dpm() does a permissions check to make sure the current user has permission to view devel's output, and then puts the krumo'd variable dump into the message queue via drupal_set_message(). This means that dpm() will work and let you see the output even if you're redirected. Great for debugging forms. kpr() just krumo's and dumps the value right here, right now. No permission check, no regard for where the content is being spit out.
This videos goes through the process of creating a form with Drupal Forms API that is single select list that has a validation, submission and redirect functionality.
NOTE:
Their is a typo in the code displayed in the video. The function
function form_fun_cake(&$form_state)
is missing the $form paramater and should instead be
function form_fun_cake($form, &$form_state)
Curious about when you're supposed to translate "title" and when you should leave it alone? Here's the answer: You don't need to translate the 'title' attribute of an array that defines a menu item because Drupal will take care of that automatically. In fact, you shouldn't translate those as they'll end up getting double translated if you do. This is because Drupal end's up using this string of text in a number of different ways some of which don't actually need to be translated and others that do like for example when it's the title of a page or the text of a link in the menu system. The #title (and #description) property for elements in Form API array however are your responsibility to translate.
Probably the most common use case for view modes is teaser nodes. Or, a node being rendered in the teaser view mode. View modes allow entities to be displayed different depending on context, and also allow other modules like Field API that participate in the entity rendering process to adjust their behavior depending on the requested view mode.
In this lesson we’re going to take a look at an ‘authenticated’ view mode that we can use to adjust the display for any authenticated users. Then we’ll update Entity Controller class and make use of this new view mode in our ::view() method.
NOTE: in the video Joe forgot to change the 'member' label to "Member" and then later in the video when we view it in the UI it is corrected. The sample code included with this video has the correct label.
In this lesson we're going to take a more in-depth look at the UI controller we used earlier to create our administrative UI for the entity. We'll walk through how the controller adds menu paths and the like, without us needing to do any extra work, and then clean up our form-builder functions by overriding the UI controller's method, so that we can gain control of the name of the function that's called.