I was unable to find a single tutorial that would show exactly how to install Laravel on Debian, possibly because I was using PHP 7.0 on Debian, which no other examples seemed to use. As such, I had to take bits and pieces from different websites to make this tutorial on installing Laravel on Debian. The same tutorial will also work for Ubuntu but I found that on Ubuntu 16.04 a lot of the dependencies were already installed out of the box, Debian may require more care to make sure everything is present. Once you have all the requirements installed it should be easy to install composer, and once composer is installed Laravel should also be fairly simple if you are doing the right things.

I found that some methods of installing Laravel did not work on my setup, this may have been because it was Debian or because I’d missed a requirement. This is the method that worked for me, and also works on Ubuntu.

Installing Composer

Before starting the most important thing is to make sure to apt-get upgrade and apt-get update… and also, make sure all the Laravel server requirements are installed. Once that’s done, restart/reload and begin. From here, you can install composer by typing these commands into the Linux terminal…

curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer

Installing Laravel

Then navigate to where you want to put the new website and create a new project. The name of the project will be the name of the directory, so here I’ve called it example.com, because it is a shared server…

cd /var/www
sudo composer create-project laravel/laravel example.com --prefer-dist

This way you can easily specify the directory name. There is an alternative method here.

After installation, the last thing it should tell you is what the encryption key is. A good thing to do right away would be to check that this is the same as the value in the .env file. If the installation was successful it should be there, but it is good to check and also to have a first encounter with the .env file!

Configuring your Website to Run Laravel

Now, set up this new domain as normal on your webserver, making sure that instead of pointing to the /var/www/example.com directory, you point to /var/www/example.com/public.

Next, one thing that I was not prepared for with Laravel was the need for the ownerships and permissions to be correct. All the files will probably be owned by the root user, so change them to whichever user they should be (i.e. not root). So, navigate to your web directory and change the owner as follows…

cd /var/www
sudo chown -R youruser example.com

Then, after that navigate to the public folder in your directory and it may not work. First make sure the storage directory has the correct owner, group and permissions…

cd /var/www/example.com
sudo chown -R youruser:www-data storage
sudo chmod -R ug+rwx storage

Changing storgate may fix the problem, or if there are still problems you can also do this for the bootstrap/cache directory.

Now, make sure your site is pointing at the public directory and it should be working now and showing you the Laravel welcome page…

Laravel Welcome Page

If you see a page like this in your browser in the public directory, Laravel was installed and is working.

If not check the requirements are installed, then the permissions, owners and groups. In particular, if it is a brand new web server with no other websites already running on it, check things like mysql and all the requirements for both Composer and Laravel.

Finishing Up

From this stage, if you see the Laravel welcome page you’re all set up. You can set up a database and a database user in mysql and enter the information in the .env file. You should also make sure that mod_rewrite is installed and that your Virtual host config file is allowing it to work.

The internet is gradually becoming more and more encrypted and secure. While this is most important for websites where you might enter sensitive data, like credit card info, it is generally a good thing to have for any website. Browsers now warn surfers if a website is not encrypted. As I write this unsecure, unencrypted websites just have an exclamation mark inside a circle in the location bar, but the trend is towards this warning getting more and more visible on the surfers browser.

As well as having quality content for surfers, you can also try to not turn surfers off your content by having an unencrypted website. Maybe secure websites will rank higher than unsecured ones.


Setting up a SSL Certificate to make a Secure Website

When trying to set up a free SSL certificate from Let’s Encrypt the information I found to begin with was quite confusing. Then, once I got my head around what I was doing, the sites I tried to add it to were not able to use Let’s Encrypt certificates for different reasons.

Once I finally got a VPS that could handle Let’s Encrypt certificates I followed this guide… Install Let’s Encrypt to Create SSL Certificates.

I would say that starting off it is important to pay attention to detail. Make sure everything is updated to begin with, and you have all the server requirements. Also, whereas you may not have specified the IP address in your virtual host config file before, you will need to specify the IP there for this to work.

Luckily, for a Linus administration beginner there are plenty of error logs and hints to find out what if anything has gone wrong. Not all the online guides state all the pitfalls. That’s why I am putting this information together in one place on how to make your website secure with SSL encryption…

Installing Let’s Encrypt

To begin with, make sure port 443 is open in the firewall (see troubleshooting). In these lines of code make sure to change “example.com” to your website domain.

