---
title: 'Create a PHP REST API : Write a RESTful API from Scratch using Plain, Object-Oriented PHP and MySQL'
source: 'https://youtube.com/watch?v=X51KOJKrofU'
video_id: 'X51KOJKrofU'
date: 2026-06-16
duration_sec: 0
---

# Create a PHP REST API : Write a RESTful API from Scratch using Plain, Object-Oriented PHP and MySQL

> Source: [Create a PHP REST API : Write a RESTful API from Scratch using Plain, Object-Oriented PHP and MySQL](https://youtube.com/watch?v=X51KOJKrofU)

## Summary

This video tutorial teaches how to build a complete RESTful API using plain object-oriented PHP and MySQL. It covers setting up endpoints, routing, database integration, and handling CRUD operations (Create, Read, Update, Delete) with proper HTTP methods and status codes. The code is free to download, and the tutorial uses tools like HTTPie for testing.

### Key Points

- **Capturing and Parsing the URL** [0:42] — Use `$_SERVER['REQUEST_URI']` to get the URL path, then parse it with `explode()` to extract segments like 'products' and an optional ID.
- **URL Rewriting with .htaccess** [2:09] — Create an `.htaccess` file with `RewriteEngine On` and a rule to route all requests to `index.php`.
- **Creating the Controller Class** [5:19] — Create a `ProductController` class with a `processRequest` method that takes the HTTP method and ID, then delegates to `processCollectionRequest` or `processResourceRequest`.
- **Autoloading Classes** [6:39] — Use `spl_autoload_register()` to automatically load class files from the 'source' folder.
- **Setting JSON Content Type** [10:20] — Set the Content-Type header to 'application/json; charset=utf-8' to return JSON responses.
- **Database Connection Class** [11:59] — Create a `Database` class that uses PDO to connect to MySQL, with configurable host, dbname, username, and password.
- **Custom Exception Handler** [14:48] — Implement a custom exception handler using `set_exception_handler()` to return errors as JSON with a 500 status code.
- **Product Gateway for Database Operations** [16:51] — Create a `ProductGateway` class with methods like `getAll`, `get`, `create`, `update`, and `delete` to interact with the product table.
- **PDO Configuration for Native Types** [20:26] — Configure PDO attributes `ATTR_EMULATE_PREPARES` and `ATTR_STRINGIFY_FETCHES` to false to preserve integer and boolean types.
- **Handling POST Requests and Validation** [22:46] — For POST requests, read JSON data from `php://input`, decode it, and validate required fields like 'name'.
- **Error Handler for PHP Errors** [28:12] — Use `set_error_handler()` to convert PHP errors into exceptions, ensuring they are also returned as JSON.
- **Updating Resources with PATCH** [37:07] — For PATCH requests, update only the provided fields, using existing values for missing ones.
- **Deleting Resources** [41:12] — For DELETE requests, remove the record and return the number of affected rows.
- **Handling Unsupported Methods** [42:43] — Return 405 Method Not Allowed with an Allow header for unsupported HTTP methods.

## Transcript

in this video you'll learn how to create a 
complete restful api using plain object-oriented  
php and mysql all the code developed in this video 
is free to download and use and the link is in the  
description to make api requests you'll need 
an api client for example curl postman or http  
in this video i'll be using httpi on the command 
line we'll start with the api endpoints first  
we'll create a new file called index.php in 
here we'll start with the php opening tag  
and for now let's just print out the value of the 
request uri element from the server super global
let's see what response we get from that page on 
the command line using httpi we make a get request  
to that page and we see the response status code 
which is 200 the response headers and the response  
body in the response body we see the output of 
the vardump call and this is printing out the  
path part of the url index.php if we make that 
request again but remove the index.php part as  
index.php is the default the request still works 
and the value we get printed out is just the slash  
so this server variable contains the part 
of the url after the host name as the api  
is going to be restful however we want a specific 
endpoint url format a restful api consists of two  
urls one for a collection of resources and one for 
an individual one that contains the resource id  
the result of calling the endpoint 
depends on the combination of the url  
and the request method used so in order to have 
restful urls we need to do some url rewriting  
as i'm using apache let's add a new file called 
htaccess where we can specify server configuration  
settings in here we'll turn the rewrite engine on 
then add a rewrite rule with a pattern of a dot  
that matches any url and we'll 
substitute this with the index.php script  
basically this says that any url will now call 
the index.php script no matter what it is these  
rules are only valid for apache and compatible 
web servers and i'm deliberately keeping this  
very simple for the purposes of this video but if 
you need the rewrite rules for another web server  
let me know in the comments let's give that a try 
now if i make a request to any url the index.php  
script is executed and we get the path part of 
the url printed out as an aside with httpi the  
default request method is get so if we're making 
a get request we don't need to specify the method  
also the http protocol is the default so 
we don't need to specify that either now  
we have access to this part of the url from our 
code we can pass it to get the segments we need
so instead of printing this out we'll 
use the explode function to split it up  
using the forward slash character we'll 
assign this to a variable and print that out
if we call the slash product endpoint then 
we get an array with two elements the element  
with an index of one containing the string 
products if we add an id to that endpoint  
then this is placed in an additional array element 
we're just creating an api for products so if the  
url is something else we'll respond with a 404 
status code which you'll no doubt be familiar with  
so instead of printing this out if 
the first segment isn't products  
we'll call the http response code function 
setting the status code of 404 and we'll  
exit the script as for the id this will be 
the second segment or if it's not specified  
we'll default it to null for now let's 
just print that out to see what it contains  
if we make a request to an end point that isn't 
slash products we get the 404 not found response  
if we make a request to the collection endpoint  
we get a response with a status code of 200 which 
is the default success response code and the id  
is null if we add the id to 
the url we get this printed out
note that for the purposes of this 
video i'm keeping the routing simple  
with a simple rewrite rule and passing the 
url manually like this in a more complex  
project you'd probably use a third-party router 
component like fastroot to provide the routing  
next let's add a controller class to control the 
response to this first let's add a new folder  
to store the class files called source then a 
new file in here called productcontroller.php
in here we'll add the php opening tag and the 
class definition next let's add a public method  
to this called process request the response 
depends on the request method and if there's a  
resource id or not so let's add a string argument 
for the method and a string argument for the id  
to keep it simple we'll just echo out the response 
from this method so we'll declare the return type  
as void as we just saw when we made a request the 
id can be null so we'll make this type declaration  
nullable inside this method for now let's just 
print out the values of these two arguments  
back in the index script as we're using type 
declarations let's enable strict types at  
the top of the script then in order to use the 
class we just added we need to require the file  
that it's in instead of explicitly doing this 
as we'll be adding more class files later on  
let's add an auto loader to load class files 
automatically we'll do this by calling the spl  
auto load register function passing in 
a callback function that will be called  
whenever a previously unused class is referenced 
passing in the name of that class as an argument  
in the body of the function we'll require that 
class in the source folder using the dir constant  
to reference the directory of the current file the 
class variable passed into the function contains  
the name of the class you are trying to use so as 
the file name matches the class name we can just  
add the dot php suffix and we'll get the right 
file name in a larger project you'd probably use  
composer's autoloader but again for the purposes 
of this video we're keeping it as simple as we can  
then at the end of the script now we can 
use the controller class we just added  
so instead of printing out the id 
variable we'll create a new object  
of the product controller class then we 
can call the process request method on this  
passing in the request method which we can 
get from the server super global then the id
so now if we make a request to slash 
products the controller class is loaded  
automatically and we get the request method 
printed out which is get and the id is null  
if i add the id then we get that printed out too  
if i change the request method for example 
to post then this is what is printed out  
back in the controller now we can actually process 
the request instead of printing out this message  
we're going to base the response on the request 
method and the id if there's an id then it's a  
request that affects a single resource and if 
not it's a request that affects a collection of  
resources instead of doing all the processing 
in one method let's add separate methods for  
each one of these a process resource request 
method passing in the request method and the  
id as arguments and a process collection request 
method to which we'll just pass the request method  
then back in the process request 
method we can call these two methods
let's start by processing the collection requests
a get request to slash products should return a 
list of products and a post request will create a  
new product so in the process collection request 
method let's check the request method with a  
switch statement if it's get will return a list of 
products the standard format of an api response is  
javascript object notation or json so let's start 
by just outputting an array containing a sample  
element encoded as json then a break statement 
to end the case block if we make a get request  
to slash products then we see the array in the 
response body however if we look at the content  
type response header it's set to text html 
which is the default as we're returning json  
we need to set this to the json content 
type instead of doing this in here as every  
response we send back from the api will be in 
json format we'll do it in the index script  
so just after we set up the auto loader we'll call 
the header function passing in a string to set the  
content type header to application json and also 
additionally specifying the character set as utf-8
so when we make the same request the 
content type header is set to json  
plus using httpi the response body now 
contains additional color formatting  
now we have this setup we can return some 
actual data instead of this hard-coded value  
i'm going to create a database 
quickly by running this sql  
this will create a database called productdb 
and a table in that database called product  
this table contains various 
columns of different types  
to demonstrate how these are handled in an api 
client and how they're json encoded there's a  
link to the source code that includes this sql 
in the description of this video let's run that
and there's the database and the product table
while we're here let's just insert a 
couple of example records into this table  
we don't need to provide values for the id 
column as being an auto increment column  
values for this will be assigned automatically 
if we browse the table there are the two records
now we can connect to the database from 
php first let's add a class to represent  
the database connection so we'll add a new 
file in the source folder called database.php  
in here we'll add the php opening tag and the 
class definition to connect to the database  
we need details such as the hostname database name 
username and password let's pass these values in  
when we create an object of this class using 
the constructor method we'll add arguments for  
the database host database name username and 
password if you need any other values like the  
port for example then you can include them here 
we'll use constructive property promotion to  
automatically create private properties for each 
of these and assign the values of these arguments  
to these properties next let's add a method called 
get connection which will return a pdo object  
in the body of this method let's create a variable 
for the dsn containing the hostname and database  
name using the values of the properties we 
created above then we'll create a new pdo  
object passing in the dsn username and password 
and we'll return this object from the method
in the index page let's create an object 
of this class passing in the database  
host name username and password i'm using the 
root account which by default has a blank password  
this is fine when you're developing locally but 
on a production machine the connection should  
have its own username and password also to keep 
it simple i'm going to hard code these values in  
here but in reality what you'd probably do is 
have these settings in a separate config file  
to test the database code we just created let's 
call the get connection method on this object
if we make a get request to slash products then 
we get the same response as earlier with the  
json test data this means that the class has 
been loaded automatically and we connect it to  
the database successfully however let's see what 
happens if i get one of the database connection  
details wrong for example an incorrect password 
now if we repeat the request we get an exception  
this is as expected however by default 
the exception details are formatted as  
html we always want to return json 
from the api even if there is an error  
to fix this we could put a try catch block around 
the get connection method call and output the  
error details as json in the catch block instead 
however let's add a generic exception handler that  
will output any unhandled exception as json we can 
do this with the set exception handler function  
this takes a callback function that will be 
executed when an unhandled exception occurs  
the single argument to this function is an object 
of the throwable class so let's add a new file in  
the source folder called errorhandler.php 
and in here we'll add the php opening tag  
and the class definition then let's add a method 
called handle exception with the single argument  
of type throwball that represents the exception 
that's been thrown and doesn't return anything in  
the body of the method we'll output some json that 
contains various data from the exception object we  
can get the error code the error message the file 
it occurred in and the line number in that file  
in addition to outputting the exception details 
in the response body let's also set the http  
status code to 500 indicating that there is an 
error on the server to use this class as the  
generic exception handler in the index file we 
call the set exception handler function passing  
in a string that identifies the handle exception 
method in the error handler class we just added  
we do this as early as possible in this script 
so that it's enabled as soon as possible  
but so that the class is loaded automatically we 
have to do it after we've created the autoloader  
let's make the api request again and now 
we get the error details encoded as json  
along with the 500 internal 
server error http status  
now we've tested the error handler we can change 
the password back to the correct one next we can  
use this database connection to make a query 
to the database we'll do this in a separate  
class we'll start by adding a new file in 
the source folder called productgateway.php
this class uses the table gateway pattern 
basically its methods serve as a gateway to the  
product table in the database we'll add the php 
opening tag and the class definition the methods  
in this class depend on a database connection 
so we'll pass an object of the database class  
in using the constructor all the methods in this 
class are going to use the database connection  
so instead of using constructor property 
promotion to simply store this value in a property  
let's add a private property to the class to 
store the pdo connection object then in the  
body of the constructor method we'll call the get 
connection method on the database object and store  
this in the property then let's add a method 
to get all the records from the product table  
we'll add a new public method called get all and 
this will return an array in the body of this  
method we'll add a variable containing the sql 
to select all the records from the product table  
we'll keep it simple with no order by clause or 
limit or anything like that just the sql to select  
all of the records then we'll call the query 
method on the connection object passing in the sql  
and assigning the returned pdo statement object 
to a variable we want to return an array of rows  
so let's initialize a variable with an empty array 
then we'll use a while loop to fetch each row in  
turn as an associative array inside the loop 
we'll append the row to the array and finally  
in this method return the array of row data now we 
can call this method to query the database which  
we'll do here in the product controller class 
however instead of creating an object of the  
product gateway class in here we'll pass one in as 
a dependency so let's add the constructor method  
with a product gateway object argument and 
we'll add a private visibility modifier to this  
so that the value of this argument will 
be assigned to a private property with the  
same name then in the process collection request 
method instead of outputting this hard-coded array  
we'll call the get all method on the gateway 
property to get this working back in the index  
script we just need to stitch all this together 
so instead of calling the get connection method  
in here we'll create a new product gateway object 
passing in the database as an argument then we  
can pass this gateway object in as an argument 
when we create the product controller object  
let's give that a try now if we make the same 
request again we get the json containing the  
two records from the database that we inserted 
earlier note however that the values for each  
record are encoded as strings even though in the 
database the id and size columns are integers  
and the is available column is boolean this is 
because pdo is converting these values to strings
if the pdo stringify fetch's attribute is true  
then all values will be converted to 
strings so we need to set this to false  
we also need to set the emulate prepares 
attribute to false so that this works
so in the database class when we create a 
new pdo object we'll add a fourth argument  
that's an array and we'll set both the emulate 
prepares and stringify fetch's attributes to false  
now if we make the api request again the 
numbers have no longer been converted to strings  
note however that the boolean value is also 
a number one or zero this is to be expected  
as internally the database server stores boolean 
values as one for true and zero for false if  
you want these to be boolean literals in the 
json then they have to be converted manually
so in the product gateway class inside the 
while loop where we're getting each row from the  
database before we append the row to the array 
we'll cast the is available column to boolean
now when we make the api request the is 
available column is output as a boolean literal  
true or false so when we make a get request 
to the collection url slash products we get  
a list of all the products next let's add the 
functionality to create a new product which we  
do by making a post request to the same url so 
in the product controller class in the process  
collection request method we'll add a new case to 
the switch statement for when the request method  
is post first we need to get the data from the 
request with a post request for a regular web form  
that you would submit from a browser the data from 
that form would be available in the post array  
so let's assign that array to a variable and 
print it out to see what we get if we make a post  
request to the collection endpoint with some data 
in the request we get an empty array printed out  
by default httpi sends data in the request encoded 
as json as the api is responding with json encoded  
data we'll require that data sent to the api is 
encoded as json also instead of the post array  
we get json data from the request 
directly from the php input stream  
we do this by using the file get contents function 
passing in this string to identify that stream
now if we make the same request we get a string 
containing some json let's decode that json  
using the json decode function passing in true as 
the second argument to get an associative array  
if we make the request again now we have an 
associative array containing the data from the  
request if we add another item of data this adds 
a new element to that array note that with httpi  
by default values are encoded as strings to send 
a literal integer or boolean value for example  
we need to add a colon before the equal sign now 
the value for that field is encoded as an integer  
note what happens though if we make a post 
request but don't include any data in the request  
we get null to make the api more robust 
and handle this possibility we need to  
check that this value isn't null the json decode 
function will return null if the json is invalid  
or if there isn't any data we could check for 
this with an if statement but a simpler way to  
do it is to just cast this value to an array 
if the value is already an array then nothing  
happens if it's null then it will be converted to 
an empty array if we make an empty post request  
again now we get an empty array instead of null 
now we have an array of data from the request  
we can insert a new record into the database 
to do this first in the product gateway class  
let's add a new public method called create with 
an array argument for the data inside this method  
we'll add a string containing the sql to insert 
a new record into the product table specifying  
the name size and is available columns with 
placeholders for the values then we'll use  
a prepared statement for this so we'll call 
the prepare method on the connection property  
passing in the sql then we can bind the values to 
the placeholders first the name which is a string
then the size which will default to zero if it 
wasn't supplied binding its value as an integer  
finally the is available column which will 
default to false and we'll cast this to boolean  
just in case the value was supplied as another 
type and we'll bind this as a boolean value  
then we'll execute the statement and we'll 
return the id of the record that was inserted  
which we can get by calling the last 
insert id method this method returns  
a string so we'll add the string return 
type declaration to the function definition
then back in the controller instead of 
outputting the data from the request  
we can call the create method on the gateway 
property passing in the array of data this  
returns the id of the newly created record so 
we'll assign that to a variable for the response  
to this request we'll output some json with 
a message saying that the product was created  
and its id finally we'll add a break 
statement to end the case block
let's give that a try if we make a post request to 
the product's endpoint passing in just a product  
name we get a reply saying the product with an 
id of 3 was created if we include the size we get  
a product with an id of 4 and if we include 
the is available field we get product id 5.
in the database we can see the three new 
records that we just inserted using the api  
where we didn't specify values for the size and 
is available columns the values for these were  
defaulted note that in the output when we 
make this request we have a status code of  
200. this is the default status code if we don't 
change it however when inserting a new record the  
status code to use is 2 0 201 so let's set 
that using the htt response code function
now if we make a successful request to create a 
new product we get the 201 created status code  
watch what happens though if we make a request 
with no data at all we get a couple of errors  
the first tells us we have an undefined array 
element the second is a database error that  
comes from trying to insert a record with 
no value for the name column however note  
that the first error isn't encoded as json even 
though we configured a generic exception handler  
what's actually happening here is that a 
php error has occurred which isn't caught  
by the custom exception handler to catch the 
error we have to set a custom error handler  
using the set error handler function the callback 
function we passed to this has this signature with  
the error number message and so on so first in the 
error handler class let's add a new public method  
called handle error which fits this signature 
although we only need the first four arguments
inside the method instead of repeating 
what we have in the exception handler  
we can just throw a new exception 
of the error exception class  
this exception class was designed to 
represent errors as exceptions the  
constructor takes various different arguments 
for the various attributes of the exception  
so in the body of the handle error method we'll 
throw a new error exception passing in the error  
message zero for the exception code as we don't 
have this the error level file where it occurred  
and the line number in that file then in the 
index script before we set the exception handler  
we'll call the set error handler function 
passing in the callback function we just added
now if we make a post request without 
any data we get the error encoded as json  
we also no longer get the other exception as 
execution halted after this exception occurred  
which is as expected now we can look at 
the reason why this error is occurring  
we're getting an undefined array key error 
on line 38 of the product gateway class
on that line we're trying to use 
an array element that doesn't exist  
this is because we didn't send any data with 
the request so before we try and save the  
data to the database we need to validate it 
we'll do this in the product controller class  
let's add a new private method called get 
validation errors this will have one argument  
which is the array of data to validate 
and will return an array of error messages  
in the body of the method first we'll initialize 
an empty array then we'll validate the name field  
we'll keep this simple and just 
check to see if it's empty or not  
if it is we'll append an error 
message to the errors array
next we'll validate the size this is optional so 
first we'll check if a value has been supplied  
if so we'll use the filter var function with 
the integer validation filter to check that  
it's an integer if it's not this function will 
return false so we'll explicitly check for that  
the reason we check it's specifically boolean 
false and not just negate the result of the  
function call is that it could be zero which 
is still a valid value but this evaluates to  
boolean false if it's not valid we'll append 
a suitable message to the errors array finally  
at the end of the method we'll return the array 
then back in the process collection request method  
before we call the create method we'll call the 
method we just added passing in the data from  
the request and assigning the return value 
to a variable if this variable isn't empty  
then we'll output the errors as json in 
the response body and break out of this  
case block we'll also return an http status 
code of 422 which is unprocessable entity
let's give that a try now if we make a 
request with no data we get the error  
in the body of the response and a 422 status code  
if we add an invalid size to the data 
then we get the error message for that too  
if we send valid data then the record is 
created and we get the 201 status code  
so now we can make a get request to this 
collection endpoint to get a list of all products  
and a post request to create a new one there 
are other http request methods we can use for  
example delete if we make a delete request to this 
endpoint we get an empty response body with a 200  
status code we should respond differently if this 
method isn't allowed for this endpoint so let's  
add a default block to the switch statement and 
in here we'll respond with a 405 status code which  
is method not allowed when responding with this 
status code the standard requires you to include  
the methods that are allowed in an allow header 
so we'll add the call to the header function  
with an allow header specifying that get and post 
are the only methods allowed on this endpoint
now if we try an invalid method we get the 
method not allowed response and the allow  
header is included if we try a valid method such 
as get we get a successful response as expected  
that completes the processing for the collection 
request next let's process requests where the  
product id is included in the endpoint the 
first thing we need to do for these requests  
is to check that a record already exists in 
the database for the given id in the product  
gateway class let's add a new public method 
called get with a string argument for the id  
as above we'll use a prepared statement for this 
so first we'll write the sql to select the record  
from the product table using a placeholder 
for the id then we'll prepare the statement  
passing in the sql and bind the value 
of the id argument as an integer
next we'll execute it and fetch the record as 
an associative array finally in this method  
we'll return the data the fetch method will 
return an array if the record was found  
are false otherwise so we'll add the appropriate 
return type declaration to the function definition
then in the controller in the process resource 
request method we can call the get method on the  
gateway property passing in the id then for now 
let's just output the return value encoded as json
let's give that a try if we make a get request 
to the slash products slash one endpoint  
then we get the product record in 
the response body in json format  
note however that the is available column 
is an integer instead of a boolean value
in the get all method in the product gateway 
class we manually converted this column to a  
boolean value when we retrieve the data 
let's do the same in the get method so  
once we fetch the data if it isn't 
false we'll cast its value to boolean
now if we make the same request again 
the is available column is boolean  
this request worked because 
a record with an id of 1  
exists in the database if we make a request 
with an id that doesn't exist we just get false
back in the product controller 
class let's check for this  
and if the product wasn't found 
we'll respond with a 404 status code  
a suitable message in the response body and we'll 
exit from the method with a return statement
now if we make the same request 
we get the 404 not found response
next we can process the request 
based on the http request method used  
as before we'll do this with a switch 
statement on the method argument  
if the method is get we'll do what we're already 
doing which is to output the product data as json  
then we'll break from the case block we 
don't need to specify the status code as 200  
as this is the default but you can if you want to 
so if we make a get request to the endpoint for  
a product that exists we get a 200 response 
with the product data in the response body
next we'll process a request 
to update an existing record  
we'll do this with a patch request so let's add 
a patch case to the switch statement in here  
most of this will be similar to what we're doing 
down here when we insert a new record so let's  
copy this whole case block and paste it in the 
patch block the first part will be the same where  
we get the data from the request and validate 
it however instead of calling the create method  
on the gateway object we need a different method 
to update an existing record so let's add a new  
public method to the product gateway class called 
update we'll pass in the current product details  
and the new details from the request data and 
we'll return an integer which will be the number  
of rows in the database that were updated in here 
we'll add the sql to update a record identifying  
the record with a where clause for the id we'll 
prepare the statement as before passing in the sql
then we can bind values to the placeholders 
starting with the name if a new value has been  
passed in the request we'll use that otherwise 
we'll just use the existing value if the value  
hasn't changed the database will detect this and 
not update anything we'll do the same for the size  
and is available columns then we'll bind the id 
value which we get from the current product values  
and we'll execute the statement we'll 
call the row count method to set the  
return value from this method then back in the 
controller instead of calling the create method  
we call the update method we just added passing 
in the current product as the first argument  
this returns the number of rows affected so we'll 
change the name of the variable we assign this to  
accordingly for the response we'll use the 
200 status code so we can remove this call  
to the http response code function as this 
is the default for the body of the response  
we'll include the id in the message and 
return the number of rows that were affected
let's give that a try we'll send a patch request 
to the product with an id of one updating the name  
we get a successful response telling us one row 
was affected if we make a get request to the same  
endpoint then we see the name value has indeed 
been updated if we make the same patch request  
again then no rows were affected as no values 
were changed we can update all of the columns
and the validation works as before however if 
we just want to update the size for example  
then we get a validation error saying that 
the name is required the name is only required  
when we're creating a new record so we need 
to do some conditional validation on this  
in the get validation errors method we'll only 
add this validation message for the name field  
if we're creating a new record so let's add a new 
boolean argument to the method to identify if it's  
a new record or not which will default to true 
then before we check if the name value is empty  
we'll check if this variable is true then 
where we're processing the patch request  
we can pass in false as the second argument 
when we call the get validation errors method  
let's give that a try if we make 
the same patch request as before  
just passing in a value for the size now we 
get a response saying the record has been  
updated and if we view that record we can 
indeed see that the value has been changed
the final operation we want to carry out on 
a resource is to delete it so let's start  
in the process resource request method by 
adding a delete case to the switch statement  
then in the product gateway class we'll add a 
new public method called delete passing in the  
id as a string and returning an integer in the 
body of the method we'll add the sql to delete  
a record from the product table identified 
by the id we'll prepare the statement bind  
the id value to the placeholder and execute it 
finally we'll return the number of rows affected  
back in the controller we'll call this method 
on the gateway property passing in the id and  
assigning the return value to a variable for 
the body of the response we'll output a message  
the number of rows that were affected and 
we'll end the case block with a break statement
let's give that a try if we send a 
delete request to the product with  
an id of one then we get a result saying the 
product was deleted and one row was affected  
if we then try to read that resource by sending 
a get request to the same endpoint then we  
get a 404 response saying the product wasn't 
found confirming that the record was deleted  
one final thing we need to do in here is 
respond to any request that doesn't use one  
of the above methods as we did below so let's add 
a default block set the http status code to 405  
and send an allow header with the 
allowed methods of get patch and delete
so now if we send a post request for example 
to the endpoint for the product with an id  
of 2 we get the 405 method not allowed response 
including the allow header so now you know how  
to create a restful api using plain object 
oriented php and mysql we can make requests  
to list all resources to create one to show 
an individual resource update it and delete it
there's a link to all the code shown 
in this video in the description  
along with links to sites shown 
and relevant documentation  
please don't forget to like comment and 
subscribe and as always thank you for watching
