DEV Community

Cover image for My PHP Toolkit to Build a (quite) Frameworkless App

My PHP Toolkit to Build a (quite) Frameworkless App

Boris Jamot ✊ / on January 22, 2019

Hey, let me introduce you some of the libraries & tools I've been using in many PHP projects running in production. I'm used to build my own f...
Collapse
 
biros profile image
Boris Jamot ✊ /

I'm used to build small to medium apps with something like 50kLoC.
I have no specific strategy so I usually end up with big routes files.
As you may know, Slim routes take a closure to handle the request and give the response:

$app = new \Slim\App();
$app->any('/books/[{id}]', function ($request, $response, $args) {
    // do the stuff here
});

Instead of having a big routes file, we have the possibility to define a controller class and to pass it to the \Slim\App:

$app = new \Slim\App();
$app->any('/books', BookController::class);

I never tried that but it's well described in the official doc.

Collapse
 
hsemix profile image
Hamid Semix

You could install a DI container and do something like this

 $app->get('/books', 'BookController@getBooks');
Collapse
 
kip13 profile image
kip

Good libraries/tools/complements to work in a PHP project !

You said this

I use no ORM and I mainly build backend apps with Web APIs.

Could you explain me how you manage in an API a dynamic filter with a resource that have relation with othe(s) table(s) ?

I would like to recommend this tools too:

thephpleague / fractal

Output complex, flexible, AJAX/RESTful data structures.

Fractal

Latest Version Software License Build Status Coverage Status Quality Score Total Downloads

Fractal provides a presentation and transformation layer for complex data output, the like found in RESTful APIs, and works really well with JSON. Think of this as a view layer for your JSON/YAML/etc.

When building an API it is common for people to just grab stuff from the database and pass it to json_encode(). This might be passable for "trivial" APIs but if they are in use by the public or used by mobile applications then this will quickly lead to inconsistent output.

Goals

  • Create a protective shield between source data and output, so schema changes do not affect users
  • Systematic type-casting of data, to avoid foreach()ing through and (bool)ing everything
  • Include (a.k.a embedding, nesting or side-loading) relationships for complex data structures
  • Work with standards like HAL and JSON-API but also allow custom serialization
  • Support the pagination of data results, for small and large data sets…

thephpleague / flysystem

Abstraction for local and remote filesystems

League\Flysystem

Author Build Status Coverage Status Quality Score Software License Packagist Version Total Downloads Build status

SensioLabsInsight

Flysystem is a filesystem abstraction which allows you to easily swap out a local filesystem for a remote one.

Become a Patron

Goals

  • Have a generic API for handling common tasks across multiple file storage engines.
  • Have consistent output which you can rely on.
  • Integrate well with other packages/frameworks.
  • Be cacheable.
  • Emulate directories in systems that don't support them, like AwsS3.
  • Support third party plugins.
  • Make it easy to test your filesystem interactions.
  • Support streams for big file handling.

Installation

composer require league/flysystem

Documentation

Check out the documentation

Community Integrations

Want to get started quickly? Check out some of these integrations:

Adapters

Core

  • Ftp
  • Local
  • NullAdapter

Officially Supported

violet-php / streaming-json-encoder

PHP library for iteratively encoding large JSON documents piece by piece

Streaming JSON Encoder

Streaming JSON Encoder is a PHP library that provides a set of classes to help with encoding JSON in a streaming manner, i.e. allowing you to encode the JSON document bit by bit rather than encoding the whole document at once. Compared to the built in json_encode function, there are two main advantages:

  • You will not need to load the entire data set into memory, as the encoder supports iterating over both arrays and any kind of iterators, like generators, for example.
  • You will not need to load the entire resulting JSON document into the memory, since the JSON document will be encoded value by value and it's possible to output the encoded document piece by piece.

In other words, the Streaming JSON Encoder can provide the greatest benefit when you need to handle large data sets that may otherwise take up too much memory to process.

nikic / iter

Iteration primitives using generators

Iteration primitives using generators

This library implements iteration primitives like map() and filter() using generators. To a large part this serves as a repository for small examples of generator usage, but of course the functions are also practically quite useful.

All functions in this library accept arbitrary iterables, i.e. arrays traversables, iterators and aggregates, which makes it quite different from functions like array_map() (which only accept arrays) and the SPL iterators (which usually only accept iterators, not even aggregates). The operations are of course lazy.

Install

To install with composer:

composer require nikic/iter

Functionality