Start off by getting and installing the Let’s Encrypt software, then use it to get the certificates. The order of the two domains in the final command are fairly important because the virtual directory containing the certificates will be named after the first domain, so you might want to use the one without www for simplicity…

sudo apt-get install git
sudo git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt

Installing Let’s Encrypt SSL Certificates

Go to the directory you have cloned to when installing Let’s Encrypt…

cd /opt/letsencrypt
sudo -H ./letsencrypt-auto certonly --apache -d example.com -d www.example.com

If there are any errors after the final command, it should tell you what the error is related to, but if it does not or it is unclear there are some ideas in the troubleshooting section.

Check the certificates by typing the following commands, below. The directory should be your domain instead of “example.com“, if it does not exist or is misspelt then you’ll have to get the certificates again as it will not work. When you get the certificates you should specify both www and non-www. Let’s Encrypt does not work for wildcards so every subdomain has to be specified. If it is a subdomain with a different config file then it will need a separate set of certificates…

sudo ls /etc/letsencrypt/live/example.com
sudo stat /etc/letsencrypt/live/example.com/fullchain.pem

Modify the VirtualHost file to look for SSL Certificates

Then, once you have the certificates. Modify the config file for the website, e.g. “/etc/apache2/sites-available/example.com.conf“. You can Keep the same file just change the port from 80 to 443 and the VirtualHost tags should contain the following. The file path to the certificates should be the actual paths to your certificates. And, I believe for this to work you must have the IP address in the VirtualHost tag, a wildcard will not work…

SSLEngine On
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem

Then, make sure SSL is enabled and restart apache…

a2enmod ssl
service apache2 restart

By this stage when you go to https://www.example.com your website should work! If that’s the case you can make sure that everyone gets the secure version of your site, below.

Redirecting to Force HTTPS Encryption

Once the SSL certificates are working properly you’ll want to make sure everyone gets the secure version of your website. There are a few different methods to do this but perhaps the simplest for people who are new to Linux is using .htaccess. How to force HTTPS using the .htaccess file

RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://www.example.com/$1 [R,L]

This will still allow https://example.com/ to work so you may choose to add another line for that.

Or, have two VirtualHost tags for ports 80 and 443 in the “/etc/apache2/sites-available/example.com.conf” file and redirect port 80 as suggested here

ServerName www.example.com
ServerAlias example.com
Redirect permanent / https://www.example.com/

Now, you’ll all done!

Checking the Expiration Date of Let’s Encrypt Certificates

Let’s Encrypt certificates last for 90 days, you do not want them to expire unless you want to stop encrypting the website. To check when your current certificates are du to expire type this into the terminal…

openssl x509 -noout -dates -in /etc/letsencrypt/live/example.com/cert.pem

Which will give you the date they were created and the date they are valid until…

notBefore=May 7 14:33:00 2017 GMT
notAfter=Aug 5 14:33:00 2017 GMT

From here there is also “ssl-cert-check” for Debian-like versions of Linux. It needs installing first if it is not already installed, so…

apt-get install ssl-cert-check

Then, run it by typing this simple code (needs superuser privileges so use “sudo”)…

ssl-cert-check -c /etc/letsencrypt/live/example.com/cert.pem

Which gives something like this…

Host                                             Status   Expires     Days
FILE:/etc/letsencrypt/live/example.com/cert.pem   Valid   Aug 5 2017   90

Renewing Let’s Encrypt SSL Certificates

To renew the Let’s Encrypt certificates, navigate to the Let’s Encrypt directory… cd /opt/letsencrypt.

Then, this is one way to renew the certificates…

sudo service apache2 stop
sudo -H ./letsencrypt-auto certonly --standalone --renew-by-default -d example.com -d www.example.com
sudo service apache2 restart

The “standalone” flag means that you would have to stop apache because Let’s Encrypt needs to be the only application using port 443.

However, by using --apache or --webroot you can do the same thing while apache is running, from here. This may reload or restart apache but apache would not be stopped for nearly as long as it would be if apache was manually stopped and then restarted again at the end…

sudo -H ./letsencrypt-auto certonly --apache --renew-by-default -d example.com -d www.example.com

To automatically renew the Let’s Encrypt certificates one a month, enter this command to make a monthly task in your crontab…

echo '@monthly root /opt/letsencrypt/letsencrypt-auto certonly --quiet --apache --renew-by-default -d example.com -d www.example.com >> /var/log/letsencrypt/letsencrypt-auto-update.log' | sudo tee --append /etc/crontab

