You can visit a demo of the project visiting the following Heroku App instance:
https://tenejob-laravel-api.herokuapp.com/
Table of contents:
- TeneJob Laravel API Demo
This is a demo project to provide an example of my skills for building a REST compliant API, using Laravel, writing PHPUnit unitary tests and, taking advantage of tools like Composer (a dependency manager for PHP), Git (a distributed version control system) and, the Unix Shell. The full development environment is built on top of Docker (using the Laradock project). Also reflects my knowledge of modern development platforms like GitHub (an online source code repositories hub).
This project has not been wrote in any case thinking to be used in production, but can be used as you wants under your total responsability. You can also fork it and, use as a foundation for your own project if you found it useful.
The temporary recruitment agency called TeneJob wants to optimize the way they assign their workers to the different shifts of the jobs they work with.
In order to help them with this mission, you need to build an API endpoint that will accept a list of workers and shifts and return the best pairing options.
The problem has 3 main entities: Worker, Shifts, and Matchings.
A Worker has a weekly availability which is the days of the week (not including weekends) they can work. For example, a worker might only be able to work on Mondays and Wednesdays. Also, a worker might have a payrate, which is the amount of money paid to him for each shift he works on.
A Shift is a piece of work that needs to be done by a worker. To simplify the problem, you can consider a shift takes a whole day to be completed.
A Matching is the pairing of one worker with one shift. Two rules apply to shifts:
- A worker can only work on one shift during the same day
- A shift can only be matched with one worker
This API provides an endpoint that receives a list of workers and a list of shifts and returns the optimal list of matchings. A list of matchings is optimal if each worker is paired with at least one shift. In some scenarios, the algorithm won't able to get an optimal solution. In that case, the algorithm detects the situation and returns a message indicating this.
Build a dockerized system that can run as a docker container, to test the solution. This requirement is mandatory. The endpoint input and output should be sent in JSON format and it need to be REST compliant. The structure and an example of these are provided in the next section of this README.md file.
This project demo focuses on:
- Organization of the code, the structure, scaffold and design patterns
- The efficiency to generate the matchings
- Documentation and code readability
- Good development practices:
- Unit tests
- Input data validation o Error handling
Structure example of the JSON data that the /api/matchings/auto-generate
endpoint will expect:
{
"workers": [
{
"id": 1,
"availability": ["Monday", "Wednesday"],
"payrate": 7.50
},
{
"id": 2,
"availability": ["Monday", "Tuesday", "Thursday"],
"payrate": 9.00
},
{
"id": 3,
"availability": ["Monday", "Friday"],
"payrate": 18.00
},
{
"id": 4,
"availability": ["Monday", "Tuesday", "Friday"],
"payrate": 12.25
}
],
"shifts": [
{
"id": 1,
"day": ["Monday"]
},
{
"id": 2,
"day": ["Tuesday"]
},
{
"id": 3,
"day": ["Wednesday"]
},
{
"id": 4,
"day": ["Thursday"]
}
]
}
The /api/matchings/auto-generate
endpoint will validate the data sent through POST.
One of the validations to be considered first of all is that all the shifts
and workers
should already exist on the database. The endpoint will validate that each ID of shifts
and workers
exists on the DB and, it will also compare the data of each shift
and worker
against the each ones stored on the DB. The endpoint will also return verbose error messages if invalid data is sent. So, consider login trough the web interface and put some data for your testing purposes.
In this section, you can get the instructions to setup this project on your local machine for development and testing purposes.
This project has a few mandatory requirements. Make it sure you you have installed:
Git >= 2.13
Docker Engine >= 17.12
Clone the project (and it's git submodules) using Git:
git clone --recurse-submodules https://github.com/josepcrespo/tenejob-laravel-api.git
- Enter the
/laradock
folder and rename env-example to .env.
cp env-example .env
- Open the
.env
file of this project (tenejob-laravel-api) and set the following:
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=tenejob
DB_USERNAME=root
DB_PASSWORD=root
REDIS_HOST=redis
QUEUE_HOST=beanstalkd
MAIL_DRIVER=smtp
MAIL_HOST=maildev
MAIL_PORT=25
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
- Execute the following command inside the
laradock
folder, to build an run the containers:
docker-compose up -d nginx mysql workspace maildev
- Execute the following command inside the
laradock
folder, to get access to the MySQL Command-line Client inside themysql
container:
docker-compose exec mysql mysql -u root -proot
- Create the database for the app:
CREATE DATABASE tenejob;
- To install the defined dependencies for your project (don't execute Composer inside the workspace as is not recommended to run it as root), just run the
composer install
command into the project root directory using the Terminal.app (if you are using macOS) or with your preferred Shell:
php composer.phar install
You may want to look into the official Composer guidelines for Installing Dependencies for more details.
⚠️ If you used the--filename
option on the Composer installation
- Maybe you installed your Composer using the
--filename
installer option, for example in this way:php composer-setup.php --filename=composer
In that case, you should runcomposer install
in order to install the dependencies.
- Laradock introduces the Workspace Image, as a development environment. It contains a rich set of helpful tools, all pre-configured to work and integrate with almost any combination of Containers and tools you may choose. We should use this workspace container to execute the Laravel migration files.
docker-compose exec workspace bash
- Run the Laravel migration files to create all the tables into the MySQL container.
artisan migrate
- Open your browser and visit localhost:
http://localhost
This are the main problems (and the solutions) I've found executing the docker-compose up
command the first time, when Docker downloads and installs all the containers needed.
- Problems with the
mysql
Docker volume:
Everything works again after deleting the data folder of the mysql
Docker volume:
rm ~/.laradock/data/mysql
(This is the path in my macOS machine)
- Service
aws
failed to build:
As pointed here, a GitHub thread of the Laradock project repository. You should:
mkdir aws/ssh_keys/
touch aws/ssh_keys/id_rsa.pub
docker-compose build --no-cache
- SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client:
As pointed here, a GitHub thread of the Laradock project repository. You should:
Change MYSQL_VERSION
to 5.7
in laradock/.env
and, then execute:
docker-compose build --no-cache mysql
After installing Laravel, you may need to configure some permissions. Directories within the storage and the bootstrap/cache
directories should be writable by your web server or Laravel will not run.
First, enter your Laradock Workspace:
docker-compose exec workspace bash
chmod -R 777 ./storage ./bootstrap
Set your application key to a random string.
artisan key:generate
Read the API documentation through the Swagger Web Interface at:
http://localhost/api/docs
If you want to use the "forgot password" feature…
On your local development environment with Laradock:
the email with the link to restore your password will be sent to MailDev (a local mail server for local development). You can easily access the web interface at:
http://localhost:1080/
On the Heroku instance environment: the email with the link to restore your password will be sent to Mailtrap Heroku Add-on (a local mail server for testing purposes). You can easily access the web interface at:
https://heroku.mailtrap.io/inboxes/520364/messages
The Unitary Tests has been made using PHPUnit.
Assuming that you have all the dependencies installed using Composer, you can run the Unitary Tests by simply executing entering the Docker Workspace and typing the following command in the root directory of the project:
phpunit
The project have some basic unit tests but, the testing environment are not configured properly so, is expected to get all of them throw a Fail o Error message.
First of all, install the Heroku CLI in order to be able to continue with the following steps. To do so, execute the following command in case you are using macOS and have Homebrew installed. In other cases, please read on the Heroku Dev Center the official documentation for installing the command line interface.
brew install heroku/brew/heroku
Initialize a Git repository in the root of the project if you don't already have one.
git init
Commit any changes you want to deploy into the master branch (this is the one used by Heroku to deploy new changes into his servers).
echo web: vendor/bin/heroku-php-apache2 public/ > Procfile
git add .
git commit -m "Procfile for Heroku"
heroku create [your-app-name]
The string that you uses on the placeholder of [your-app-name]
on the command above will be your name on your Heroku Dashboard and also, the sub-domain of the URL provided by Heroku for you application. In the case of this project, the command was executed as following:
heroku create tenejob-laravel-api
and, the resulting URL for the app is:
https://tenejob-laravel-api.herokuapp.com/
heroku config:set APP_KEY=$(php artisan --no-ansi key:generate --show)
Also, you need to set all the keys/values stored on your .env
file but with the appropriate values for your Heroku instance. This project's config variables can be set using the Heroku Dashboard if you login into your app instance at heroku.com.
git push heroku master
Add ClearDB:
heroku addons:create cleardb:ignite
Retrieve the values of your ClearDB setup to be able to connect to your app with the Heroku DB:
heroku config | grep CLEARDB_DATABASE_URL
For example, from this URL:
mysql://b6de34rj38adfad3:[email protected]/heroku_c40fa7a488382ef?reconnect=true
- the string between
mysql://
and:
is yourDB_USERNAME
i.e b6de34rj38adfad3 - the string between
:
and@
is yourDB_PASSWORD
i.ea10cd36db
- the string between
@
and the next/
is yourDB_HOST
i.eus-cdbr-iron-east-05.cleardb.net
- the string between
/
and?
is yourDB_DATABASE
i.eheroku_c40fa7a488382ef
You should set all this values on your Heroku App Dashboard or using the Heroku CLI.
heroku run php artisan migrate
heroku open
Laravel, a MVC PHP Framework based on Symfony
Laradock, a full PHP development environment for Docker
Docker, operating system level virtualization
Git, a distributed version control system
Getting Started on Heroku with PHP
The Heroku CLI
Getting Started with Laravel on Heroku
Configuration and Config Vars
ClearDB Mysql
Rename your Heroku app
How to deploy a Laravel 5 app to Heroku step by step: