18

I just read the Twelve-Factor App, which looks like a pretty comprehensive set of rules to apply in a web-based application. It uses python or rails in its examples, but never php... I was wondering which factors of the manifesto can be applied to PHP projects and how?

Thanks

Naoise Golden
  • 8,793
  • 4
  • 49
  • 65

4 Answers4

17

Short answer:

All points apply to PHP as the twelve factor app manifesto refers specifically for web apps.

PHP has a very hard time complying to twelve factor, in particular in the items 2, 7, 8 9 (as a side effect of 7 and 8) and 12 (partially). Actually that's the first really grounded argument I have heard in the whole "PHP sucks" rant that is common on the Ruby and Python communities (don't get me wrong, I think Ruby and Python are better languages, but I don't hate PHP, and definitively hate the "my language is better" rants.)

Being that said, it may be that your PHP project is not a web app or SaaS, but just a simple website, so you may just deem that twelve factor is not a need.

Long answer: A point-by-point analysis would be:

  1. Codebase: not an issue

  2. Dependencies: the way PEAR works goes quite against this point, as pear dependencies are installed system wide and usually you don't have a consolidated manifesto to declare them. Is also usual for a PHP setup to require you to add packages to your OS installation to get some libraries available. Finally AFAIK there isn't a tool in PHP to provide isolation like "virtualenv", "rbenv" or "rvm" (or if it exists is not popular among the PHP community) Edit: Composer (http://getcomposer.org/) seems to do the right regarding dependencies, it still doesn't isolate the PHP version, but for all the rest it should be fine.

  3. Config: some PHP frameworks are not very well suited to do this, but there are certainly others that do well, so it's not a flaw of the platform itself

  4. Backing Services: shouldn't be much of an issue, despite maybe having to hack some frameworks a little in order to manage the services as resources

  5. Build, release, run: this is totally appliable to PHP as this definitively doesn't concern only "compiling". One may argue that several projects and hosting platforms on the PHP community abuse of direct FTP, etc. but that's not a flaw of PHP itself, and there is no real impediment on doing things right regarding this item.

  6. Processes: This definitively concerns to PHP. PHP is quite capable of running purely stateless processes (the emphasis is on the word stateless), and actually several frameworks make your life easy for it. For example, symfony provides out-of-the-box session management with memcached or database storage instead of regular sessions

  7. Port binding: Over simplyfing it, this point basically demands you to reverse proxy and have the actual webserver embedded on the app instead of being a separated component. This puts PHP in a very hard position to comply. Despite there are ways to do this (see the reply about using PHP as FastCGI) that's definitively not the most common nor the best supported way to serve a PHP app as it is on other communities (e.g. Ruby, Node.js).

  8. Processes: This is not impossible in PHP. However several elements put PHP in a hard position to comply. Namely the lack of good support for items 6 and 7; the fact that the PHP API to spawn new processes isn't really very nice to work with; and specially the way Apache's mod_php handles their workers (which is by far the most common deployment schema for PHP)

  9. Disposability: If you use the right tools there is nothing inherent on PHP to prevent you from creating fast, disposable, tidy web and worker processes. However I believe that since the underlying process model is hard to implement as per points 7 and 8, then 9 becomes a bit cumbersome as a side effect

  10. Dev/prod parity: This is very platform agnostic, and I would say one of the hardest to get done right. PHP is no exception to this rule, but it doesn't have a particular impediment either. Actually most of the tools named on the manifesto can be applied to a PHP project

  11. Logs: Having your app agnostic of the log system on the execution environment is totally doable on PHP

  12. Admin processes: The most important flaw of PHP regarding this point is its lack of a REPL shell. Regarding the rest, several frameworks like Symfony allow you to program admin tasks (e.g Doctine-based database migrations) and run them on the same environment as your "regular" web envionrment.

Since the PHP community is evolving, it may be that it has already righted some of the wrongs mentioned.

pjmorse
  • 9,204
  • 9
  • 54
  • 124
  • I find following logging directives of twelve step with php a bit tricky. They say you should just dump you logs to `stdout` but it's usually apache (or something) that consumes php's. Getting the working environment handle it could be tricky. Most people would prefer at leas dumping the logs to file and let the environment take over from there. – toraman Sep 03 '19 at 16:03
  • Regarding item 12. note that there exists a very good PHP REPL, psysh available at https://psysh.org/ Some frameworks like Drupal wrap it in their own REPL (e.g. Drush) for more features. – FGM Apr 10 '23 at 10:18
3

Build, release, Run: Applicable to compiled code which is not the case in PHP. So this point is not something you need to look at.

I don't claim any authority on this 12 factor stuff, but my read of that section is that the author would disagree. It's not just about compiling, it's about managing dependencies both in the small (the snapshot of the code) and in the large (any libraries the code uses).

Imagine you're a new dev and they say, "Okay, this is a custom php app, so...

a) The custom code is really two subprojects, which are in repo A and repo B.

b) You'll need to create a directory layout like so, and then

c) check the code for each subproject out into this subdirectory and this subdirectory.

d) You'll also need these three open source PHP libraries:

version 3.1 of library Foo, version 2.3 of library Bar, and version 5.6 of library Bat.

e) download them from their home project sites and unpack them, then copy them into this directory, that directory, and the other directory.

f) then you'll need to set these configurations in the external library,

g) and these configs in our two custom code projects.

h) once that's all done, tar/gzip it all up, upload it up to the QA server and untar it into htdocs.