To automatically renew the Let’s Encrypt software, enter this command…

echo '@monthly root cd /opt/letsencrypt && git pull >> /var/log/letsencrypt/letsencrypt-auto-update.log' | sudo tee --append /etc/crontab

Alternative Method for Debian 8 (Certbot)

Another way is to install the Let’s Encrypt certificates is to install Certbot on Debian 8 using Backports… How to Set Up Let’s Encrypt Certificates for Multiple Apache Virtual Hosts on Ubuntu 14.04.

sudo nano /etc/apt/sources.list

Then, enter this line if it is not already there…

deb http://ftp.debian.org/debian jessie-backports main

Save and exit nano, then…

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install python-certbot-apache -t jessie-backports

Troubleshooting and Checking

Check which sockets are open using ss (socket statistics)…

ss -tlnp

More information on ss here.

Check apache version and check which modules are installed

apache2 -v
apache2ctl -M


dpkg-query -l

For your second secure website on the same webserver you will have already enabled the SSL module and port 443 will already be serving your first website to the world. When you try to install the certificate for the second website there may be problems if you are using the --standalone flag, because Let’s Encrypt wants to use the same port as is already serving the website. To continue using --standalone you can stop Apache for a few seconds while you install the certificates.

service apache2 stop

Then, once the Let’s Encrypt certificates are done, you can restart Apache again…

service apache2 restart

To avoid having to stop and start apache like this on a production website you can use the --apache flag instead.

If you are using UFW as a firewall, the following command will show you whether socket 443 is allowed…

sudo ufw status

Also, Apache problems when trying to set up SSL (Debian).

Further Checks to make your Website Secure (Green Padlock)

If your website is working with HTTPS in the location bar (“https://www.example.com/”) but you do not have a green “SECURE” you have an “i” with a circle around it, check to see what it says by clicking on it. If it says you are not fully secure it probably means that the files and/or images you are linking to are not using the SSL encrytion. To fix this simply either fix your absolute image/file locations by changing them from HTTP to HTTPS, or just use relative linking.

Another thing that may cause errors is your .htaccess file, if you have one. Make sure that the error documents are all updated from http:// to https:// for the site in qustion.

Adding more Secure websites to the same Webserver

When “Let’s Encrypt” is already installed you do not have to re-install it, you can simply create the new certificates for the next website you want to make secure. When you are trying to create the certificates there may be an error saying that port 443 is already in use. In this case, you may have to stop apache briefly while you make the certificates, then restart apache as soon as they’re made.

Here is a guide to Setting up a Linux Webserver with SSH. This is for Debian 8 (Jessie) although other versions of Debian will be similar, and Debian-based versions of Linux, like Ubuntu will also use similar commands. I’ll just call it the webserver because it can be a dedicated server, a VPS, or a cloud instance.

A lot of this comes from these excellent guides… Getting Started with Linode and Securing your Server… but I’d say that searching around and getting different information from different sources is definitely a good way to go. I wanted to install PHP 7.0 so some of this guide is different to other guides, which tend to use PHP 5.6. This guide is also primarily for people using a Windows PC to talk to a remote Linux webserver, but other operating systems will be the same for most of the stages. Most of the contents of this guide uses a terminal and an SSH connection, which windows needs software for (e.g. Putty), but other operating systems may have it built-in. This guide doesn’t talk about FTPing (or SFTPing) much, but a good SFTP client for Windows is WinSCP.

There is often more than one way to get the same results. For example, you can reboot the system in a number of different ways. I tend to use the methods that appear simplest to me.


  • A linux server (Debian 8, in this case).
  • The IP address of the server.
  • The root password of the server.
  • A computer to access your remote linux webserver, in this case a Windows PC with Putty installed.


1) Login to the server with SSH
2) Update/upgrade
3) Install Apache2
4) Find your webserver’s IP address
5) Set a Hostname
6) Configure the Apache virtual hosts
7) Create the web directory
8) Install PHP7
9) Your webserver’s Timezone
10) Unattended upgrades
11) Install Sudo
12) Add a user
13) Public/private key pair
14) Turn off root login
15) Sending email
16) Fail2ban
17) Firewall: UFW
18) Install MySQL and PHPmyAdmin
19) Monitor
20) Apache Config file

1) Login to the server with SSH

