Saturday, 15 October 2016

PHP Factory pattern

What is a Factory?

A factory is in essence a function that returns an instance of an object of the desired type when the class type that you want is unknown. For instance, let's say you have a Staff class with Teacher and Janitor sub-classes. When you fetch the list of all user's from the database and you want to loop through them and create the correct object type for each user without having to write an if-block each time you want to do this. This is where a Factory comes in.

A simple Factory

Again, assuming we have a Staff class with Teacher and Janitor sub-classes:

class Staff {
  public $staffType = 'Staff';
}

class Teacher extends Staff {
  public $staffType = 'Teacher';
}

class Janitor extends Staff {
  public $staffType = 'Janitor';
}
We now want to create a new staff-member object without writing an if block each time, let's build a Factory.
class StaffFactory {

  public static function buildStaffMemberObject (string $type) {
    if ($type === 'teacher') {
      return new Teacher();
    } elseif ($type === 'janitor') {
      return new Janitor();
    } else {
      return new Staff();
    }
  }

}
When we want to create an instance of a new staff-member object we can use:
$teacher = StaffFactory::buildStaffMemberObject('teacher');
$janitor = StaffFactory::buildStaffMemberObject('janitor');
That's it, you have a working Factory that builds objects of the correct type for you.

A more complex Factory

The above example works, but it's lacking in flexibility. Every time you want to add a new type you are going to have to add another condition inside the if/else if block. What if we had a Factory that could dynamically figure out which class type to load, let's take a look:
class StaffFactory {

  public static function buildStaffMemberObject (string $type) {
    $className = ucfirst($type);
    $className = class_exists($className) ? $className : 'Staff';
    return new $className();
  }

}
This time we are checking whether a class by the given name exists in the current namespace, otherwise we default back to 'Staff'. This way when you create a new staff member type, for example, "Management", all you have to do is create and include the class in you script and you can immediately create it via your Factory.

Monday, 10 October 2016

Creating an executable bash script

What is a bash script?

A bash script is an executable script that can be run from the command-line. It can then, in turn perform any other command-line commands. This way you can group commands and add logic around their order of execution, or pass variables to them and act upon those or pass them along to other scripts.

Creating a bash script:

To create a bash script you need to create a file with the extension ".sh".
$ nano script.sh
Now we need to add some functionality to our script, let's keep it simple at first:
clear
pwd
Our command is not quite ready to be run yet, now we need to give the file 'execute' permission, we can do this by running the command:
$ chmod +x script.sh
When we run this command the screen will be cleared and the current working directory will be printed on the screen.
$ ./script.sh
That's it, your bash script is created and you are now able to use it.

Accessing variables

In your script you can access variables passed to it and make decisions based on those variables or pass them along to other scripts. Variables are passed as number in the order that they appear in the given command. Let's build a script that check's out a certain branch in git.
branch=$1
git checkout $branch
Let's execute our command and see that the branch is checked-out:
$ ./script.sh master
Master will now be the checked out branch if we are in a git repository.

Making it more accessible

Creating scripts can be really cool and can help you in automating processes easily, but typing out ./script.sh option option ... can become quite tedious, so let's take a lesson from the bash aliases tutorial and add an alias for our script.
alias sc='~/script.sh'
And now you can execute your script easily by running:
$ sc master

Thursday, 6 October 2016

Bash aliases

What is an alias?

An alias is a bash command that runs one, or many other commands. An alias can also be created as a function and passed parameters.

How to add a new alias:

To create a new alias we want to add it in the correct bash startup file. In some instances (like the Ubuntu 16.04 LTS I am currently running) the default ~/.bashrc file already points us in the right place, it includes a ~/.bash_aliases file if one is present. This is a convenient way to seperate our aliases from the already full ~/.bashrc.

The alias:

Open the ~/.bash_aliases file with your editor of choice
--in terminal
$ nano ~/.bash_aliases

Create a new alias:
--in file ~/.bash_aliases
alias sftw='cd Software';

Close and re-open your terminal window or load the aliases with:
--in terminal
$ . ~/.bash_aliases

Now run the alias from the command line to see it in action:
--in terminal
$ sftw

You can also chain commands as you can in a normal terminal command by adding two ampersands (&&) in-between them:
--in file ~/.bash_aliases
alias startWeb1='cd Software/website1 && npm start'

If ~/.bash_aliases doesn't load

If your ~/.bashrc file does not contain a reference to the ~/.bash_aliases file you can add the reference like so:
--in terminal
$ nano ~/.bashrc

And add the following lines to the end:
--in file ~/.bashrc
if [ -f ~/.bash_aliases ]; then
    . ~/.bash_aliases
fi

Creating more complex aliases with functions

A function can take arguments and make multiple calls, for example:
--in file ~/.bash_aliases
gtst () {
        clear
        git branch 
        git status 
}
gtbr () {
        from=${2:-master}
        if ! `git checkout $1 &> /dev/null`; then
                `git checkout ${FROM}`
                `git checkout -b $1`
        fi
}
In the second function above we set a default value of "master" for variable 2 if no value exists. No alias entry is necessary, the function will be available.

Getting even fancier:

Let's wrap all these into a neat command called 'gt':
gt () {
        local argument2=$2
        local argument3=$3
        st () {
                clear
                git branch
                git status
        }
        br () {
                from=${argument3:-master}
                checkout=`git checkout ${argument2} 2>&1`
                if [ $? -eq 0 ]; then
                        echo "${checkout}"
                else
                        echo "`git checkout ${from}`"
                        `git checkout -b ${argument2}`
                fi
        }

        case "$1" in
                br) br;;
                st) st;;
        esac
}
Now we can call our new gt command from the command line as follows:
$ gt st
$ gt br existing-branch
$ gt br new-branch
$ gt br new-branch from-branch