Design Patterns in PHP - Responsibility chaining

in #utopian-io7 years ago (edited)

What Will I Learn?

In this tutorial you will learn about the chaining pattern in php. You will also learn

  • The importance design patterns pattern
  • Popular projects that implement this pattern
  • An example implementation.

Requirements

To follow along in this tutorial, you should

  • have php installed on your machine
  • have a good understanding of classes (and objects) in php

Difficulty

  • Intermediate

Tutorial Contents

It is generally recommended to always write codes with a design pattern. It brings clarity and structure to your codes. It also makes it very easy to explain to someone who is working with or inspecting the code base.

Chances are that you already use some of these patterns, but don't know the name given to it. You might also not know some generally accepted practices using that pattern. In this tutorial, we'll be looking at the Chaining pattern, as used in php. What you'll learn from this tutorial will be influenced by my 5years+ experience with programming.

The way i like to look at chaining is, it makes me write code like i'm describing a thing. For instance, lets say i need to write an algorithm to exit my house everyday, i'll

  • check the lights
  • close the windows
  • lock the door
  • exit the house.

So i'll write a class and compose the above steps into methods like this;

class MyHouse {
     
    public function checkLights(){
        return $this;
    }

    public function closeWindows(){
        return $this;
    }

    public function lockDoors(){
        return $this;
    }

    public function exit(){
        echo "You have exited your house";
    }

}

Then to use the class,

<?php

class Controller {

    public function index(){

        $house = new MyHouse;

        $house->checkLights()->closeWindows()->lockDoors()->exit();

    }
}

The above example is very trivial, but it presents the basic idea.

As we can already notice, the main thing that makes chaining possible is, any method you want to be chained against must return an instance of an object; hence return $this;

Let's make a more realistic example.

Let us create a class for an SMS service so that we can easily send SMS' to our customers. We'll call it UtopianSMS.

UtopianSMS will need the following configurations;

  • API key
  • Email Address
  • Sender Name

As parameters, we will be needing

  • Recipients
  • Message
  • Sender Name (optional)

Step1

  • Create and initialize the UtopianSMS class
<?php

namespace therealsmat;

class UtopianSMS {

    /**
     * Stores the sms client key
     *
     * @var
     */
    private $apiKey;

    /**
     * Stores the account email address
     *
     * @var
     */
    private $email;

    /**
     * Stores the sender name
     *
     * @var
     */
    protected $senderName;


    /**
     * Mutator for ApiKey
     *
     * @param $key
     * @return mixed
     */
    public function setApiKey($key)
    {
        return $this->apiKey = $key;
    }

    /**
     * Mutator for account email
     *
     * @param $email
     * @return mixed
     */
    public function setEmail($email)
    {
        return $this->email = $email;
    }

    /**
     * Mutator for sender name
     *
     * @param $name
     * @return mixed
     */
    public function setSender($name)
    {
        return $this->senderName = trim($name);
    }
}

Step 2

  • Create the methods we need to send mails
/**
     * Mutator for sender name
     *
     * @param $name
     * @return mixed
     */
    public function setSender($name)
    {
        return $this->senderName = trim($name);
    }

    /**
     * Set the message to be sent
     *
     * @param $message
     * @return UtopianSMS
     */
    public function message($message)
    {
        $this->message = trim($message);
        return $this;
    }

    /**
     * Add recipients
     *
     * @param $recipients
     * @return $this
     */
    public function to($recipients)
    {
        if (is_array($recipients)) {
            $this->receipents = $recipients;
        } else {
            $this->receipents = explode(',', $recipients);
        }

        return $this;
    }

    public function send()
    {
        #. Add your protocol for sending the sms
        #.. Most likely, perform an http request...
    }

Step 3
Lets consume our class.

  • Create a controller
class Controller {

    public function index()
    {
        $utopian = new UtopianSMS();

        $apiKey = 'dhjfhj';
        $senderName = 'therealsmat';
        $email = '[email protected]';

        $utopian->setApiKey($apiKey)
                ->setSender($senderName)
                ->setEmail($email);

        $recipients = ['09098765431'];

        $utopian->message('Hello there, thanks for signing up!')
                ->to($recipients)
                ->send();
    }
}

Now we have successfully implemented chaining. I hope this helps you.

Full Codes

<?php

namespace therealsmat;

class UtopianSMS {

    /**
     * Stores the sms client key
     *
     * @var
     */
    private $apiKey;

    /**
     * Stores the account email address
     *
     * @var
     */
    private $email;

    /**
     * Stores the sender name
     *
     * @var
     */
    protected $senderName;

    /**
     * Stores the message to be sent
     *
     * @var
     */
    private $message;

    /**
     * SMS Recipients
     *
     * @var array
     */
    private $receipents = [];


    /**
     * Mutator for ApiKey
     *
     * @param $key
     * @return mixed
     */
    public function setApiKey($key)
    {
        return $this->apiKey = $key;
    }

    /**
     * Mutator for account email
     *
     * @param $email
     * @return mixed
     */
    public function setEmail($email)
    {
        return $this->email = $email;
    }

    /**
     * Mutator for sender name
     *
     * @param $name
     * @return mixed
     */
    public function setSender($name)
    {
        return $this->senderName = trim($name);
    }

    /**
     * Set the message to be sent
     *
     * @param $message
     * @return UtopianSMS
     */
    public function message($message)
    {
        $this->message = trim($message);
        return $this;
    }

    /**
     * Add recipients
     *
     * @param $recipients
     * @return $this
     */
    public function to($recipients)
    {
        if (is_array($recipients)) {
            $this->receipents = $recipients;
        } else {
            $this->receipents = explode(',', $recipients);
        }

        return $this;
    }

    public function send()
    {
        #. Add your protocol for sending the sms
        #.. Most likely, perform an http request...
    }
}

class Controller {

    public function index()
    {
        $utopian = new UtopianSMS();

        $apiKey = 'dhjfhj';
        $senderName = 'therealsmat';
        $email = '[email protected]';

        $utopian->setApiKey($apiKey)
                ->setSender($senderName)
                ->setEmail($email);

        $recipients = ['09098765431'];

        $utopian->message('Hello there, thanks for signing up!')
                ->to($recipients)
                ->send();
    }
}

Take a look at my project https://github.com/therealSMAT/laravel-ebulksms. Chaining was used almost throughout the project.



Posted on Utopian.io - Rewarding Open Source Contributors

Sort:  

Thank you for the contribution. It has been approved.

You can contact us on Discord.
[utopian-moderator]

Hey @therealsmat I am @utopian-io. I have just upvoted you!

Achievements

  • You have less than 500 followers. Just gave you a gift to help you succeed!
  • Seems like you contribute quite often. AMAZING!

Suggestions

  • Contribute more often to get higher and higher rewards. I wish to see you often!
  • Work on your followers to increase the votes/rewards. I follow what humans do and my vote is mainly based on that. Good luck!

Get Noticed!

  • Did you know project owners can manually vote with their own voting power or by voting power delegated to their projects? Ask the project owner to review your contributions!

Community-Driven Witness!

I am the first and only Steem Community-Driven Witness. Participate on Discord. Lets GROW TOGETHER!

mooncryption-utopian-witness-gif

Up-vote this comment to grow my power and help Open Source contributions like this one. Want to chat? Join me on Discord https://discord.gg/Pc8HG9x

Coin Marketplace

STEEM 0.28
TRX 0.21
JST 0.039
BTC 97529.61
ETH 3705.71
SBD 3.90