With Windows you can download and install some software, such as Putty, then connecting to your instance should be pretty straight-forward with the login information from your hosting company. To begin with you’ll probably be logging in as “root” so you will not need to type sudo as root is the master login (this is handy because sudo is not installed, yet). The commands on this guide may need sudo adding at the beginning if you are not logging in as “root”.

2) Update/upgrade

Once you are logged in the first thing to do is to make sure everything is updated so that you are installing the latest versions of everything when you get to that stage.

apt-get update && apt-get upgrade

or, later if you login as another user, you’ll need sudo…

sudo apt-get update && sudo apt-get upgrade

3) Install Apache2

First, you can check if Apache is already installed by typing…

which apache2

If it is not already installed, i.e. the above does not give you any results. To install Apache type…

apt-get install apache2

4) Find your webserver’s IP address

If your hosting company has not told you what the IP address is, this shows all IP’s installed on your instance…

hostname -I

5) Set a Hostname

The hostname can be anything. If you have more than one instance you might name your instances so that they are all plant species, stars, geographical locations, chemical elements, Roman Emperors or Greek philosophers.

Add the hostname by opening up the hosts file in nano…

nano /etc/hosts

Then, the hosts file might look like using the IP address that you already know, above… localhost myhostnamegoeshere
123.123.456.789 example.com

6) Configure the Apache Virtual Hosts

Make sure 000-default.conf is off, copy it to mywebsite.com.conf and enable. link

cd /etc/apache2/sites-available
cp 000-default.conf example.com.conf
nano example.com.conf

Then, edit the example.com.conf so that it looks like this…

ServerAdmin webmaster@localhost
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com

Then, enable the site by typing…

a2ensite example.com

7) Create the web directory

We specified the DocumentRoot should be /var/www/example.com, above. So, now we need to make it!

Move to the place for all your web directories…

cd /var/www/

Then, create the web directory…

mkdir example.com

Once you have the directory you can add an index.html inside it.

If you have not restarted apache2 since typing the a2ensite command you need to do that before the domain name will work in your browser. Restart then test it by typingthe domain name into a browser.

8) Install PHP7

You can install any version of PHP. For Debian 8, it seems that PHP5.6 is the default, whereas with Ubuntu 16.04 LTS PHP7.0 is the default. I wanted to go with PHP7.0 so followed this guide for setting it up on Debian 8… Installing PHP7

Add these two lines to your /etc/apt/sources.list file:

deb http://packages.dotdeb.org jessie all
deb-src http://packages.dotdeb.org jessie all

Add the GPG key:

wget https://www.dotdeb.org/dotdeb.gpg
apt-key add dotdeb.gpg

Install PHP 7:

apt-get update
apt-get install php7.0

Then, straight away before you do too much else you’ll want to add the other modules you need. There is information abput some common ones from here..

apt-get install php7.0-cli php7.0-common libapache2-mod-php7.0 php7.0 php7.0-mysql php7.0-fpm php7.0-curl php7.0-gd php7.0-bz2

You can then test out the PHP by making a page that has phpinfo(); on it to show you 1) that it’s working and 2) the modules that are installed and enabled. Assuming everything works fine it’s time to do more setting up…

At this stage I normally make sure everything is installed that I’ll need for phpmyadmin. Then enable mod_rewrite

a2enmod rewrite

9) Your webserver’s Timezone

Set your server timezone by typing the following command…

dpkg-reconfigure tzdata

Then, this command shows you the current time on your server…


10) Unattended upgrades

You will want to keep everything as up-to-date as possible on your instance. You can do this by configuring the Unattended upgrades… Automatic updates. Then if you don’t want to have to login to your instance and reboot/restart it after every upgrade, you can automatically reboot, if needed, after upgrading. First install the package…

apt-get install unattended-upgrades

Then configure the settings you want in nano…

nano /etc/apt/apt.conf.d/50unattended-upgrades

11) Install sudo

From Installing sudo on Debian

apt-get install sudo

12) Add a user

adduser myname

Then, add the user to sudo…

usermod -aG sudo myname

Then logout of root, login as myname and test sudo out by doing something that requires sudo privileges, e.g. reload apache2.

13) Public/private key pair

This is the main thing that is different on Windows PCs than it is with either Linux or Macs. For Windows PCs you have to use downloadable software, such as putty. This guide: Use Public Key Authentication with SSH talks you through the process.