There's no compiling going in that set of steps, but you can bet there's a lot of building.

Getting all of that set up and working is the build step.

Using tar/gzip to take a snapshot of the working build is the release step.

SCP'ing/unpacking it into the QA server's htdocs directory is the runtime step.

You might say that some of those steps above are unnecessary - the libraries should be deployed at the system level and merely imported. From the 12factors.net site I'd say the author prefers you to import them uniquely and individually for the app. It sidesteps dependency versioning problems at the cost of more disk space (not that anybody cares). There are more hassles in managing all those dependencies as local-to-the-app, but then that's the point of the build/release/runtime scheme.

  • Hmm I'd say SCP and unpacking is still the release step. The runtime step is more "what happens while the app is running" IMO. – Jerome Baum Oct 19 '12 at 06:23
2

It might have changed since you read it - there are a few PHP examples now, although a few of them seem like negations of the twelve-factor concept.

One of the ways that normal mod_php sites violate twelve-factor comes with VII. Port binding. From the manifesto:

The twelve-factor app is completely self-contained and does not rely on runtime injection of a webserver into the execution environment to create a web-facing service. The web app exports HTTP as a service by binding to a port, and listening to requests coming in on that port.

However, apache/php can be coaxed into this worldview with something like this:

https://gist.github.com/1398498

Not perfect, but it works for the most part. To test it out, install foreman:

gem install foreman

then run it in the directory you cloned the gist into:

foreman start

then visit

http://localhost:5000/foo

Erik Kastner
  • 171
  • 1
  • 6
-2

DO NOT TAKE THIS POST AS A REFERENCE, THIS WAS WRITTEN IN 2011, MANY THINGS HAVE CHANGED SINCE THEN... THE WORLD OF PROGRAMMING IS IN CONSTANT EVOLUTION. A POINT OF VIEW OF 2011 IS NOT NECESSARILY STILL VALID IN 2018.


I just read a few lines of each points and here goes my analysis of the document:

  1. Codebase: Everyone, php or not should have a codebase even for the little projects

  2. Dependecies: PHP uses includes and code libraries that you should always be able to port easily by simply copying the code to a server. Sometimes you use PEAR and then if the server doesn't support it, you have to copy and install pear manually. I use Zend Framework most of the time, so it's just copying the code of the framework with the ftp upload.

  3. Config: It is common for php apps to have a writable config file that you store configurations into. Where you store it is your choice as a developer, but it is usually either at the root of your app or in a settings/config folder.

  4. Backing Services: PHP does use backing service most of the time such as MySQL. Other common services depending on your app are twitter and facebook. You use their API to communicate with them and store/retrieve data to work with.

  5. Build, release, Run: Applicable to compiled code which is not the case in PHP. So this point is not something you need to look at.

  6. Processes: HTTP is stateless and is SERVED,thus, you usually have no process apart from the web server. This is not entirely true as a webservice may be bundled with applications you package with or create for it. But, for the sake of standards, you usually don't have to use processes in the web world.

  7. Port binding: PHP doesn't apply to port binding at all because it is not a process that hooks to an address, Apache, NGinx or Lighttpd does that for you. Reading #6/7 makes me understand that a website could never be a Twelve-Factor app.

  8. Concurrency: Again this point treats about processes which do not apply to PHP web pages. This point applies to the server serving the content.

  9. Disposability: This point discusses about how fast a process should be. Obviously, PHP web sites not being a process shouldnt apply but always note that your website should execute pages as fast as possible... Always think about this block or that block of code and see if it is optimized.

  10. Dev/Prod Parity: This point is crucial in any app development. You never want to have a large gap between two app versions or upgrading can become a hassle. Furthermore, never create client specific versions of an app. Always find ways to allow your app to be configured/customized at the template level so you can keep your app as close as possible to all installed versions everywhere.

  11. Logs: Logs are always a good thing to have, they allow you to follow the process of your code without having to output it to screen. My favorite tactic is to "tail -f logfile" inside of a linux console and look at what is happening as i execute my code.

  12. Admin processes: Not applicable, in php, you don't have processes, but you do have pages that you can secure with usernames and passwords.

Mathieu Dumoulin
  • 12,126
  • 7
  • 43
  • 71
  • Could you re-format it for better readability? Great thourough answer. – Naoise Golden Dec 22 '11 at 12:53
  • 1
    Some of the answers make it clear that the Mathieu didn't read the article to understanding. For example: "Reading #6/7 makes me understand that a website could never be a Twelve-Factor app." That isn't true, they're saying the web server should be part of the app... – Jeremy Logan Apr 16 '12 at 14:46
  • 1
    Your answer to #5 is poor advice. Web applications should definitely have a build, release, run process. – Travis Jul 23 '12 at 06:10
  • 1
    For #7 Port Binding. If you are running mod_php in Apache, it doesn't make sense. However, if you use PHP as a FastCGI (e.g. [PHP-FPM](http://php-fpm.org/)) You can bind PHP-FPM to a port like `localhost:9000`. In this instance, Apache or Nginx just forwards PHP requests to that PHP-FPM instance. – Shane Stillwell Sep 28 '12 at 16:18
  • Why does calling the answer to #5 "poor advice" make it so? Do you have a plausible argument? – Jay Godse Mar 05 '13 at 05:48
  • I wrote that 7 years ago, please do not use this post as a reference... The world of coding evolves a lot and this is not necessarily true anymore... – Mathieu Dumoulin Feb 08 '18 at 14:38