Develop Plesk Extensions Series: My first Plesk extension

How to develop Plesk extensions

In the first part (Install a local version of Plesk) we installed Plesk locally and in the second part (Create extension stub and IDE project) we prepared our development environment to get started writing great Plesk extensions. This blog post will give you a brief introduction how to write a simple extension. In the screencast video I will write a Hello World extension within 5 minutes and in the blog article I will explain you the basics with the Pizza extension that I’ve created for this purpose.

Part 3 – My first Plesk extension

Relax and lean back, let me show you how to write a small Hello World extension using the previously created extension stub. In this video you will also see what you can do if you encounter permission right problems while using the deployment feature within PhpStorm. This problem occurs if you upload the extension once within the Plesk instance where you are logged in as another user than the SFTP user that you use to update the modified files. We can solve this issue directly in the terminal using chown for folders and chmod for specific files. Here we go:

Easy, isn’t it? Now let me explain the Pizza extension in more detail. The Pizza extension was my first extension to get into the development of Plesk extensions. Though it is a small extension, it contains many of the basics that you will need for your own extension, such as saving an option value to the database or showing a custom button in the main view.

What does the Pizza extension actually do? It adds a link to your favorite pizza delivery service directly to the main page Websites & Domains. You may specify your own pizza link in the settings. This means that you can use the extension to set a bookmark to any page.

Let’s take a look on a simple Plesk extension

Download the Pizza extension – you can use the ready to go package linked above or get it from the official Plesk Github repository . Unpack the archive in your working directory and add this folder in PhpStorm as a new project. You will see the typical structure that you already encountered if you’ve created an extension stub via command line – what I described in part 2 of this tutorial (with small exceptions).

Let’s go through all files and see what they contain. Use your IDE to navigate through the files. If you’ve setup your environment properly, you will be able to use auto-completion and the documentation of used classes and functions.


  <name>GET Your Pizza!</name>
  <description>Set a link to order a delicious pizza directly from Plesk!</description>

This file is the manifest file. It contains all information about the extension, such as the ID, name, description and version. Keep this file updated (version and release) if you update your extension! Please refer to the official documentation to understand the extensions structure even more profound. See the following page for a detailed description of all parameteres: Extension Structure


This folder contains screenshots and icons for the catalog. It is required to be able to get listed within the official Plesk extension catalog. If you just develop for yourself, you don’t need to create this folder.


$application = new pm_Application();

Here you can find the entry point file (index.php) and the icon that is used to set a custom button. See also part 2 of the tutorial where I’ve described the structure in more detail.


This folder contains the logic of the extension. Here you will find all important PHP and HTML files that are required for the extension.

It is important that you understand the correct structure and naming conventions of Plesk extensions. They are using Zend framework practices, so also the MVC pattern implementation. Please read Step 1 of the following page before you proceed with this tutorial: Exercise 1. Tabs, Forms, Lists, Tools


public function init()

    // Init title for all actions
    $this->view->pageTitle = $this->lmsg('page_title');

public function indexAction()
    // Default action is formAction

This is the main controller of our extension. It extends the abstract class pm_Controller_Action that is used for all extension controllers. With init() we initialize the controller. In the Pizza extension I use the function formAction() as the default action, so I have to forward from the function indexAction().

public function formAction()
    // Set the description text
    $this->view->output_description = $this->lmsg('page_title_description');

    // Init form here
    $form = new pm_Form_Simple();
    $form->addElement('text', 'pizzalink', ['label' => $this->lmsg('form_pizzalink'), 'value' => pm_Settings::get('pizzalink'), 'style' => 'width: 40%;']);
    $form->addControlButtons(['cancelLink' => pm_Context::getModulesListUrl(),]);

    // Process the form - save the license key and run the installation scripts
    if ($this->getRequest()->isPost() && $form->isValid($this->getRequest()->getPost())) {
        if ($form->getValue('pizzalink')) {
            $this->_pizzalink = $form->getValue('pizzalink');

        pm_Settings::set('pizzalink', $this->_pizzalink);

        $this->_status->addMessage('info', $this->lmsg('message_success'));
        $this->_helper->json(['redirect' => pm_Context::getBaseUrl()]);

    $this->view->form = $form;

In formAction() we prepare the form for the settings page and set some variables that we will use in the view file. Additionally, the post request after a click on the save button is processed here.


public function getButtons()
    $buttons = [[
        'place'       => self::PLACE_DOMAIN,
        'title'       => 'GET Your Pizza',
        'description' => 'One click away from a delicious pizza!',
        'icon'        => pm_Context::getBaseUrl().'images/icons/pizza-icon.png',
        'link'        => pm_Settings::get('pizzalink'),
        'newWindow'   => true

    return $buttons;

In this file the custom button is created. The key-value-pair place in the buttons array defines the position of the button. Here we used self::PLACE_DOMAIN to display the button on the domain overview page in the right sidebar. Take a look into the pm_Hook_CustomButtons class to see all possible places.

The Plesk team created a demo extension with many examples how to use the custom button feature. Get it here: Custom Buttons


$messages = [
    'message_success'        => 'Your pizza link was saved successfully!',
    'page_title'             => 'GET your pizza directly from Plesk!',
    'page_title_description' => '<p>Let\'s get cheesy! :-) </p><p>This extension adds a link to your favorite pizza delivery service directly to the main page "Websites & Domains". You may specify your own pizza link in the settings.</p><p>Be Plesky And Enjoy Your Pizza!</p>',
    'form_pizzalink'         => 'Set your own pizza link'

This is the language file, default language is en-US. In this file we define all translation strings in an array. You can see the usage of the strings in the IndexController.php in the form creation call $this->lmsg('LANGUAGESTRING').


pm_Settings::set('pizzalink', '');

This file is only triggered directly after the installation process. I use this call to preset the link in the settings of the extension.


<?php echo $this->output_description; ?>
<?php echo $this->form; ?>

The view files are used to create the output. Here we display the content that was created in the controller (description and form).

Learn from official sources how to write a good extension

That’s all – we are done! You see it is quite easy to get started. Please read the official documentation to understand more about the development of Plesk extensions and take a look on the example extensions in the Plesk GitHub account.

Still reading? Stop now and write your own cool extension. In the next part I will show you how you submit your extension to the official Extensions Catalog. Make all Plesk users happy with your contribution!

Stay Plesky and enjoy coding!

No comment yet, add your voice below!

Add a Comment

Your email address will not be published. Required fields are marked *


  • Yes, please, I agree to receiving my personal Plesk Newsletter! WebPros International GmbH and other WebPros group companies may store and process the data I provide for the purpose of delivering the newsletter according to the WebPros Privacy Policy. In order to tailor its offerings to me, Plesk may further use additional information like usage and behavior data (Profiling). I can unsubscribe from the newsletter at any time by sending an email to [email protected] or use the unsubscribe link in any of the newsletters.

  • Hidden
  • Hidden
  • Hidden
  • Hidden
  • Hidden
  • Hidden

Related Posts

Knowledge Base

Plesk uses LiveChat system (3rd party).

By proceeding below, I hereby agree to use LiveChat as an external third party technology. This may involve a transfer of my personal data (e.g. IP Address) to third parties in- or outside of Europe. For more information, please see our Privacy Policy.