Ambrosius Topor

Notiz — 2024-01-05

PHP Pro

PHP has come a long way. One can cold start with more or less ugly code (using solely functions in page scripts). One can also go professional and use all the nice features and tools that PHP has to offer to create stable, secure and maintainable projects.

I hear people talk snidely about PHP. I doubt those really know what they are talking about, only having seen those naive page scripts. Ignoring that meanwhile—among several other things—there are security features like an attribute which allows to hide sensitive data from exceptions.

How people think PHP has to look like:

<html>
<?php
$con = mysqli_connect("localhost","my_user","my_password","my_db");
$sql = "SELECT lastname, age FROM persons WHERE lastname LIKE '%" . $_GET["lastname"]. "%' ORDER BY lastname";
$res = mysqli_query($con, $sql);
$persons = mysqli_fetch_all($res);
?>
<body>
<?php
foreach ($persons as $person) {
    echo $person[0] . " " . $person[1];
}
?>
</body>
</html>

Already around 1999/2000, when I intensively explored Java, I made the prediction that strong typing (type hints) will make its way to other languages like PHP.
Meanwhile I can see I was right: ActionScript (as part of the ECMAScript family) came up with types, possibly influencing the advent of TypeScript; and PHP's typing system is getting more and more capabilities.

How PHP can actually look like:

<?php
declare(strict_types=1);

namespace App\Commands\Page;

use Exception;
use InvalidArgumentException;
use Respect\Validation\Validator as v;
use Core\Commands\Command;
use App\Traits\JsonDataLoaderTrait;
use App\Models\Page;

class QueryCommand extends Command
{
    use JsonDataLoaderTrait;
    use QueryCommandHomePageTrait;

    public const NAME = 'query_page';
    public const ENTITY_TYPE = 'Page';

    private ?Page $page = null;

    private function getPageByPath(string $path): ?Page
    {
        if ($path === '') {
            $path = '/';
        }
        try {
            return $this->container->get('pageStore')->byPath($path);
        } catch (Exception $exception) {
            return null;
        }
    }
}
<?php
declare(strict_types=1);

namespace Http\Controllers;

use Exception;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use Ambrosius\JsonRpc\Response as JsonRpcResponse;
use Http\Controller;
use Compositor\PageBuilder;
use Compositor\Page;

class PageController extends Controller
{
    #[\Override]
    public function handle(Request $request, Response $response, array $args = []): Response
    {
        $pageBuilder = new PageBuilder($this->container);

        try {
            $page = $this->getPageByPath('/' . $this->getPlaceholder($args, 'path', ''));
        } catch (Exception $exception) {
            return $this->container->get('notFoundHandler')($request, $response);
        }

        $html = $pageBuilder->build($page);

        $body = $response->getBody();
        $body->write($html);

        return $response->withBody($body);
    }

Standards: PHP-FIG, Composer

Adhere to standards makes it easier to develop; following coding styles (PSR-12Fn), using commonly accepted interfaces (e.g. PSR-7, PSR-15Fn) puts away unnecessary thoughts and lets you focus on the real tasks. Besides using your IDE to ensure code style, you can run the PHP Coding Standards FixerFn.
Using ComposerFn has long time ago been established; there is no need to either write your own autoloaders, nor the need to implement everything yourself—there is certainly a packageFn for that.

Assuring Code Quality, Testing, Security

When it comes to assuring the functionality of your code, several tools are available. For (automated) testing, PHPUnitFn has become the go-to testing framework. It's quick to start with simple, while offering you quite a lot of options to check your code. Data providers help you to test with data variations, while keeping your test code base short. In combination with Xdebug, you can have detailed code coverage reports and code complexity metrics.

For static code testing, there is PHPStanFn. You can start with a low level (1) and go all the way up (9) when you want to be really strict.

Besides a ton of tests (unit, integration, e2e) I also have a tool of mine in use which will scan the code base and check for differences (using an hashing algorithm), making sure no part has been tampered.

Frameworks

Guess the usual candidates are well-known: Symfony, Laravel, Yii, CakePHP. For my projects (which are quite API centric and don't need much), I've decided to go with the Slim frameworkFn, while lending some ideas from the other solutions. Besides being focused, concise, still flexible, what I like about it is that it is following standards (PSR-7: HTTP Message Interface, PSR-11: Container Interface, PSR-15: HTTP Handlers). Request, response, routing, middleware are the concepts that make a solid base.

References

Comments

There are no comments yet.

Thanks for your contribution!
Your comment will be visible once it has been approved.

An error occured—please try again.

Add Comment