YeenDeer softness blog (programming and electronics)

Ellie the Yeen is a soft YeenDeer that mweeoops and does programming

View on GitHub About Bots Projects Tags

LeafPHP

One thing I have not done much with PHP is looking at different frameworks. For many other languages such as Python and Java I have used quite some frameworks such as Netty, Twisted, Flask, Quart, and CherryPy. For PHP however I have not seen many at all that I have really looked into. For that reason I am looking into one that looks good called LeafPHP.

The first thing to notice about LeafPHP is that there is a router there and a hello world app might look like this

index.php

<?php
require '/home/pi/.config/composer/vendor/autoload.php';

app()->get('/', function () {
  response()->json([
    'message' => 'Welcome!'
  ]);
});

app()->run();

And what to also note is that it redirects all requests in the directory and down unless there already is a file or folder using a .htaccess file

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]

In order to stat using LeafPHP is quite simple. Just first make sure to install composer which can be done using

sudo apt install composer

but you might also want to install apache with php which can be done using

sudo apt install libapache2-mod-php

which will automatically install apache and the latest php as a module.

Now we can run a certain composer command that is

composer global require leafs/cli

which will install a command line tool that you can use to install what is needed for an app and get an example project running using the command

leaf create

keep in mind the command might not end up in path but it will end up somewhere like ~/.config/composer/vendor/bin/leaf so you can add ~/.config/composer/vendor/bin to $PATH to be able to run it with ~ expanded of course which is just a shell symbol to get the home directory for your current user.

Running that command will give you a file that looks like this index.php

<?php

require __DIR__ . '/vendor/autoload.php';

app()->get('/', function () {
        response()->page('./welcome.html');
});

app()->run();

and as you can see it will read a HTML file that looks like the image below if you do not bother running it yourself.


Welcome to Leaf 3
Documentation
Whether you are new to Leaf or have prior experience, we recommend checking out our documentation.
Documentation
Twitter
Follow Leaf PHP on Twitter to get latest news about releases, new modules, tutorials and amazing tips.
@leafphp
GitHub
All leaf projects are opensource and publicly hosted on GitHub. You can contribute or pull the code to make enhancements.
@leafsphp
YouTube
We have a youtube channel where we upload videos on leaf, our modules, frameworks and other projects.
Leaf YouTube Channel

In order to get this to show you need to either run something like leaf serve which will start a server accessible from localhost only or better use the apache php combination and have the app somewhere in the webroot or any subdirectory.

Now we are going to look at features. I have worked in the past in Flask and Quart which also has routing and as seen in the examples above it has emitting of HTML files and JSON documents.

# Emit HTML page
response()->page('./welcome.html');
# Emit JSON
response()->json([
    'message' => 'Welcome!'
]);

Just like similar frameworks it also has some handling for special routes to insert variables and such.

app()->get('/page/{page}', function ($page) {
    response()->json(['message' => "This is page $page"]);
});
# Path /1 will return the response {"message":"This is page 1"}

Which is quite elegant and having a single point handle all requests makes it easier to read the code compared to having many PHP files and makes it easy to add things like headers in one place. We need to however look at a lot of basic things that is usually done and how LeafPHP would do it.

# Handle post request taking a query string parameter
app()->post('/param', function () {
  $param = request()->get('parameter');
  response()->json(['message' => "The parameter is $param"]);
});
# Responds {"message":"The parameter is 1"} if the URL has a query string like ?parameter=1
# It will return {"message":"The parameter is "} if nothing is set

# Send plain text containing the accept header
app()->get('/headers', function () {
  $accept = request()->headers('Accept');
  response()->plain("mew the accept header is $accept");
});
# Will return something like
# mew the accept header is text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8

# Globally set a header
Leaf\Http\Headers::set(['Access-Control-Allow-Origin' => '*']);
# Header will now always have the following set on every path
# Access-Control-Allow-Origin: *

# Send raw HTML as a string
app()->get('/html', function () {
  response()->markup('This is some raw html as a string<br />Meow');
});
# Will return
# This is some raw html as a string
# Meow

# Take the raw post body
app()->post('/body', function () {
  $body = request()->body();
  response()->json($body);
});
# curl --header 'Content-Type: application/json' -d '{"a":[1,2,3]}' -X POST
# returns {"a":[1,2,3]}
# curl -d 'urlencodedparampostbody=yep' -X POST
# returns {"urlencodedparampostbody":"yep"}
# curl --header 'Content-Type: text/plain' -d 'setwitgujh4weitg=1' -X POST
# return ["setwitgujh4weitg=1"] but unsure why the array is there

So one thing that is interesting is that PHP is considered a really bad language but using frameworks like this will make it much easier to write certain things.

One thing that is convenient is regex path matching that looks like this and is harder to do without any form of framework.

# Regex path matching
app()->get('/(meo?w)', function ($meow) {
  response()->plain($meow);
});
# returns either meow or mew depending on what path you used

# Alphanumeric string 1 to 10 characters then one lowercase onle exactly 64 characters (A sha256 hash)
app()->get('/yes/([0-9a-zA-Z]{1,10})/([a-z0-9]{64})', function ($channel, $hash) {
  response()->plain("$channel $hash");
});
# Path /yes/B00ba/30f7d6673d054fc66b6984765574e44330c7aa0dede4fb64b0c502776a47bb1c
# Returns B00ba 30f7d6673d054fc66b6984765574e44330c7aa0dede4fb64b0c502776a47bb1c

# Alphanumeric strings separated by comma
app()->get('/tags/([0-9a-z,]+)', function ($tags) {
  $alltags = explode(',', $tags);
  response()->json($alltags);
});
# Path /tags/salads,meows,cats,dogs,foxes,stones
# Returns ["salads","meows","cats","dogs","foxes","stones"]

I will perhaps use this in another project as it is actually useful and a lot of useful things could be done if the quirks can be worked out and such. One example is when installing I ran into an issue where if a certain PHP extension was missing it would try to install an earlier version of LeafPHP but still the latest addon libraries which would make it try to add a newly added function called getStatic and crash but I got messaged by the creator and it was solved.

So yeah this is an interesting framework that I will look more into but I do rate it very high as it is very good except one thing that is some HTML error system that I have not managed to turn off and sometimes I would like to get JSON error messages when using cURL as the HTML response on error is extremely large.

I also have some other things to review such as SlimeVR full body VR tracking that I got sent free of charge to review and such.

*Mweeoops*

By ellietheyeen 30 September 2024 Permalink Tags: apache framework leafphp php review


Instance: