1. Data Manipulation API (DML)
Never write raw SQL queries unless absolutely necessary. Use the global $DB object.
global $DB;
// Get a single record
$user = $DB->get_record('user', ['id' => 1]);
// Get records
$courses = $DB->get_records('course', ['visible' => 1]);
// Insert
$record = new stdClass();
$record->name = 'New Thing';
$id = $DB->insert_record('my_table', $record);
// Update
$record->id = $id;
$record->name = 'Updated Thing';
$DB->update_record('my_table', $record);
2. Moodle Forms API
Moodle uses a wrapper around PEAR HTML_QuickForm.
require_once($CFG->libdir.'/formslib.php');
class simplehtml_form extends moodleform {
public function definition() {
$mform = $this->_form;
$mform->addElement('text', 'email', get_string('email'));
$mform->setType('email', PARAM_NOTAGS);
$mform->addRule('email', null, 'required', null, 'client');
$this->add_action_buttons();
}
}
3. Events API
Moodle uses an event-driven architecture. You can trigger events or listen for them (Observers).
Triggering an Event
$event = \local_myplugin\event\something_happened::create([
'context' => $context,
'objectid' => $record->id
]);
$event->trigger();
Listening (Observer)
Define the observer in db/events.php:
$observers = [
[
'eventname' => '\core\event\course_completed',
'callback' => 'local_myplugin\observer::course_completed',
],
];
4. File API
Handling files in Moodle is complex because of the secure storage system (files are hashed and stored in moodledata/filedir).
// Saving a file from a form
$mform->save_stored_file('attachment', $context->id, 'local_myplugin', 'attachment', $itemid);
// Serving a file (pluginfile.php)
function local_myplugin_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
// Check permissions...
send_stored_file($file, 0, 0, $forcedownload, $options);
}
5. Navigation API
You can inject links into the primary navigation, user menu, or course settings menu using hooks in lib.php.
// lib.php
function local_myplugin_extend_navigation(global_navigation $nav) {
$mainnode = $nav->add(get_string('pluginname', 'local_myplugin'));
$mainnode->add('My Dashboard', new moodle_url('/local/myplugin/index.php'));
}
function local_myplugin_extend_settings_navigation(settings_navigation $nav, context $context) {
if ($context->contextlevel == CONTEXT_COURSE) {
$coursenode = $nav->get('courseadmin');
$coursenode->add('My Plugin Settings', new moodle_url('/local/myplugin/settings.php'));
}
}
6. Web Services API (Server)
To expose your plugin's functionality to external apps (like the Mobile App), define functions in classes/external.php and register them in db/services.php.
// classes/external.php
use external_api;
use external_function_parameters;
use external_single_structure;
use external_value;
class local_myplugin_external extends external_api {
public static function get_data_parameters() {
return new external_function_parameters([
'id' => new external_value(PARAM_INT, 'The ID')
]);
}
public static function get_data($id) {
// Validate parameters
$params = self::validate_parameters(self::get_data_parameters(), ['id' => $id]);
// Logic...
return ['result' => 'Success'];
}
public static function get_data_returns() {
return new external_single_structure([
'result' => new external_value(PARAM_TEXT, 'Result status')
]);
}
}
6. Output Components (Templatable)
Modern Moodle development separates logic from presentation using the templatable interface.
// 1. Create a class that holds the data for the template
class my_widget implements \renderable, \templatable {
public function export_for_template(\renderer_base $output) {
return [
'title' => 'My Widget',
'items' => ['A', 'B', 'C']
];
}
}
// 2. Render it in your script
$widget = new my_widget();
echo $OUTPUT->render($widget);
// 3. Create the template (templates/my_widget.mustache)
// <div class="widget">
// <h3>{{title}}</h3>
// <ul>{{#items}}<li>{{.}}</li>{{/items}}</ul>
// </div>