The most important thing to note is that you should be logged in as the user you want to make the key pair for when you make the ~/.ssh directory and put the authorized_keys file in it, the reason is that the “~/” means “/home/yourusername/”, so if you login as root when you make the directory it’ll make the file in “/home/root/” which will not work. You should also make the file owned by your username… chmod yourusername ~/.ssh -R

Before this will work you need to restart the SSH service as suggested here

sudo service ssh restart

Then, logout of root and login with your user to check that the new user works correctly with the public key authentication. You should be asked for the keyphrase, as opposed to the password.

14) Turn off root login

If you can login with the username you set up with the public/private key pair you can “turn off” root logins.

Turn off root logins and turn off password authentication in the sshd_config file using nano…

nano /etc/ssh/sshd_config

15) Sending email

https://www.debian.org/releases/jessie/amd64/ch08s05.html.en allows server to send email, e.g. for unattended upgrades reboot.

16) Fail2ban


apt-get install fail2ban

Then, you can endit the config file, and/or make a local file…

nano /etc/fail2ban/fail2ban.conf

17) Firewall

For a firewall, UFW (Uncomplicated Firewall) is there for Debian systems. This is a good guide: Configure firewall with UFW

apt-get install ufw

As the guide says, you’ll have to be very careful when switching on the firewall that you do not lock yourself out of SSH.

18) Install MySQL and PHPmyAdmin

Here are two useful guides: MySQL and MySQL on PHP7.

apt-get install mysql-server


apt-get install libapache2-mod-php7.0 php7.0-mysql php7.0-curl php7.0-json

A good place to begin before installing PHPmyAdmin is by checking the phpmyadmin prerequisites and installing everything needed (e.g. mbstring). If 500 server errors, check the prerequisites again, installing anything that isn’t already installed, then re-install phpmyadmin to get rid of the error.

Install PHPmyAdmin on Debian 8

For each virtual host that you would like to give access to your PHPMyAdmin installation, create a symbolic link from the document root to the phpMyAdmin installation location (/usr/share/phpmyadmin). You do this by moving into the public directory of each virtual host, then creating a symlink…

cd /var/www/example.com/public_html
sudo ln -s /usr/share/phpmyadmin

19) Monitor

You can monitor the performance and usage of the web server by using top… Just type top into the terminal and you’ll get a summary of the usage every few seconds.

Linux TOP command explained

You can also set up a script that will email you if certain conditions are met (RAM usage, for example).

20) Apache Config file

It’s a good thing to take a look at the apache2 config file to make sure it is configured correctly. One of the things you’ll want to check is that KeepAlive is set to off. From Setting up LAMP on Debian 8.

sudo nano /etc/apache2/apache2.conf
KeepAlive Off

TL;DR / Conclusion

Different setups are all slightly different. If you are getting errors the best thing to do is to either examine the error itself or find the relevant error logs and do some problem solving. Unix & Linux Stack Exchange and Server Fault tend to have a lot of problems already answered.

This is just a general guide to setting up a Linux Webserver with SSH with a Windows PC talking to a Debian 8 remote webserver. You may want to change the order I have followed here and there may well be steps I’ve missed out here, errors I get that you do not get, or vice versa. But, I hope it can be useful to someone.

After getting this far there will probably still be thing you need to do to your webserver. There will be other PHP and Apache modules that your web applications and/or frameworks require, such as mod_rewrite… As before, figure out what you need for your application and add it as required. Have fun!

There are 1,000s of WordPress Plugins and each one is individual, but for anyone wanting to make a plugin for themselves here are a few basics to help you get stated. I made my first plugin recently for WordPress and I was amazed at how little information was out there. So, I decided to make this simple tutorial on “How to write a WordPress Plugin” for anyone else with an interest in web programming or web design who would like to see if they can make a plugin. Obviously, the plugin itself will be whatever you want it to be and will be as complex as you want to make it. This tutorial will be an easy introduction that you can add to if you wish.


While it can be very straight-forward there are two things you’ll definitely need to begin working on a WordPress plugin.

  • A working version of WordPress wether on a website or on a localhost.
  • Knowledge of PHP.

You are going to need a working version of WordPress. I won’t go into the details here of how to setup and install a WordPress blog but if you are interested in making a WordPress plugin I’m assuming that you’ve had some experience with using WordPress.

