10 Years of

planet PHP - 2019-03-05(火) 16:00:00
カテゴリー: php

Hand-written service containers

planet PHP - 2019-03-04(月) 19:45:00

You say "convention over configuration;" I hear "ambient information stuck in someone's head." You say "configuration over hardcoding;" I hear "information in a different language that must be parsed, can be malformed, or not exist."

— Paul Snively (@paul_snively) March 2, 2019

Dependency injection is very important. Dependency injection containers are too. The trouble is with the tools, that let us define services in a meta-language, and rely on conventions to work well. This extra layer requires the "ambient information" Paul speaks about in his tweet, and easily lets us make mistakes that we wouldn't make if we'd just write out the code for instantiating our services.

Please consider this article to be a thought experiment. If its conclusions are convincing to you, decide for yourself if you want to make it a coding experiment as well.

The alternative: a hand-written service container

I've been using hand-written service containers for workshop projects, and it turns out that it's very nice to work with them. A hand-written service container would look like this:

final class ServiceContainer { public function finalizeInvoiceController(): FinalizeInvoiceController { return new FinalizeInvoiceController( new InvoiceService( new InvoiceRepository( $this->dbConnection() ) ) ); } private function dbConnection(): Connection { static $connection; return $connection ?: $connection = new Connection(/* ... */); } }

The router/dispatcher/controller listener, or any kind of middleware you have for processing an incoming web request, could retrieve a controller from the service container, and call its main method. Simplified, the code would look this:

$serviceContainer = new ServiceContainer(); if ($request->getUri() === '/finalize-invoice') { return $serviceContainer->finalizeInvoiceController()->__invoke($request); } // and so on

We see the power of dependency injection here: the service won't have to fetch its dependencies, it will get them injected. The controller here is a so-called "entry point" for the service container, because it's a public service that can be requested from it. All the dependencies of an entry-point service (and the dependencies of its dependencies, and so on), will be private services, which can't be fetched directly from the container.

There are many things that I like about a hand-written dependency injection container. Every one of these advantages can show how many modern service containers have to reinvent features that you already have in the programming language itself.

No service ID naming conventions

For starters, service containers usually allow you to request services using a method like get(string $id). The hand-written container doesn't have such a generic service getter. This means, you don't have to think about what the ID should be of every service you want to define. You don't have to come up with arbitrary naming conventions, and you don't have to deal with inconsistent naming schemes in a legacy single project.

The name of a service is just the name of its factory method. Choosing a service name is therefore the same as choosing a method name. But since every method in your service container is going to create and return an object of a given type, why not use that type's name as the name of the method? In fact, this is what most service containers have also started doing at some point: they recommend using the name of the class you want to instantiate.

Type-safe, with full support for static analysis

Several years ago I was looking for a way to check the quality of the Symfony service definitions that I wrote in Yaml. So I created a tool for validating service definitions created with the Symfony Dependency Injection Component. It would inspect the service definitions and find out if they had the right number constructor arguments, if the class name it referenced actually existed, etc. This tool helped me catch several issues that I would only have been able to find out by clicking through the entire web application.

Instead of doing complicated and incomplete analysis after writing service definitions

Truncated by Planet PHP, read more at the original (another 13461 bytes)

カテゴリー: php

Bulgaria PHP Conference 2019 - 2019-03-03(日) 20:37:07
カテゴリー: php

User Roles and Access Control (ACL) in Laravel

planet PHP - 2019-03-03(日) 11:37:00

It's been over a year since I covered how to protect adminpanel routes in Laravel using Gates. Some people kept reminding me about my promise to cover ACL and user roles, and I kept putting off fulfilling that promise.

Finally I run into that on one of my projects, and that's the sign I was waiting for to continue giving back to the community I learned so much from.

What is ACL

Although some computer science theorists like to throw baffling definitions of the term into people (looking at you, MSDN), in reality it's pretty simple and straightforward. ACL stands for Access Control List, and specifies what users are allowed to do.

There are three entities in the ACL:

  • User Role: e.g. admin, editor, reader
  • Object: e.g. blog post
  • Operation: create, edit, read, etc.

Continue reading
カテゴリー: php

413 Payload Too Large

planet PHP - 2019-02-27(水) 00:00:00

The 413 Payload Too Large response is used when the client sent a request with a body that’s too big.

Maybe the request was a file upload, and it exceeded the maximum file-size, or maybe it’s an API and it preemptively blocks requests that are unrealisticly large.

It’s a good idea to try and think of reasonable limits for requests, as accepting arbitrary-size HTTP requests could result in denial-of-service attacks.

If this error is temporary, a server can include a Retry-After header to indicate to the client they should just try again after a certain amount of time.

One example of a temporary status could be that the client has an upload-quota and it was exceeded.

If the reason for the error is that the server ran out of disk- space, 507 Insufficient Storage should be used instead.

Example HTTP/1.1 413 Payload Too Large Content-Type: text/html <p>This endpoint does not support requests larger than 1MB</p> HTTP/1.1 413 Payload Too Large Retry-After: 3600 Content-Type: text/html <p>You exceeded your quota. Try again in an hour</p> References
カテゴリー: php

Interview with Maintainers

planet PHP - 2019-02-26(火) 22:00:00
カテゴリー: php

In defense of the office

planet PHP - 2019-02-25(月) 05:49:00
In defense of the office

