Blog

Solid Design Principles in PHP

Design Principles was introduced over a decade ago by Robert C Martin (Uncle Bob) and is used across the object-oriented design spectrum.

Why use these principles I hear you ask? When applied properly it makes your code more extendable, logical and easier to read.

I’m going to try and keep this as jargon-free as possible so it’s easy for beginners to understand. Let’s go through each principle one by one:

S: Single Responsibility Principle

Each class should have one responsibility and one responsibility only. This means that all the methods and properties should all work towards the same goal.

Let’s take the following simple class as an example of how this principle may be violated:

class Customer
{
    public $name;
    public $age;

    public function __contsruct($name, $age)
    {
        $this->name = $name;
        $this->age = $age;
    }

    public function getCustomerDetails()
    {
        return "Name: ".$this->name." Age: ".$this->age;
    }
}

This may be fine for printing information to the frontend but what about if you need to get that information in JSON or as an array? You use classes or interfaces with defined roles, thus separating the business logic from the presentation layer:

interface CustomerInterface
{
    function getCustomerDetails();
}

We then may have an interface for retail customers that must return the data as a string.

class RetailCustomer implements CustomerInterface
{
    public function getCustomerDetails()
    {
        return "Name: ".$this->name." Age: ".$this->age;
    }
}

We may have the trade interface to return this data as an array:

class TradeCustomer implements CustomerInterface
{
    public function getCustomerDetails()
    {
        return array( "name" => $this->name, "age" => $this->age);
    }
}

O: Open-closed Principle

In a nutshell, your classes should be extendable without actually changing the contents of the class you’re extending.

Here’s a very basic example of how this principle can be violated if we had to introduce another customer type:

class PointsCalculator
{
    public function getPointsSpent($customerType, $points)
    {
        switch ($customerType)
        {
            case 'retail':
            return $points * 0.5;
            break;

            case 'trade':
            return $points * 0.75;
            break;
        }
    }
}

The way around this would be to use interfaces as in the previous principle:

interface CustomerInterface
{
    function getPointsSpent();
}

class RetailCustomer implements CustomerInterface
{
    public function getPointsSpent()
    {
        return $this->type * 0.5;
    }
}

class TradeCustomer implements CustomerInterface
{
    public function getPointsSpent()
    {
        return $this->type * 1;
    }
}

class PointsCalculator
{
    public function getPointsSpent($customerTypes)
    {
        $amount = 0;

        foreach ($customerTypes as $type)
        {
            $amount += $type->getPointsSpent();
        }

        return $amount;
    }
}

L: Liskov Substitution Principle

This principle basically specifies that child classes should be suitable for their parent classes. This means it will adhere to the principles and functionality of the class it extends

class Instrument
{
    public function play() {..}
    public function changeKey() {..}
    public function autoTune() {..}
    public function plugIn() {..}
}

The instrument class may behave as an abstract and could be implemented in the following ways:

class Guitar extends Instrument
{
    public function play() {
        $this->plugIn();
        $this->strum();
        parent::play();
    }

    public function strum() {..}
}

class Trumpet extends Instrument
{
    public function play() {
        $this->blow();
        parent::play();
    }

    public function blow() {..}
}

I: Interface Segregation Principle

This principle is probably the simplest in terms of theory.

A client should not be forced to use interfaces that it doesn’t need.

Here’s an example of violation of this principle:

interface InstrumentInterface {
    public function play();
    public function changeKey();
    public function autoTune();
    public function plugIn();
}

class Guitar implements InstrumentInterface {
    public function play() {..}
    public function changeKey() {..}
    public function autoTune() {..}
    public function plugIn() {..}
}

class Trumpet implements InstrumentInterface {
    public function play() {..}
    public function changeKey() {..}
    public function autoTune() { /* Exception */ }
    public function plugIn() { /* Exception */ }
}

The Trumpet class has autoTune()plugIn() forced upon it – I’m not saying that there are no plugin-in trumpets out there but in this case I’m talking about a standard acoustic trumpet. An ISP-safe method is to create an interface for each of the instruments that employs only the methods needed for the client:

interface InstrumentInterface
{
    public function play();
    public function changeKey();
}

interface GuitarInterface
{
    public function autoTune();
    public function plugIn();
}

class Guitar implements InstrumentInterface, GuitarInterface
{
    public function play() {..}
    public function changeKey() {..}
    public function autoTune() {..}
    public function plugIn() {..}
}

class Trumpet implements InstrumentInterface {
    public function play() {..}
    public function changeKey() {..}
}

D: Dependency Inversion Principle

This principle states that high-level modules should not depend on low-level modules. High-level modules should never change and should be decoupled (separated) from low-level modules that could be changed on a daily basis.

The introduction of dependency injection in Magento 2 has made this principle easier to adhere to, as it is now clear which classes and clients are dependent on each other. Please check my last post Diving into Magento2 Dependency Injection for detailed information.