WordPress has many existing functions that will assist you in making your plugin but the programming language that you’ll need to use to make a WordPress plugin is PHP. There’s no getting around the fact that you should probably have some PHP knowledge to make a plugin that behaves exactly the way you’d like it to behave and has all the functionality you want it to have. I’d say that you may not have to be a PHP whizz and you can learn-as-you-go, but you’d need to have an understanding of programming languages, and an idea of how to write PHP.

A good source of information about PHP is PHP.net, often searching for a PHP function will take you there. Another good place for PHP examples and troubleshooting is Stack Overflow, again searching for a problem you are having will often take you here where someone has generally already asked the question and it has already been answered.

Why WordPress? Why a plugin?

WordPress rocks. There are many many people using WordPress all over the world, and WordPress.com is in the world’s top 50 websites. The basic blogging software is amazing and constantly evolving, but the power of WordPress is in it’s open source. Because the source code can be viewed by anyone and there is extensive online documentation many people have made plugins and themes which aid and enhance WordPress blogs. Through plugins you can modify almost any aspect of the blog, adding things, removing things and changing it until it is almost unrecognisable from the original blog you added to your hosting.

You’ll want to use plugins that other people have made, but maybe the plugin that would be perfect for you has not been made yet. If this is the case or you just want to give it a try, read on…

Making a WordPress Plugin: First Things First

Ok then, let’s begin! We’ll start off with a one page plugin. The first thing you have to do is open up a text editor and create a file called whatever you’d like your plugin to be called. There are 1000’s of plugins already so my advice would be to call it something with at least 2 or 3 words in the name if you wish to submit to the WordPress Repository. WordPress needs each plugin to have a unique filename so that there are no conflicts between different plugins. This concept extends to the naming of functions which should all begin with a unique prefix so as not to cause any conflicts with WordPress functions or functions of other plugins. If you are not interested in submitting your plugin you can call it pretty much whatever you like as it’ll only be on your website.

So, let’s call our plugin “My First Ever Plugin” and give it the filename “my-first-ever-plugin.php” and let’s start off with this code in our PHP file, I’ll call this the “header” code…

 * @package my-first-ever-plugin
 * @version 0.0.01
 * Plugin Name: My First Ever Plugin
 * Plugin URI: http://www.shortdark.net/my-first-ever-plugin/
 * Description: My plugin does...
 * Author: My Name
 * Text Domain: my-first-ever-plugin
 * Version: 0.0.01
 * Author URI: http://www.shortdark.net/

It should be fairly self-explanatory. This plugin will have the file "my-first-ever-plugin.php" in a directory called "my-first-ever-plugin". If your plugin was called "Whatever" it would have a file called "whatever.php" inside a directory called "whatever". The description is a short description of what the plugin does.

Prevent Direct Access

Next, still on the "my-first-ever-plugin.php" file, it's good practice to prevent direct access to your plugin. I.e. we want the plugin to be used by someone within their WordPress blog, we do not want the plugin to be accessed from elsewhere. To prevent direct access we insert this code after the header...


defined('ABSPATH') or die('No script kiddies please!');

So, if "ABSPATH" is not defined the PHP script will die().

Believe it or not, we're almost done if you're just making a WordPress plugin for your own use. I'll cover the steps you need to take if you want to add your plugin to the WordPress repository later. All that has to be done now is to hook some code to WordPress.

Hook It Up

WordPress uses "hooks" to connect functions you have written to a WordPress blog. A hook can be either an "action" or a "filter". An action adds something and a filter changes something that already exists. We will use a filter for this tutorial but an example of an action would be to make a page in the admin area we would use the "add_action" like this... "add_action('admin_menu', 'function_name');". For more information check out the WordPress Plugin API reference.

Here we are filtering the content of all the posts and pages. We are going to add some "Hello World!" text in <p> tags at the end of the post and page content. We make a function that has the parameter "$content" then we hook the function using the filter "the_content" whoch means that whatever we return from the function will replace the post or page content. As we do not want to remove the content we just want to add to it I have just added the string we want onto the end of the "$content" variable.

This goes next in the "my-first-ever-plugin.php" file...

