Home > Article > Backend Development > How to create API with Pure PHP?
In this project we will create a Simple API using only PHP in any framework. All we will need will be:
Let's start by defining our docker-compose.yml file for our database configuration. If you don't want to use Docker to create a database in containers, a solution is to install the database on your machine. For this tutorial we will use MySQL.
After creating the folder where our application will be located, we start by configuring docker-compose.yaml:
services: mysql: image: mysql:9.1.0 ports: - '3306:3306' environment: MYSQL_ROOT_PASSWORD: useroot MYSQL_USER: api_user MYSQL_PASSWORD: api_password MYSQL_DATABASE: api_example
Let's break this file into parts for explanation:
services: mysql:
In this file we are defining the services that will be used.
I'm naming this service mysql. Attention, the name of this service will be used to connect to the database as host
image: mysql:9.1.0
Next I am defining which image will be used to create our database, for this project I am using version 9.1.0 of mysql.
You can find this and other versions on Docker Hub.
ports: - '3306:3306'
The port is being set to 3306. This is the default mysql port!
You can notice that the port is like 3306:3306, this : means that we want to listen to this port on our local machine and not just on the docker container, so we can access it it directly on our machine.
environment: MYSQL_ROOT_PASSWORD: useroot MYSQL_USER: api_user MYSQL_PASSWORD: api_password MYSQL_DATABASE: api_example
As an environment we must define the credentials for our mysql service.
Therefore, we are defining user, password and database name using environment variables:
MYSQL_USER: api_user // <--- Este é nosso usuário
MYSQL_PASSWORD: api_password // <--- Este é nosso password
MYSQL_DATABASE: api_example // <--- Este é nosso banco de dados
MYSQL_ROOT_PASSWORD: useroot // <--- Está é a senha para o usuário root
To start our container, just be inside the folder where the docker-compose.yaml file is located and type the following command in our terminal:
docker compose up -d
This will initialize the mysql service in our container.
If you want to access mysql within the terminal, you can use this command:
docker exec -it <nome do container> bash
After typing this command and pressing enter you will enter the container where the mysql image is running.
The container name is formed by foldername-hostname-number
In this case, the name of our container would be: create-api-php-mysql-1 if our application was created within the "create-api-php" directory.
We will also create a composer.json file, this file will serve as the basis for installing external libraries that will be used in the project. In this project we will only use Dotenv.
services: mysql: image: mysql:9.1.0 ports: - '3306:3306' environment: MYSQL_ROOT_PASSWORD: useroot MYSQL_USER: api_user MYSQL_PASSWORD: api_password MYSQL_DATABASE: api_example
In this line we are adding the most used library for dotenv in php.
You can find the repository for this lib at: Github Vlucas Repository
services: mysql:
In the line below we are basically saying that we will use autoload with the default configuration of the PSR-4. The most used PSRs currently are PSR-12 and PSR-4, with 12 being the most used to date. But for now we will continue using the PSR-4.
image: mysql:9.1.0
With these two files created we can give the command
ports: - '3306:3306'
It will install the Dotenv library and configure the settings for the desired PSR.
After this command, the composer.lock.
For those coming from the JavaScript world, these files can be compared with package.json and package-lock.json.
You will also see that a folder has been added to your directory with the name vendor. It contains our Dotenv lib and also a very important file: autoload.php.
We do not need to touch or change anything in this file, as it will be responsible for transacting Dotenv information between our other files.
We will also create a file called bootstrap.php, this file is responsible for initializing our application and connecting some important parameters so that everything works as expected:
environment: MYSQL_ROOT_PASSWORD: useroot MYSQL_USER: api_user MYSQL_PASSWORD: api_password MYSQL_DATABASE: api_example
We can then create the .env file to add the environment variables that will be responsible for connecting to our mysql database.
We then add:
MYSQL_USER: api_user // <--- Este é nosso usuário
We will also create a .env.example file where a copy of this information will be saved in case someone wants to clone our repository or even for us in the future if we want to continue our project, this way we will have the necessary information to know what we need define and what we don't need.
MYSQL_PASSWORD: api_password // <--- Este é nosso password
The reason we will create these two files, one containing all the information and the other containing only part of the information, is because the .env file should not be uploaded to the repository, as it contains confidential information. Let's say that in the future we want to use a third-party API where we need to add a token for access, then we will store this information within the .env file.
To prevent the .env file from being uploaded to our repository we will create a file called .gitignore and add the following information:
MYSQL_DATABASE: api_example // <--- Este é nosso banco de dados
This way we define that the .env file and the entire contents of the vendor folder will not be committed.
With this we have finished configuring our project and are free to continue coding.
We will create the following directories src/System and within System the file DatabaseConnector.php
services: mysql: image: mysql:9.1.0 ports: - '3306:3306' environment: MYSQL_ROOT_PASSWORD: useroot MYSQL_USER: api_user MYSQL_PASSWORD: api_password MYSQL_DATABASE: api_example
Here we are defining a namespace for this file, so that we can use it in the future within other files.
services: mysql:
We will create our class with the same name as the file and create a private variable named $dbConnection passing the value null.
This variable will be responsible for a new instance of this class and connecting us with the database.
We'll see more later when we implement try-catch.
image: mysql:9.1.0
Within the constructor we will create the following variables and check the values captured from the .env file with Dotenv.
ports: - '3306:3306'
Still inside the constructor we will do a try-catch to validate the action we want to perform:
environment: MYSQL_ROOT_PASSWORD: useroot MYSQL_USER: api_user MYSQL_PASSWORD: api_password MYSQL_DATABASE: api_example
Within this try we are trying to create a new instance of our class and passing it into the $dbConnection variable. We are using a PDO module for this where it receives the parameters
Error case:
MYSQL_USER: api_user // <--- Este é nosso usuário
We will trigger an exception from PDO and return the error message.
Clearly this is just an example of how we should present errors in a development environment. For production environments, it is good practice to present more concise errors that help us understand the problem more clearly.
Outside the constructor but inside our class, we will create the following function:
MYSQL_PASSWORD: api_password // <--- Este é nosso password
Being responsible for calling our variable containing the instance of our connection.
Remember our bootstrap.php file? Let's add the following lines of code to it:
MYSQL_DATABASE: api_example // <--- Este é nosso banco de dados
Looking like this:
MYSQL_ROOT_PASSWORD: useroot // <--- Está é a senha para o usuário root
Inside the folder src we will create another directory with the name Database and inside it the file database_seed.php.
This file will be responsible for populating our database for the first time, so if we want to share this project with someone it will not end up with an empty database.
Inside this file we will add the following codes:
services: mysql: image: mysql:9.1.0 ports: - '3306:3306' environment: MYSQL_ROOT_PASSWORD: useroot MYSQL_USER: api_user MYSQL_PASSWORD: api_password MYSQL_DATABASE: api_example
We import require 'bootstrap.php'; because within our bootstrap file we have already imported the variable that is responsible for instantiating our database.
services: mysql:
We create a variable with the name $statement that has a value of Heredoc
image: mysql:9.1.0
Within this Heredoc we will add some querys:
ports: - '3306:3306'
Here I am opting for drop table to drop the entire base and then start a new one, however if you want you can remove this line of code.
The following line of code specifies that this table will be used to carry out transactions and will have a connection between the tables. If you want to learn more about this mysql declaration: innoDb documentation
environment: MYSQL_ROOT_PASSWORD: useroot MYSQL_USER: api_user MYSQL_PASSWORD: api_password MYSQL_DATABASE: api_example
Within the same Heredoc we will add another query:
MYSQL_USER: api_user // <--- Este é nosso usuário
Here we are inserting some data into the person table.
We create a try-catch at the end of the file where we try to initialize the querys and in case of error we return an error message just as we did in the data processing in the codes above.
MYSQL_PASSWORD: api_password // <--- Este é nosso password
Inside src we will create another directory with the name TableGateways and inside it we will create the file: PersonGateway.php.
MYSQL_DATABASE: api_example // <--- Este é nosso banco de dados
The files inside this folder will be responsible for interacting with our database, almost like a Repository.
In our PersonGateway class we will add the following constructor:
MYSQL_ROOT_PASSWORD: useroot // <--- Está é a senha para o usuário root
We will add this constructor because our class will be called in other files so that we can trigger some methods of our class.
See the following methods:
Method responsible for listing all users in our table
docker compose up -d
Method responsible for listing a single user from our table
docker exec -it <nome do container> bash
Responsible method to insert a user into our table
{ "require": { "vlucas/phpdotenv": "^2.4" }, "autoload": { "psr-4": { "Src\": "src/" } } }
Method responsible for updating a user's information in our table
"require": { "vlucas/phpdotenv": "^2.4" },
Method responsible for deleting a user from our table
"autoload": { "psr-4": { "Src\": "src/" } }
We will create within src a directory with the name Controller and inside it the file: PersonController.php.
The files within this directory are responsible for interacting with our application route. Here we interact directly with the bank, but we could use a services layer and limit all logic and business rules to this layer.
If you want to create the services layer, it would be like this:
services: mysql: image: mysql:9.1.0 ports: - '3306:3306' environment: MYSQL_ROOT_PASSWORD: useroot MYSQL_USER: api_user MYSQL_PASSWORD: api_password MYSQL_DATABASE: api_example
However, our intention is not to delve deeper into this type of architecture, for now we will continue with the controller file:
services: mysql:
Inside our PersonController class we will add:
image: mysql:9.1.0
This way we guarantee that we are interacting with a new instance of our database.
We also created a method to process our requests:
ports: - '3306:3306'
This header is responsible for transmitting the status code and if a body is created it returns this same body to be viewed.
environment: MYSQL_ROOT_PASSWORD: useroot MYSQL_USER: api_user MYSQL_PASSWORD: api_password MYSQL_DATABASE: api_example
We also created the methods that will interact with the routes:
Method responsible for interacting with the user's listing route
MYSQL_USER: api_user // <--- Este é nosso usuário
Method responsible for interacting with the user's creation route
MYSQL_PASSWORD: api_password // <--- Este é nosso password
Method responsible for interacting with the user's update route
MYSQL_DATABASE: api_example // <--- Este é nosso banco de dados
Method responsible for interacting with the user's deletion route
MYSQL_ROOT_PASSWORD: useroot // <--- Está é a senha para o usuário root
Methods responsible for validation
docker compose up -d
docker exec -it <nome do container> bash
{ "require": { "vlucas/phpdotenv": "^2.4" }, "autoload": { "psr-4": { "Src\": "src/" } } }
Finally, we will create a directory outside our folder src with the name Public.
This folder is responsible for containing the php display file.
We will create the file inside it: index.php
We will add the following code:
"require": { "vlucas/phpdotenv": "^2.4" },
This file is responsible for setting the headers and checking access to the url. If the access is successful it returns the contents, if not it returns an error.
To access your application, simply upload a server using the internal PHP server:
"autoload": { "psr-4": { "Src\": "src/" } }
if you have not initialized the container, type the following command in the terminal:
composer install
Now just use postman or any other application that helps you interact with url.
My social networks:
Github Linkedin
The above is the detailed content of How to create API with Pure PHP?. For more information, please follow other related articles on the PHP Chinese website!