Craft is both a fully-featured content management system and a powerful web application framework. Extensions allow you to build on top of its smart abstractions, or create completely new features that live alongside the main application.

This page collects some common extension vectors along that continuum.

Pardon the mess! We just launched this page, and plan to collect more resources here as they are updated with the generator in mind.

Questions? Feedback? Use the links at the bottom of any page to let us know what’s on your mind.

# Monitoring and Changing Behavior

You can be notified when certain things happen within a Craft application by listening for events or registering hooks.

# Events

Events are emitted throughout Craft’s request-response and model life cycles, giving developers a chance to react to (or alter) system behavior. This is far and away the most common point of entry for extensions—if you’re looking for a way to familiarize yourself with Craft’s internals, this is it!

Explore the myriad events Craft emits for customizing the behavior of built-in features.

# Hooks

Hooks are similar to events, but designed specifically for manipulating the context or output of templates. In addition to hooks provided by Craft’s own control panel templates, plugins can fire their own hooks using the {% hook %} tag.

Template Hooks
Inspect template data and modify output with hooks.

# Adding Features

While events enable a wide variety of customizations, some extensions will need to provide entirely new features.

# System Component Types

Craft’s most powerful features like elements and custom fields are built on interfaces and base classes that are also available to developers.

Element Types
Add native-feeling content types to empower content authors and administrators.
Field Types
Custom field types are an essential piece of Craft’s powerful content modeling toolkit.
Filesystem Types
Filesystems are the foundation of Craft’s flexible asset management tools.
Widget Types
Create customizable, heads-up resources for control panel users.
Queue Jobs
Offloading work to a background process can improve the experience and reliability of your plugin’s functionality.

# Miscellany

Other high-impact places to dive in.

Utilities are special, non-content pages in the control panel, that provide access to back-office features or debugging data.

# Working with Data

Getting data from users and processing it safely.

# Controllers + Routing

Learn about requests, routing, URL rules, responses, and Craft’s robust authorization and permissions systems.

Respond to HTTP requests by connecting them with back-end services.
User Permissions
Register a customizable permissions scheme for your plugin’s features.

# Models + Records

Extend built-in data types, define new ones, and consolidate logic.

Behaviors enable plugins to decorate built-in classes with native-feeling attributes and methods.
Services are the clearinghouse for your plugin’s critical operations.
Soft Deletes
Make destructive actions reversible with soft-deletion.

# Caching

Sometimes, it can be expensive to repeatedly generate a dataset, or to block requests while waiting for a third-party API. Craft exposes a configurable cache component (opens new window) that can store temporary data in a consistent way:

use Craft;

$params = [
    'productId' => 1234,

$key = 'my-plugin:' . md5(json_encode($params));

$value = Craft::$app->getCache()->getOrSet($key, function() {
    // Fetch remote data...

    return $data;
}, $duration);

Data returned from this method will be cached with $key for $duration—or, if $key was set within that duration, the data will be returned immediately.

All database queries have a cache() (opens new window) method, as well.

# Using External Services

Many plugins act as a bridge between Craft features and third-party services.

# Making HTTP Requests

Whenever you need to call a remote web service, use the built-in Guzzle (opens new window) factory:

use Craft;

$client = Craft::createGuzzleClient([
    'base_uri' => '',

$response = $client->post('/widgets', [
    'json' => [
        'style' => 'fancy',

Creating HTTP clients this way ensures that all outgoing requests are configured the same way—Craft will apply project-specific settings from the Guzzle config file, as well as a global httpProxy.

Some third-party packages will use their own HTTP client. Whenever possible, provide the equivalent configuration to those adapters. Guzzle configuration (if any was provided) is available through the config service:

// Guzzle config object:
$guzzleConfig = Craft::$app->getConfig()->getConfigFromFile('guzzle');

// HTTP proxy:
$proxyConfig = Craft::$app->getConfig()->getGeneral()->httpProxy;

# Writing Files

Any time your application needs to generate a temporary artifact, you can write it to a file with craft\helpers\FileHelper (opens new window):

use Craft;
use craft\helpers\FileHelper;

$content = '# Todo List';

$filename = '';
$tempDir = Craft::$app->getPath()->getTempPath();

$path = $tempDir . DIRECTORY_SEPARATOR . uniqid() . $filename;

FileHelper::writeToFile($path, $content);

// Pass $path back to another part of the application...

Notice that we’ve used craft\services\Path::getTempPath() (opens new window) to keep our files alongside other runtime data. This helps Craft clean up temporary data via the Caches utility, or the clear-caches/temp-files console command.

Logging should always be done via Craft’s convenience methods, not written directly to disk.

# The Control Panel

Start learning about how to create new views in the control panel.

Control Panel Sections