Take the example below which shows a rather limited example of higher level code being dependent on the lower level code:

class CountApples
{
    private $apple;
    public function __contsruct($apple)
    {
        $this->apple = $apple;
    }

    public function howMany()
    {
        return count($this->apple->howMany());
    }
}

This does the job, but the class is completely dependent on us always counting apples. There are other fruits out there kids! We should make our counting class more general:

class CountFruit
{
    private $fruit;
    public function __contsruct($fruit)
    {
        $this->fruit = $fruit;
    }

    public function howMany()
    {
        return count($this->fruit->howMany());
    }
}

/** Create our generic fruit interface **/

interface Fruit
{
    public function howMany();
}

/** Create our clients **/

class Apples implements Fruit
{
    public function howMany()
    {
        return 14;
    }
}

class Bananas implements Fruit
{
    public function howMany()
    {
        return 6;
    }
}

The end result is code that is less dependent on the lower level code with which it is working. You could take this much further than the example above but the theory is the same.

I hope I have kept this simple enough for beginner OOPHP developers to understand. Thanks for reading.

Laravel Performance Tips

Laravel performance has proven it that it can be used to build the application from a small scale to large. Laravel has been evolving consistently since its launch in 2011 and now it is considered one of the best PHP framework.

Laravel provides tools and libraries to automate common web application development tasks including database operations, authentication, file system, routing, testing, templating and cache.

Research has proven, a large percentage of online users leave the website if it take more than 3 seconds to load. Google and other search engines consider loading speed of a website as a ranking signal. Therefore, Laravel developer has to build web applications which load lightning fast.

Laravel framework provides an architecture that makes it easy to write clean, well-structured and tested code. However, to build large-scale web applications, Laravel developer should know how to utilize the power of this framework and enhance performance.

As Laravel is considered one of the best php framework to work with, today I will share 13 tips and show you how I optimize Laravel application and imporove laravel performance.

Laravel Performance Tips

13 Tips to Boost Laravel Performance

 

1. Using Artisan Commands Efficiently

Laravel Artisan comes with a set of optimization commands which we can use to optimize the Laravel performance. These commands enable Laravel developer to make Laravel application load faster by improving the optimization of files, creating cache files and compiling commonly used classes into a single file.

Laravel developer can improve the Laravel performance by running below command. For more elaboration, I will discuss every command separately.

Config Caching

There are so many configuration files in Laravel and requesting every single configuration file is a tedious job. You can use config:cache to cache and combine all configuration into one file

php artisan config:cache

Don’t forget to re-run this command if you have made any changes to configuration files as your latest changes won’t reflect in the cache. Just to refresh your cache run above command and if you would like to clear all config cache you can run below command.

php artisan config:clear

Config caching can improve Laravel performance significantly as configuration data will be served from the cache which is just an array instead of from the object.

Routes Caching

Laravel performance can be affected by routing if your application is very big and you have a very large list of routes. To cache the routes.php the file just run below command.

This command will not work if you are using closures in your routes.php file. You have to move all closures logic to controllers if you want to cache your routes.

php artisan route:cache

Same as Config Cache, you have to re run the command if you have make any changes to routes.php file. To clear all routes cache use below command.

php artisan route:clear

Views Caching

Laravel compiles all views of your application first time they are rendered. You can find all compiled views in storage/framework/views folder.

To clear all compiled views use below command.

php artisan view:clear

This command is very handy while building Laravel application, in case if you don’t see your changes, this is the command to rescue you.

2. Reduce Packages Usage

There is a number of Laravel packages available on GitHub and other code hosting services. Laravel packages add additional functionality to your application. Less the packages you use in your application better it will perform.

Laravel packages loads through Composer Dependency Injection which loads all packages defined in composer.json file. One thing to note here is, you don’t just include a package into your application if that package is depending on any other packages it will install that packages as well.

Laravel performance can decline significantly due to this reason. So less packages = better performance.

3. Use Eager Loading

Laravel use Eloquent ORM to map your objects to database which is one of the best feature of Laravel. You can map a database table to a PHP class by creating a Modle which will extend the Model class of Eloquent. Laravel Eloquent use lazy loading approach which you perform any operation on a model.

For example, if you want to retrieve category of a product, Eloquent won’t actually retrieve the data until it is specifically referenced somewhere else in the application.

It seems OK to have two extra queries to load details of a product, but if your application is growing and it interacts with the database a lot, it will reduce the Laravel performance as you will wait for all of your product details to return.

$products = App\Product::all();
    foreach ($products as $product)
    {
        echo $product->category->name;
    }

Instead of lazy loading, you should set up your queries to use Eager Loading. Eager Loading will retrieve any associated object model as part of your first query and will be available immediately for use. Above code example will change below after adopting Eager Loading technique.

$products = App\Product::with('category')->get();
    foreach ($products as $product)
    {
        echo $product->category->name;
    }

