- Postman Collection
- Frameworks
- Prerequisites
- Installation
- API Usage
- Building Your Queries
- Example Queries
- Contact
You can interact with the API using the Postman collection provided here: Job Board API Postman Collection
Proceed by installing this project on your local machine first, then import the collection to Postman to start testing the API.
Please note that seeding the database will generate random data, so the results may vary.
- Laravel 12
- PHP 8.2 or higher
- Composer
- PostgreSQL (or any SQL DB)
Note: The following installation is directed for testing environment. This setup is not production-ready as this is not the purpose of this project.
Follow the following instructions to install the project on your local machine.
git clone https://github.com/ahmed-fawzy99/job_board_api_laravel.git
cd job_board_api_laravel
composer install
cp .env.example .env
php artisan key:generateThen open .env file do the following fill in your database credentials.
To generate basic data needed to start and test the system, we need to run the migrations and starter seeder:
php artisan migrate --seedRun the development server
php artisan serveThe Postman collection has the following endpoints with examples. The following are the endpoints:
- GET
/api/v1/jobs- Get all jobs - GET
/api/v1/jobs/{id}- Get a job by ID - GET
/api/v1/attributes- Get all attributes - GET
/api/v1/attributes/{id}- Get an attribute by ID - GET
/api/v1/categories- Get all categories - GET
/api/v1/categories/{id}- Get a category by ID - GET
/api/v1/langauges- Get all languages - GET
/api/v1/langauges/{id}- Get a language by ID - GET
/api/v1/locations- Get all locations - GET
/api/v1/locations/{id}- Get a location by ID
- All filters and sorting should be passed as query parameters.
- to filter multiple values, separate them with a comma
,.- Example:
?filter[FIELD_NAME]=VALUE1&filter[FIELD_NAME]=VALUE2&sort=FIELD_NAME
- Example:
- Multiple filters can be passed in the same query. They will be treated as
ANDconditions.- Example:
?filter[FIELD_NAME1]=VALUE1&filter[FIELD_NAME2]=VALUE2&sort=FIELD_NAME
- Example:
- The API supports filtering, sorting, and loading relationships for the jobs resource.
- The jobs will not contain any relationships by default. You need to include them in the query if you want to load them.
- The API supports filtering by dynamic attributes. You can filter by any attribute name.
-
?filter[FIELD_NAME]=VALUE- Filter the results by a specific field -
?filter[FIELD_NAME]=!Value- Filter the results by a specific field that is not equal to the value.- Supported fields:
id,title,description,status, andjob_type.
- Supported fields:
-
?filter[FIELD_NAME]=VALUE1,VALUE2- Filter the results by a specific field that is equal to one of the values.- Supported fields:
id,title,description,status, andjob_type.
- Supported fields:
-
?filter[FIELD_NAME]=*VALUE*- Filter the results by a specific field that contains the value.- Supported fields:
title,description.
- Supported fields:
-
?filter[DATE_FIELD]=VALUE1, - Filter the results by a specific date field that is equal to the passed value.- Supported fields:
publishedAt,createdAt, andupdatedAt. - The date should be in the format
YYYY-MM-DDorYYYY-MM-DD HH:MM:SS.
- Supported fields:
-
?filter[DATE_FIELD]=>VALUE1, - Filter the results by a specific date field that is after the passed value.- Supported fields:
publishedAt,createdAt, andupdatedAt. - The date should be in the format
YYYY-MM-DDorYYYY-MM-DD HH:MM:SS.
- Supported fields:
-
?filter[DATE_FIELD]=<VALUE1, - Filter the results by a specific date field that is before the passed value.- Supported fields:
publishedAt,createdAt, andupdatedAt. - The date should be in the format
YYYY-MM-DDorYYYY-MM-DD HH:MM:SS.
- Supported fields:
-
?filter[DATE_FIELD]=VALUE1,VALUE2- Filter the results by a specific date field that is between the two passed values.- Supported fields:
publishedAt,createdAt, andupdatedAt. - The dates should be in the format
YYYY-MM-DDorYYYY-MM-DD HH:MM:SS.
- Supported fields:
-
?filter[NUMBER_FIELD]=VALUE1- Filter the results by a specific number field that is equal to the passed value.- Supported fields:
salaryMinandsalaryMax.
- Supported fields:
-
?filter[NUMBER_FIELD]=>VALUE1- Filter the results by a specific number field that is greater than or equal to the passed value.- Supported fields:
salaryMinandsalaryMax.
- Supported fields:
-
?filter[NUMBER_FIELD]=<VALUE1- Filter the results by a specific number field that is less than or equal to the passed value.- Supported fields:
salaryMinandsalaryMax.
- Supported fields:
-
?filter[NUMBER_FIELD]=VALUE1,VALUE2- Filter the results by a specific number field that is between the two passed values.- Supported fields:
salaryMinandsalaryMax.
- Supported fields:
-
?filter[BOOLEAN_FIELD]=true|false- Filter the results by a specific boolean field that is equal totrueorfalse.- Supported fields:
isRemote.
- Supported fields:
-
?filter[attribute:ATTR_NAME]=VALUE- Filter the results by a specific attribute field- supported fields: dynamic attributes fields.
-
?filter[location]=VALUE- Filter the results by a specific location -
?filter[location]=VALUE1|VALUE2- Filter the results by any of the passed locations -
?filter[location]=VALUE1,VALUE2- Filter the results that have all the passed locations
Note: You can also pass remote as a location value to filter remote jobs
-
Example:
?filter[location]=Cairo|remotewill return jobs in Cairo or remote jobs. -
?filter[language]=VALUE- Filter the results by a specific language -
?filter[language]=VALUE1|VALUE2- Filter the results by any of the passed languages -
?filter[language]=VALUE1,VALUE2- Filter the results that have all the passed languages
?include=RELATIONSHIP_NAME- Load a specific relationship?include=RELATIONSHIP_NAME1,RELATIONSHIP_NAME2- Load multiple relationships
Note: Include the plural form of the relationship name. For example, to load the categories relationship, you should use categories instead of category.
?sort=FIELD_NAME- Sort the results by a specific field?sort=-FIELD_NAME- Sort the results by a specific field in descending order?sort=FIELD_NAME1,-FIELD_NAME2- Sort the results by multiple fields
Grouping can be achieved implicitly by passing multiple filters and combining AND/OR operators. This is a design choice to keep the API simple and easy to use.
For example, (job_type=full-time AND (languages HAS_ANY (PHP,JavaScript)))AND (locations IS_ANY (New York,Remote)) AND attribute:years_experience>=3 can be achieved by passing the following query:
/api/v1/jobs?filter[job_type]=full-time&filter[language]=PHP|JavaScript&filter[attribute:experience_years]=>3&filter[location]=NY|Remote
Not implemented as they are not needed for the current project. However, I've laid out the structure to make it easy to implement in the future.
-
Get all jobs that are published after
2022-01-01and have asalaryMingreater than or equal to5000and are remote:/api/v1/jobs?filter[publishedAt]=>2022-01-01&filter[salaryMin]=>5000&filter[isRemote]=true
-
Get all jobs that are published after
2022-01-01and have asalaryMingreater than or equal to5000and are remote, and include the category relationship, and sort bysalaryMinin descending order:/api/v1/jobs?filter[publishedAt]=>2022-01-01&filter[salaryMin]=>5000&filter[isRemote]=true&include=categories&sort=-salaryMin
-
Filter by dynamic attributes:
/api/v1/jobs?filter[attribute:experience_years]=12. This will only work if the attributeexperience_yearsexists in the database and the current job utilizes it.
-
Filter full-time jobs, requries PHP or JavaScript, requires min 3 years of experience and in NY or remote:
-
/api/v1/jobs?filter[job_type]=full-time&filter[language]=PHP|JavaScript&filter[attribute:experience_years]=>3&filter[location]=NY|Remote
- The names of location values (city, state, country), as well as language names, are stored in lowercase to make filtering case-insensitive. Even though it is possible to process case-insensitive queries on both Laravel and Database lever, it's a process that relatively consumes more resources. Therefore, it's better to store the values in lowercase to avoid the need for case-insensitive queries. The client can manage the case sensitivity on their end.
- As previously mentioned, grouping conditions are not explicitly supported. This is a design choice to keep the API simple and easy to use. The client can achieve grouping by passing multiple filters and combining AND/OR operators.
- Relationships are not loaded by default. The client needs to include them in the query if they want to load them. This is to avoid unnecessary data transfer and to keep the response size small.
You can reach me using any of the following media: