This Script Turned 2 Days Into 8 Seconds

Coding (Php 7.x)

Aug 25, 2022

How using a bash files I have created many files at once
 
/img/blog/this-script-turned-2-days-into-8-seconds.jpeg

Who is This Post For?

 

Here we talk about bash files and command line.

 

If you are not quite there yet you might start with:

 

Learn PHP [the definitive guide]

 

If you know all about this topic it is time to level up your skills:

 

Discovering Higher Order Functions [refactoring to Collections]

 

TL;DR

 

  • Bash files tell the computer what it should do or say.
  • A good programmer is one who refuses to write the same code more than once.
  • You can create files and write inside them using Linux commands.
  • Save time makes you more productive and lets you do stuff you love.

 

The Tale of Hoji and Ramsey

 

Once upon a time, there was this quaint little village.

It was a wonderful location to live in excluding one issue.

 

The village had no water.

 

To solve this problem once and for all, the village elders decided to put out to bid the contract to have water delivered to the village daily.

 

Two people volunteered to take on the task and the elders granted the contract to both of them.

 

The first of the two people who won the contract, Ramsey, immediately bought two buckets and began running back and forth along the trail to the lake which was miles away.

 

He immediately began making money as he labored morning to evening carrying water from the lake with his two buckets.

 

Each morning he had to get up before the rest of the village awoke to make sure there was sufficient water for the people when they desired.

 

It was hard work, but he was pleased to be making money and having one of the two contracts.

 

The second contractor, Hoji, disappeared for a while.

 

Instead of buying two buckets to compete with Ramsey, Hoji had written a business plan, found investors, hired a president to do the work, and returned months later with a construction team.

 

Within a few months, his team built a large volume stainless steel pipeline that connected the village to the lake.

 

Hoji also announced that his water was cleaner than Ramsey’s water.

Hoji understood that there had been criticisms regarding dirt in Ramsey’s water.

 

Hoji also announced that he could supply the village with water 24 hours a day, 7 days a week.

 

Then Hoji announced that he would charge 75% less than Ramsey did, for this higher grade and more reliable source of water.

 

“I choose a lazy person to do a hard job. Because a lazy person will find an easy way to do it.” -Bill Gates

 

To compete, Ramsey immediately lowered his rates by 75%, bought two more buckets, added covers to his buckets, and started dragging four buckets each trip.

 

Eventually, Ramsey had employee and union problems.

 

The union was demanding higher salaries and wanted its fellows to only carry one bucket at a time.

 

Hoji, instead, acknowledged that if this village needed water then other villages must need water too.

 

He went off to sell his high speed, high volume, low cost, and clean water delivery system to villages throughout the planet.

 

Hoji lived happily ever after and Ramsey worked hard for the rest of his life and had financial problems forever after. The end.

 

Why your Time is Valuable?

 

One of the clearest memories I have back from my computer science days is a quote that my professor used to tell his students.

 

“A good programmer is one that who refuses to write the same code more than once.”

 

Think about that!

 

The job of a programmer is to write code that simplifies the daily routine of people all around the world.

 

We allow journalists to write their articles on a CMS making their life way easier than printing letter by letter using a printing press.

 

In the same way, we can now order food via an app from our sofa delivered by a driver that uses Maps to easily find his way to our home.

 

It sounds quite a paradox that we do this for a living and more often than not our codebase looks like a bunch of spaghetti with repeated commands here and there rather than a clear and comprehensive structure of files.

 

I am a lover of the work of Uncle Bob, one of my favorite books he wrote is Clean Architecture.

 

In there he describes an ideal structure an application should have,

 

Detailing each layer’s duties from the presentation layer to the highest ones such as the application core.

 

I am trying to replicate his advice in my work and in doing so, I try to use the same patterns for every domain I work on.

 

From the creation of a new user to the checkout of orders, the majority of the class flow looks the same, and whenever a new domain needs to be added to the system the architecture gets repeated for consistency.

 

A rough example of this architecture is:

 

 

This looks very similar to:

 

 

…And so on...

 

A couple of days ago, I realized that when a new domain or task had to be added to the application I had to manually recreate all these classes alongside their factories, compositions, and inheritances needed.

 

I was being a Ramsey!

 

Worked hard and spent whole days just, for the sake of replicating something that I had repeated over and over already.

 

I had to do something about it.

 

Bash scripts to the rescue…

 

What are Bash Files?

 

Photo by Gabriel Heinzer on Unsplash

 

I found that the best description for this type of file is the one from Ryan Chadwick on his blog ryanstutorials.com

Think of a script for a play, or a movie, or a TV show. The script tells the actors what they should say and do. A script for a computer tells the computer what it should do or say. In the context of Bash scripts we are telling the Bash shell what it should do.

 

I have managed to create a very consistent structure for my application.

 

Both the flow of the data and the control follow are well-established and this lets everything be readable and changeable if needed.

 

This has allowed me to write a script that automates this process for me.

 

So I can spend my time doing something I really like such as enjoying freshly made Cappuccinos and watching cats meme on the internet.

 

I am Jocking!

 

I don’t watch cats’ memes.

 

Let’s See Some Code

 

First thing first:

 

Here is a quick brief of some of the commands you are about to see

 

echo is one of the most basic and frequently used commands in Linux. The arguments passed to echo are printed to the standard output.

 

read is bash built-in command that reads a line from the standard input.

 

tr is a command-line utility in Linux and Unix systems that translates, deletes, and squeezes characters from the standard input and writes the result to the standard output.

 

do is a construct that generates a menu from a list of items.

 

case is generally used to simplify complex conditionals when you have multiple different choices.

 

mkdir allows you to create directories.

 

if…else statements in Bash are used to execute code based on a certain condition.

 

cat is most commonly used to display the contents of one or multiple text files, combine files by appending one file’s contents to the end of another file, and create new files.

 

Let's dive into the actual bash script:

 

1. Creating the Bash File

cat initNewDomain.sh

 

2. What are we Building?

echo "Type the name of the domain"

read domain_namedomain_name_lowercase=$(echo "$domain_name" | tr '[:upper:]' '[:lower:]')

 

This part just prompts the developer what is the new domain the script has to create and creates 2 variables out of it.

 

A capitalized and one that thanks to the tr option makes every letter of the domain lowercase

 

(you will see why we need it below).

 

An example of this would be the word Articles.

 

3. What is the Task we need?

'Please enter your choice:'options=("ListAll" "GetSingle" "Quit")
select opt in "${options[@]}"
do
    case $opt in
        "ListAll")
            endpoint_type='ListAll'
            break
            ;;
        "GetSingle")
            endpoint_type='GetSingle'
            break
            ;;
        "Quit")
            exit
            ;;
        *) echo "invalid option";;
    esac
doneecho "You choose" $endpoint_type

 

Here there is a list of objectives this new domain could perform.

 

Let’s imagine we want to retrieve all the articles published.

 

Then we will type option 1 for ListAll , the new variable will become ListAll

 

4. Creating a Controller

 

It is finally time to create a proper class now.

 

mkdir -p src/Controller/controller_class=src/Controller/"$domain_name""$endpoint_type"Controller.php
if test -f "$controller_class"; then
    echo "$controller_class already exists."
else 
    cat /dev/null > $controller_class

 

First, we create a Controller folder, then we save an ideal path where our controller will live alongside its name.

 

Then we check if the class ArticlesListAllController already exists.

 

5. Writing into the Controller

echo "logger = \$logger;
    }
/**
     *
     * @param "${domain_name}""${endpoint_type}"Service \$service
     * @return JsonResponse
     */
    public function __invoke(
        "${domain_name}""${endpoint_type}"Service \$service
    ): JsonResponse
    {
        try {
            \$"${domain_name_lowercase}" = \$service->get"${domain_name}""${endpoint_type}"();
        } catch (\Exception \$exception) {
            \$this->logger->error(\$exception->getMessage());
            return \$this->getResponse(
                \$error->getText(), 
                \$error->getCode());
        }
        return new JsonResponse(json_decode(\$"${domain_name_lowercase}"), \$"${domain_name_lowercase}"->getStatusCode());
    }
}" >> $controller_class
echo "Class "${domain_name}""${endpoint_type}"Controller created"
fi

 

This is where the magic happens!

 

The echo command prints out everything we write inside the quote the >> copies all of that into the file we have created.

 

 

 

 

6. Run the Script

sh initNewDomain.sh

 

7. Enjoy your Deserved Coffee

 

And here is your result:

logger = $logger;
    }
/**
     *
     * @param ArticlesListAllService $service
     * @return JsonResponse
     */
    public function __invoke(ArticlesListAllService $service): JsonResponse
    {
        try {
            $articles = $service->getArticlesListAll();
        } catch (\Exception \$exception) {
            $this->logger->error($exception->getMessage());
            return $this->getResponse(
                $error->getText(), 
                $error->getCode());
        }
       
        return new JsonResponse(json_decode($articles), $articles->getStatusCode());    }
}

 

This is just a quick example of how with just some questions to the developer via the command line, the script automatically created a controller file.

 

Imagine the power of it after you add 2, 5, or even 20 files that will automatically be created and filled at once.

 

(this includes PHPUnit tests).

 
 
If you like this content and you are hungry for some more join the Facebook's community in which we share info and news just like this one!

Other posts that might interest you

Coding (Php 7.x) Nov 17, 2022

How to Refactor Legacy Code

See details
Get my free books' review to improve your skill now!
I don't want to improve