It is trendy these days to extol the virtues of remote working, and either implicitly or explicitly shame any company/manager that doesn't like it. While there are absolutely advantages to remote work or working from home, the one-sidedness of the conversation is, I believe, actively harmful. The idea of "going to work" is still a valid and useful one, and one that should not be cavalierly cast aside in Twitter snark the way it currently is.

Continue reading this post on SteemIt.

Larry 24 February 2019 - 2:49pm
カテゴリー: php

Quelques livres lus en 2018

planet PHP - 2019-02-21(木) 09:00:00
Deux mois en retard, j’ai fait le tour des livres que j’ai lus en 2019. J’en ai déjà recommandé plusieurs autour de moi et, en parcourant mes lectures de ces derniers mois, j’en ai vu d’autres dont je n’ai jamais parlé mais qui étaient tout aussi intéressants. Voici donc quelques livres que j’ai lus en 2018 et que je recommande. Why we sleep — Matthew Walker Pour commencer, Why we sleep est un livre très intéressant sur le sommeil (j’avais écrit un article à ce sujet il y a un moment, d’ailleurs).
カテゴリー: php

It depends

planet PHP - 2019-02-20(水) 22:00:00

When I was younger, I had strong opinions about many subjects. I felt I was right about a great many things, and anyone who disagreed with me was wrong. In my mind there was a right or a wrong, a black and a white, with little room for grey. Others were certainly entitled to their […]

The post It depends appeared first on

カテゴリー: php

412 Precondition Failed

planet PHP - 2019-02-20(水) 00:00:00

In HTTP it’s possible to do conditional requests. These are requests that only execute if the right conditions are met.

For GET requests, this might be done to only retrieve the resource if it has changed. For those cases 304 Not Modified is returned.

For other cases, 412 Precondition Failed is returned.


This client only wants the PUT request to succeed, if it didn’t already exit:

PUT /foo/ HTTP/1.1 Content-Type: text/markdown If-None-Match: *

This request is an update, and it should only succeed if the article hasn’t change since last time.

PUT /foo/ HTTP/1.1 If-Match: "1345-12315" Content-Type: text/markdown

If the condition didn’t pass, it returns:

HTTP/1.1 412 Precondition Failed Content-Type: text/plain The article you're tring to update has changed since you last seen it.

One great advantage of this is that prevents lost updates, due to multiple people writing to the same resource. This is also known as the ‘lost update’ problem.

Using the Prefer header, it’s possible for a client to get the current state of the resource, in case the local copy was outdated. This saves a GET request.

PUT /foo/ HTTP/1.1 If-Match: "1345-12315" Content-Type: text/markdown Prefer: return=representation ### Article version 2.1 HTTP/1.1 412 Precondition Failed Content-Type: text/markdown Etag: "4444-12345" Vary: Prefer ### Article version 3.0

This is useful, but it should probably have been designed with a HTTP/2 Push message instead. Nevertheless, there’s no harm in adopting this for legacy HTTP/1.1 systems.

カテゴリー: php

Longhorn PHP 2019 Schedule - 2019-02-15(金) 00:03:51
カテゴリー: php

When I started writing PHP...

planet PHP - 2019-02-13(水) 10:46:00
When I started writing PHP...

I don't know exactly when I started writing PHP. It was shortly after the start of my second quarter of my freshman year of college, when a newly-met friend of mine introduced me to PHP as an easier to understand alternative to Perl. That puts it, I think, somewhere in January or February of 1999.

20 years ago, give or take a week. I have been writing PHP for two decades. That's more than half my lifetime. I feel old.

I thought it would be amusing (mostly at my expense) to look back a bit on just how much the PHP world has changed in the last two decades.

Larry 12 February 2019 - 7:46pm
カテゴリー: php

411 Length Required

planet PHP - 2019-02-13(水) 00:00:00

Most HTTP requests that have a request body, will also have a Content-Length header indicating how big the body will be. However, this is optional for some cases, such as when Chunked Transfer Coding is used.

It’s useful for a client to not include a Content-Length header for a few different cases. For instance, a client might send a HTTP request body based on a stream.

If a server does not support this feature, it can indicate this by sending back 411 Length Required.

In a situation like this, a recourse a client might have is to buffer the entire request to determine the real length.

Example HTTP/1.1 411 Length Required Content-Type: text/html Server: curveball/0.6.0 <h1>This server requires a Content-Length</h1> References
カテゴリー: php

Help! My tests stopped working.

planet PHP - 2019-02-12(火) 16:00:00
カテゴリー: php

PHP.Barcelona 2019 - 2019-02-08(金) 00:22:17
カテゴリー: php

PHP 7.2.15 Released - 2019-02-07(木) 20:30:07
カテゴリー: php

PHP 7.3.2 Release Announcement - 2019-02-07(木) 20:00:19
カテゴリー: php

PHP 7.3.2 Release Announcement

planet PHP - 2019-02-07(木) 09:00:00
The PHP development team announces the immediate availability of PHP 7.3.2. This is a bugfix release, with several bug fixes included.All PHP 7.3 users are encouraged to upgrade to this version.For source downloads of PHP 7.3.2 please visit our downloads page, Windows source and binaries can be found on The list of changes is recorded in the ChangeLog.
カテゴリー: php

PHP 7.2.15 Released

planet PHP - 2019-02-07(木) 09:00:00
The PHP development team announces the immediate availability of PHP 7.2.15. This is a bugfix release.All PHP 7.2 users are encouraged to upgrade to this version.For source downloads of PHP 7.2.15 please visit our downloads page, Windows source and binaries can be found on The list of changes is recorded in the ChangeLog.
カテゴリー: php