Laravel developer can easily speed up the Laravel application by adopting Eager Loading approach instead of lazy loading approach.

4. Leverage Cache

Laravel developer can utilize the various caching systems. Developers can improve performance significantly by using robust caching tools like Redis and Memcache. You can cache config and routes using commands discussed above into these cache systems.

There are a number of ways to implement cache systems, I strongly recommend that you should use a cache system to store all your cache which will improve the performance.

5. Remove Unused Services

Laravel provide a convenient way to inject services into application using service container. You can use any service by adding into the providers array in config/app.php file.

Make sure you don’t include any service which you are not using. Laravel loads all services added to this array on the application bootstrapping. You can comment out any service which you don’t use.

6. Optimize the Composer Autoloader

Optimizing composer autoload is not only for Laravel developer but for a PHP developer, in general, is very important. Composer is used to load packages or libraries into framework. Composer loads all classes by using PSR-4 coding standard, which means when we ask the composer to load App\Mail\ContactForm composer will look into the class map and load the class.

The class map is an array of 1-to-1 associations of classes and files. Because App is a PSR-4 namespace, which comes by default with Laravel and it’s associated to the app/ folder, composer will try converting the PSR-4 class name to a filename with basic string manipulation procedures.

In the end, it guesses that App\Mail\ContactForm must be located in a ContactForm.php file, which is in a Controllers/ folder that should luckily be in the namespace folder, which is app/.

You can run below command to scan your entire application and create direct 1-to-1 associations of classes and files.

composer dumpautoload -o

7. Optimize Response Data

Laravel developer can achieve better performance by compressing response data. As most of the data come from the database using Eloquent which is already optimized, but any additional data will impact the application’s loading speed and bandwidth consumption.

Laravel developers can leverage view models, to compress response data. The view models create multiple subsets of the data model and send data elements to the client gradually. The developers can even use libraries like Fractal to accelerate response data compression and object model data conversion.

8. Pre Compile Assets

Laravel developers often store websites assets like CSS and javascript in multiple files, so they can access them quickly and change them. By having so many files your application will be dealing with more assets request which will make your page loading slow.

Laravel developers can easily speed this up by combining or concatenating files into one file. Luckily Laravel Mix provides nice commands to compile all assets using the command line. By using Laravel Mix commands you can minify your assets and concatenate them very easily.

9. Profile Database Queries

Another way of improving performance is by optimizing your database queries. For this, you need to have a look which queries are making most requests to the database. There is no such feature built-in Laravel.

For profiling we can use Laravel Debuger which integrate generic PHP debug bar package. Once installed into your application you will have a nice toolbar on the bottom of each rendered views. This toolbar will show you SQL queries that are used by the given page and amount of memory they are consuming.

This is a really good package which enables you to have an in-depth look at your memory consumption.

10. Leverage JIT Compiler

PHP is a server-side language and computer machine do not understand PHP code natively. Developers use compilers to interpret the PHP code and compile the code into bytecode. The code compilation process affects Laravel application’s performance and user experience. Laravel developer can use Zend Engine which comes with just-in-time (JIT) compiler and compile PHP code quickly and once.

11. Minify Blade Views

Laravel compile all blade views but doesn’t minify them. You should always minify all your blade views when pushing your site to production mode. Minifying views can slow down your initial response time but with the help of cache it will make smaller response.

I recommend to use Laravel HTMLMin package to minify all your blade views. This package is a simple minifier which minify entire response but can also minify blade at compile time.

12. Compress Images

If you have images on your Laravel application then you should compress all images and optimize them if they haven’t yet. Image optimization can be done in a number of ways. For different image types, you will need to use different tools to keep the quality and resolution of images intact.

If you are using Laravel Mix, you can use an NPM package like ImageMin to compress your images when compiling your assets. If you have a very large image, I recommend you to try TinyPNG to compress image first and then use ImageMin to compress image as much as possible.

13. Use Dedicated or Cloud Server for Laravel Performance

Hosting your Laravel application on a shared server will make your application dead slow, because shared hosting use the shared resources with other users so you don’t get the speed required by your application. Shared hosting environment also doesn’t give you freedom of using command line.

Dedicated managed servers like Forge can make it possible to easy boot up a server which is optimized for performance. Providers like Digital Ocean or Linode can bootup a server in a couple of minute which includes creating a virtual machine, writing configuration etc and you will can immediately start with SSH or Git.

With Forge you can manage your databases and other operations from a nice user interface. Either its Forge or Digital Ocean or Linode all provide you dedicated resources which can make your Laravel application blasting fast.

Any Laravel developer must evaluate and improve the performance of Laravel application throughout the application development lifecycle. By optimizing performance you can provide better user experience to users and make your application search engines friendly. You can easily improve the speed and performance of Laravel application by implementing these simple steps. However, the developers must keep in mind specific project requirements while implementing these performance optimization techniques.