// Add "<p>Hello World!</p>" to the end of each post and page
function mfep_hello_world($content) {
	$content .= "<p>Hello World!</p>";
	return $content;

// Hook the function to "the_content"...
add_filter('the_content', 'mfep_hello_world');

Notice, I have named my function beginning with an acronym of my plugin. My plugin is called "My First Ever Plugin" so I put "mfep_" at the start of all my function names.

And, that's it. You've made a plugin!

Make your WordPress Plugin Translatable

To make your plugin translatable you'll need to load your text domain. In the "header" we had a line like this...

 * Text Domain: my-first-ever-plugin

So, now we need to use another hook, which this time is an "add_action" to tell WordPress where you'll be storing the translation files. Here, I'm storing the translation files in a directory within my plugin called "languages".


function mfep_load_textdomain() {
	load_plugin_textdomain('my-first-ever-plugin', false, dirname(plugin_basename(__FILE__)) . '/languages');

add_action('init', 'mfep_load_textdomain');

Again, you'll notice that my function has the acronym of my plugin name, "mfep_", at the beginning.

That's all we have to do in the "my-first-ever-plugin.php" file.


If you want to submit your plugin to the WordPress repository you'll also need a "readme.txt" file in your plugin directory.

Similar to the header of the PHP file, the readme.txt also has a header...

=== My First Ever Plugin ===
Contributors: shortdark
Donate link: http://www.shortdark.net/my-first-ever-plugin/
Tags: posts, pages
Requires at least: 3.5
Tested up to: 4.6.1
Stable tag: trunk
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html

Adds a Hello World! to the end of the post and page content.

The plugin title is on the top line in between two sets of "===".
Contributors is hwo has helped to make the plugin.
Tags should be exactly the same as the ones that WordPress has already. You can see the existing tags here.
Requires at least is the minimum WordPress version number your plugin should work for. Our plugin here is very simple but if you used a WordPress function that was created fairly recently you should investigate which version of WordPress it was introduced in. This will allow you to calculate the minimum version without installing every single version of WordPress ever.
Tested up to should be the version of WordPress you have tested your plugin on. This should always be the latest version of WordPress because you should always update to the latest version every time an update comes out.
Stable tag is telling WordPress which is the stable version of your plugin. To begin with this will be the "trunk".
Then, your plugin must be open source and it must have a public licence,
Lastly, before the next section of the "readme.txt" you can add one sentence to describe your plugin. This will be what will show up on the plugin page of the user's blog after they download your plugin.

The rest of readme.txt

After the one sentence short description you can add a much longer description that can be as long as you like with several paragraphs. Links can be added as shown with the link text in square brackets before the URL in brackets. Then comes the necessary "Installation" and "Changelog" sections. You'll notice that all the sub headings are in the middle of a set of "==" and the subheadings have "=" around them.

== Description ==

Much longer description goes here.

Please let me know if you like this plugin by leaving a review or [contacting me](http://www.shortdark.net/contact-me/).

Go to the [Shortdark WordPress plugin page](http://www.shortdark.net/wordpress-plugin/) for more information.

== Installation ==

This section describes how to install the plugin and get it working.

1. Upload the plugin folder to the `/wp-content/plugins/` directory, or install the plugin through the WordPress 
plugins screen directly.
2. Activate the plugin through the 'Plugins' screen in WordPress.

== Changelog ==

= 0.0.01 =

* New plugin.

And that's it!

Once you've finished your readme.txt you can check your readme.txt at the readme.txt validator.

Now your're ready to review the Plugin Directory information zip your plugin up and submit it to the WordPress Repository.

Once your Plugin has been Approved

WordPress uses SVN, so you'll probably need something like TortoiseSVN to upload your plugin to the WordPress repository. More info on how to do that at this youtube video.

Here are some extra things that I didn't find out immediately that might be helpful to you.

Add images to your WordPress Plugin Page

You should have two images: "banner-772x250.jpg" and "icon-128x128.jpg". They can be in your plugin folder (the "trunk" of your WordPress repository), or it may be better to put them in your "assets" folder out of the way. These will be the banner image at the top of your plugin page and the square icon that people will see when they search for a plugin.

Add Screenshots

To add a screenshots section you simply add "== Screenshots ==" to your readme.txt.

== Screenshots ==

Here are some screenshots...

1. Nice screenshot of my plugin.
2. Another screenshot of my plugin.

Each number in this section will be a different screenshot. Screenshot 1 will look for the file "screenshot-1.jpg", and screenshot 2 will look for "screenshot-2.jpg". Similar to the banner and icon, you'll either put these images in your trunk or in your assets folder. The text by each number on the readme.txt is the caption that will go under the image on the screenshot page.

Everything All Together

The complete files from this "How to write a WordPress Plugin" tutorial can be cloned or downloaded from GitHub page.