![PHP Tutorial: How to make your own PHP framework [part 1 of 2]](https://artslap.io/wp-content/uploads/2022/08/1200x628_elasticsearch-tutorial-min.jpg)
PHP Tutorial: How to make your own PHP framework [part 1 of 2]
We’ve all been there; “how does a framework work?”, “what is the purpose of a framework?” or maybe even “how […]
Read moreThis is the second part in our “How to make your own PHP framework”-tutorial. Check out the first part of the tutorial in PHP Tutorial: How to make your own PHP framework [part 1 of 2].
If you’re using Wamp or LAMP or any other application that uses Apache2, you should add an .htaccess
file, next to the index.php
, with the following contents:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php [NC,L,QSA]
The above file will ensure that any url requested, will always be processed by our index.php
, unless the requested url is an existing file.
If you’re using Nginx you can add the following code:
location / {
try_files $uri $uri/ /index.php;
}
In part 1 of the tutorial we succesfully displayed the following message:
Hoorah! We finished the first part of the tutorial!
The first thing we’ll do is add the functionality of registering new routes to our framework.
Replace the contents of the Application
addRoutes
method with the following code:
public function addRoutes(array $routes)
{
$this->routes = array_merge($this->routes, $routes);
}
The above code stores the routes we add, directly into the Application
itself in a variable named routes
. By using an array_merge
we can call $app->addRoutes
multiple times to keep adding new routes.
Now we’re going to move on to the part of checking the url to see if it matches any of our registered routes. Firstly we’re going to update our run
method to the following:
class Application
{
...
public function run()
{
try {
foreach ($this->routes as $url => $closure) {
if ($url == $this->request->getPath()) {
echo $closure->call($this, ...[$this->request]);
exit;
}
}
echo $this->render("templates/404.php", [
"request" => $this->request
]);
} catch (\Exception $exception) {
echo $this->render("templates/error.php", [
"exception" => $exception
]);
}
}
That’s a whole bunch of code, but what does it do?
$app->run()
we’re going to iterate
over each of our registered routeskey
and our closure
as the callbackurl
matches the current request urlecho
method to display our rendered templateexecuting
our closure
, we stop PHP from preventing any further code by calling exit
If for whatever reason an Exception
occurs while executing the closure
or calling the render
method, we’ll show the error that was triggered.
When running the application, you’ll probably get an exception saying Application->render
does not exist and that’s correct. So let’s move on to creating our render
method.
Under the run
method in our Application
class, add a new method called render
. This method will accept two arguments: template
and data
.
public function run()
{
...
}
public function render(string $template, array $data = [])
{
}
In this render function we want to do two things
To achieve the above we’ll want to add the following code to our Application
render
method:
public function render(string $template, array $data = [])
{
if (file_exists($template) == false) {
throw new \Exception("The template file \"{$template}\" could not be found");
}
ob_start();
extract($data);
include $template;
$contents = ob_get_contents();
ob_end_clean();
return $contents;
}
The above code looks kinda wacky, and that’s for a reason.
file_exists
function. If the template file does not exist, we throw
an Exception
ob_start()
to turn on output buffering. This will prevent PHP from immediately showing our templatedata
available for our template, we use the extract
function. This will make each variable in our data
available as a separate variable
.include
to render our templateob_get_contents()
to get the output from our include
method and store it in a variable called contents
ob_end_clean()
to let PHP resume it’s not output behaviour.Now that we have rendered our template and have the contents store in our contents
variable, we return the contents
variable.
Now we can wrap up things by creating our actual template parts. In the code we just wrote, we can see we need at least two templates, templates/error.php
and templates/404.php
You can create these two new files, by creating a folder named templates
and creating the files error.php
and 404.php
.
In the file error.php
we want to add something like this:
<html>
<head>
<title>My PHP framework! | An error occurred</title>
</head>
<body>
<h1>An error occurred</h1>
<?= $exception->getMessage() ?>
</body>
</html>
In the file 404.php
we want to add the following:
<html>
<head>
<title>My PHP framework! | Page not found</title>
</head>
<body>
<h1>Page not found</h1>
<p>The requested page "<?= $request->getPath() ?>" does not exist.</p>
</body>
</html>
In the first part of this tutorial we also added a route for /my-page
. Now is the time to create the template for it.
Create a new file in the templates
folder called my-page.php
and add:
<html>
<head>
<title>My PHP framework!</title>
</head>
<body>
<h1><?= $title ?></h1>
<?= $content ?>
</body>
</html>
Now before we test our framework, let’s add another route
for the url /my-page-with-an-error
:
$app = new Application();
$app->addRoutes([
"/my-page" => function (Request $request) {
return $this->render("templates/my-page.php", [
"title" => "I made this myself!",
"content" => "Hello from my page!"
]);
},
"/my-page-with-an-error" => function (Request $request) {
return $this->render("templates/this-template-does-not-exist.php");
}
]);
$app->run();
Now if all goes well we should be able to see the following if we navigate to /my-page
:
Very nice. Navigate to the url /my-page-with-an-error
and you should be see:
Cool and good. Now finally we want to check if the 404
page is working correctly so go to any random url, for example /404
or /asdasipojfeoifjes
or /i-should-see-a-404
and you should see:
These are the basics of any modern framework. Most frameworks are obviously a lot more complex and can have dynamic routes, middleware, database-driven templates, caching and a lot more but in essence; what we made is the basis for any framework.
Thank you for following this tutorial, we hope you liked it and learned a little more about frameworks.
We’ve all been there; “how does a framework work?”, “what is the purpose of a framework?” or maybe even “how […]
Read moreThis is a post about if statements and how to use them accordingly (depending on your language of course).
Read more
Its such as you learn my mind! You appear to grasp a lot about this, such as you wrote the guide in it or something. I feel that you simply could do with some percent to force the message house a bit, but other than that, this is excellent blog. A great read. I’ll certainly be back.
Top site ,.. amazaing post ! Just keep the work on !
Hm,.. amazing post ,.. just keep the good work on!
Top ,.. I will save your website !