A small usage example for the map() and range() functions:

<?php
use iter\fn;
require 'path/to/vendor/autoload.php';

$nums = iter\range(1, 10);
$numsTimesTen = iter\map(fn\operator('*', 10), $nums);
// => iter(10, 20, 30, 40, 50, 60, 70, 80, 90, 100)

You can find…

thecodingmachine / safe

All PHP functions, rewritten to throw exceptions instead of returning false

Latest Stable Version Total Downloads Latest Unstable Version License Build Status Coverage Status

Safe PHP

Work in progress

A set of core PHP functions rewritten to throw exceptions instead of returning false when an error is encountered.

The problem

Most PHP core functions were written before exception handling was added to the language. Therefore, most PHP functions do not throw exceptions. Instead, they return false in case of error.

But most of us are too lazy to check explicitly for every single return of every core PHP function.

// This code is incorrect. Twice.
// "file_get_contents" can return false if the file does not exists
// "json_decode" can return false if the file content is not valid JSON
$content = file_get_contents('foobar.json');
$foobar = json_decode($content);

The correct version of this code would be:

$content = file_get_contents('foobar.json');
if ($content === false) {
    throw new FileLoadingException('Could not load

paragonie / easydb

Easy-to-use PDO wrapper for PHP projects.

EasyDB - Simple Database Abstraction Layer

Build Status Latest Stable Version Latest Unstable Version License Downloads

PDO lacks brevity and simplicity; EasyDB makes separating data from instructions easy (and aesthetically pleasing).

EasyDB was created by Paragon Initiative Enterprises as part of our effort to encourage better application security practices.

Check out our other open source projects too.

If you're looking for a full-fledged query builder, check out Latitude and Aura.SqlQuery which can be used with EasyDB.

If you'd like to use EasyDB but cache prepared statements in memory for multiple queries (i.e. to reduce database round-trips), check out our EasyDB-Cache wrapper class.

Installing EasyDB

First, get Composer, if you don't already use it.

Next, run the following command:

/path/to/your/local/composer.phar require paragonie/easydb:^2

If you've installed Composer in /usr/bin, you can replace /path/to/your/local/composer.phar with just composer.

Why Use EasyDB? Because it's cleaner!

Let's refactor a dangerous PHP snippet that previously used string concatenation to pass user input instead…

Collapse
 
biros profile image
Boris Jamot ✊ /

I didn't know these libs and it sounds great.
I know that thephpleague do a great job for PHP.

Regarding the ORM, I don't use it and I prefer building the SQL queries by myself. I use a mapper layer for that which is responsible for the DTO stuff. When several tables are required, I just use a JOIN statement.
It's not ideal but even with ORM, I don't see any clean way to do that.
The problem is with REST. I have to give a chance to GraphQL 😉

Collapse
 
david_j_eddy profile image
David J Eddy

Great list Boris! While I knew many of these it is good to see some I was not aware of. Would you have time to checkout a little library I put together?

davidjeddy / normie

Wrapper library that provides normalized function interfaces for the PHP standard library.

Normie

Badges

Build Status License codecov

Latest Stable Version Latest Unstable Version composer.lock

Scrutinizer Code Quality Build Status Code Coverage Code Intelligence Status

Monthly Downloads Daily Downloads Total Downloads

Contributors

Description

Normie (short for Normalizer) attempts to make using the PHP Standard Library (SPL) function calls more consistent by implementing a norm_{function name}() wrapper function declarations. This library DOES NOT over ride the SPL functions in any way.

Examples

Function parameter order examples.

Arrays fn()

Normie array functions follow the 'array source X, operator Y (callback,key, needle, etc), other parameters are Z' mentality. The complete list of array functions are viewable here.

SPL: array array_map ( callable $callback, array $arr1, array $_ = null) { }

Normie: array norm_array_map( array $array, callable $callback, array $userdata = null): array

Strings fn()

Normie string functions follow the 'Search X string or Y target, replace with Z string' mentality. The complete list of string functions are viewable here.

SPL: array explode ( string $delimiter , string $string [, int $limit = PHP_INT_MAX ] )

Collapse
 
biros profile image
Boris Jamot ✊ /

Hi David,

I don't use the SPL that much and honestly, its lack of consistency doesn't bother me.
I hope PHP8 will move this in the right way.

Anyway, you made a great job for the community by providing this library.

Collapse
 
marconicolodi profile image
Marco Nicolodi

Lean & Elegant