While it's good in some respects, all this enterprisization is exhausting and can, perversely - counter to its intentions, be a significant drain on productivity. Once upon a time, we were focused on the important things - problem-solving, domain data, and business logic. But now we're almost entirely focused on abstraction, generics, and boilerplate while the important objective-related stuff that pays the bills just gets whatever scraps of time are leftover (if any).
We used to spend 90% of our time determining the right nail to use, the right wood to use it on, and where best to place it, and only 10% of our time on selecting and wielding the hammer. Now we spend 90+% of our time figuring out which GenericAbstractToolFactoryManagerFactoryInterface to invoke and how to properly invoke it a in such a way as to coerce it to ultimately generate something that eventually might generate something else that will hopefully drive some sort of fastener into something in such a way that will possibly hold it together, and the rest debugging why instead it is generating a generator that generates chisels that are chopping away at the foundation.
Yes, that's an exaggeration, but how much so? We are smart people, we do figure out how to use these complex combinations of systems to build functioning (bloated monstrosities of) applications. But are they really reducing technical debt or adding to it?
Are these systems really going to be easier to maintain in a few years when they have 357 dependencies that have each evolved over time (and or been abandoned)? Easier to optimize, when that means modifying what's going on under the hood of those dependencies? Easier to extend, when doing so would lead to conflicts with those dependencies?
I'm predicting that the next wave of discovery and hype in the field will be focused on improving productivity while reducing technical debt by removing the cruft that we're building now and replacing it with something simpler and more to-the-point.
In my current job I inherited a 7 years old php project that's marked as legacy and scheduled to be phased out in 2020. Until then its mostly maintenance and adaptions to changes in stuff it interacts with.
It's built with php5, uses pretty static file structure, no namespaces but an autoloader. It has around 150 source files. I must say that it was surprisingly easy to get into the code base. The fact that there are no namespaces means class names have been picked carefully, no generic stuff like "dataholder". About half the classes are entirely static and there is still a lot of assoc arrays being passed around while in other places proper classes are used. The front end is just bootstrap with a little bit of additional js and ajax where it makes sense. Still it is really easy navigating the code base and finding the right spot to extend. I hardly ever felt constrained by the project's design, if ever rather by the inconsistencies of php(5) itself. Yes, sometimes it's annoying to implement a dynamic page update via ajax by hand without fancy abstraction, but if you're not building a modern spa it's not that bad and you actually get what's going on.
That other java code base I'm involved with is about 4 years old and really modular and fancy and maven and every time something needs to be added a discussion starts on how to do it, which parts to abstract away in which way, which library or framework might be suited best, and after five trillion years coding might actually start. I might have exaggerated a bit here but that's somehow the feeling I have more and more in modern software development.
Boom. You can stop here. This has nothing to do with PHP or your project.
It's just the previous devs were good professionals. This is why "it's easy to navigate and extend".
Proper naming is one of the most important tell of a code work well done. You got lucky.
But a (good) framework will enforce a reasonable structure that will drive even less skilled professionals in a unperfect but sane direction. It's still possible to take bad decisions, but less often, and the cost of it is reduced.
Came here to say something similar. Not sure if you were downvoted or what, but I've inherited projects with function names like "runFunc()" and "doit()" which then have 18 global variables imported, then 1000+ lines of "if(foo=='j' && (barfoo!='f' && foo_old2=='ff') || 7) { // do j stuff v3".
You did indeed have a more professional set of folks developing that.
I just inherited a small PHP project written 2 years ago:
* no version control
* running as root on apache 2.2 in /var/www/html
* php 5.5
* about 12 "pages" each with a healthy mix of html/php ('header/footer' are abstracted to external incudes)
the problem with the 12 "pages" is there's around more than double the logic states and I need to add more. there's a bunch of
interspersed all over the place. Do I continue the pattern? Or refactor? The previous developer would add 'new' stuff in a matter of a few hours, because they'd just expand on that pattern; it's now unwieldy, and I need to add 'new' stuff, and expectations are "a few hours".
FWIW, it's probably what I'll do, but am migrating code in to version control, adding items in an issue tracker, and documenting my concerns in tickets, a README, and some code comments. It may come across as a bit passive-agressive, but it's not meant to; just trying to keep a history of concerns while also hitting their short deadline.
Don't worry about the possible "passive aggressive" interpretation. You are doing the best that can be done in your position. If they don't see it... well, that's their problem, not yours. You are already being more than enough accommodating by just accepting to work on such a mess of a project!
Imho because the poster says: it is possible to have maintainable code without entreprization and the comment says: "that just due to good developers". Which is exactly the point of the post: you don't need entreprization if you follow the basic simple rules.
Yeah but you see, "entreprization" can help less skilled developers to stay on track and produce maintenable software.
It's the difference between flask and django in the Python world.
Beginners tend to go for flask. It seems easier.
But I actually always recommend Django to beginners, and only flask to experts.
Why ?
Well, because I've worked on a lot of code bases with both django and flask, and when you don't have good devs, the result with flask is disastrous. Indeed, flask delegates a lot of decisions to the dev, and as a result, if you don't know what you are doing, the project ends up with bad structure and terrible security.
E.G: django out of the box rotates your session key, provides csrf token, and en entire auth system. But I've worked last year on a flask project that used unsalted md5 password hashes. Their auth backend returned 403 for most errors in the authentication process, even for bugs, with unrelated 3 words messages.
The thing is, if your project is not a success, you don't care. But the goal of a project is being successful, and if it is, less skilled devs will probably have to work on it.
Hell, most projects don't even start with skilled devs. The reason is simple: there are too much demand for tech, and not enough devs. So we do with what we have. I mean, I have companies in the silicon valley paying a lot of money for me to work from my bedroom in France because they can't hire the expert they need around them anymore.
And when I arrive on a new project, guess what happens ? If it's a framework I know, I can start working on it from day one. If it's not, I'll need time to adjust. It's it's custom, I'll need more time, in direct correlation with the skill level of the other devs that worked on it.
Completely agree with you, basic php is really straightforward: one webpage = one php file. Nothing fancy. Basic Java is 1k layers of abstraction. That's why people tend to learn php on their own and java in school.
That's exactly what Ruby on Rails seemed like it was about to do ten years ago. But it was followed up by a counter-revolution that took us even further into enterprise bloat. It's as if there are hidden psychosocial forces that drive web developers in the direction of more complexity.
I think a vast majority of people in general, and developers especially, equate complexity with quality. And even when they realize that the inverse is true they don’t take the time to reduce that complexity.
I have to disagree with you here regarding "enterprisization". Having worked in multiple large Java code bases leveraging multiple DI frameworks (Spring, Guice, and Dagger), I've definitely seen both sides of the argument first hand. I'm targeting DI specifically here, because it is most often complained about when talking about "enterprise" software. What I've learned is that proper use of DI is hugely beneficial in large code bases. Where things really break down is when the code base suffers from a lack of philosophy. The biggest issue with DI is that it is very easy to abuse, but these abuses have very specific patterns and can easily be avoided by applying a principled approach to development.
Regarding the beauty of DI, let me provide an example of a typical large application. Such an application may need a UserInfo class to model a user's information in the app. This user info class will likely have many dependencies: it needs a way to persist itself to disk, to make network calls for server syncs, and any other ancillary components. As an app component, I don't need to understand any of this. I just add a component to my constructor and I immediately have access to any functionality I may need. Using DI in this way also has a nice side effect: classes can be stateless singletons and still be easily testable with mocks. And the best part is none of this is magical. All of it is governed by a few simple rules.
I worried that PHP would go too much 'pro' when they started consolidating things. But I thought they wouldn't reach JavaEE levels of fluff.. since most PHPers were more into pragmatics than hyperstructure.
Modern Java EE is actually really simple and lightweight. (My background is mostly php, later Java, all the time with some other languages like python w/flask, javascript etc in between.)
I started a startup in 2013, and I picked PHP for a core language since I had a decade~ experience with it by then and it was a good enough reason to use it. PHP 7 wasn't available yet and nodejs was only starting to take off and didn't seem like the future yet.
Taking learning from previous companies, I've found the main thing PHP was lacking at the time was a good routing mechanism. We obviously don't want to rely on Apache hitting .php files to handle requests. So we used ToroPHP (https://github.com/anandkunal/ToroPHP) for routing, which is a seriously lightweight routing lib. Indeed we used composer and a lot of dependencies, but for our own codebase we used manual includes instead of the autoloader. With the usual PHP production setup like APC with opcode caching enabled and file stat'ing off (later on opcache + APCu), we handled scale extremely well. (mentioning this because a counter-point for manual includes is that many requests would unnecessarily load way too many code files)
As far as codebase maintenance and growth go, that PHP codebase was actually very easily manageable even with manual includes. Having routing solved frees you up to organize your code files in any ways you want. Even today, I have a mini-framework structured this way for myself to start side projects and test ideas with. (Yes, using PHP5 for side projects in 2018 ;)
My point in bringing all this up is that the architecture this article is trying to take you in, seems unnecessarily complicated for PHP.
This past year I've been working in a full nodejs shop and this entire architecture (from this article) reminds me heavily of how a node/express app is structured. Someone else on this thread mentioned modern languages have their architectures converging. This is exactly what's happening. Even as a PHP fan, it makes me feel a bit of "Why use PHP at this point, instead of nodejs/go/python?" while reading this. It feels like if you wanted to go this route, nodejs is a better option on almost all fronts -- language syntax brevity, availability of packages, community, developer-availability. The only reason to use PHP at this point is nostalgia/sticking to PHP syntax.
The reason to use PHP over JS/Python or Ruby is that PHP supports strict typing and that makes code both more maintainable, understandable (Find Usage feature only works reliably when types are inferrable which is not always the case in those other theee langs) and refactorable.
Now the reason to use PHP over Java or Go is that PHP at this point has a type system that’s on par with Go’s but at the same time it gives you an advantage of fast development process thanks to the lack of need for compilation and/or restarting the container after each change in the code. I’m currently working with Java and before that I had a long experience of PHP, while I personally would choose Java over PHP almost in any case because I value type system features perhaps a bit too much, but I do suffer from those slow turnaround times (compile/restart TomCat) and I can see how it could potentially be bad for the business at early stages especially.
So the bottom line is PHP at this point has a nice balance which is hard to find atm in any other popular languages with evolved ecosystem
As someone who's been doing PHP for nearly 15 years, but 2 years ago switched to Node.js for a job, I agree. This is even more true when switching to Typescript.
We introduced typing later in the project and wow what a step up in safety and productivity.
I've been part of teams that pride themselves on using propel + klein to build an app in a non-framework.
If you want a light framework just go with lumen, flask, sinatra. Ymmv.
All new devs wasted a lot of hours learning propel and klein and it didn't always do what they wanted/needed, and the code wasn't the prettiest, where as most knew laravel, and longed for the comfort/sanity of coding in laravel.
Sure, for a hobby project/side project this is a good practice to become a better dev, and understand how a mvc framework is built, but for a large code/team it's best to go with something established so new devs hit the ground running without having to learn a ton of stuff.
It's easier to find a 'laravel dev', than it is to find a 'custom built mvc dev with extensive experience in x, y, z packages'.
I've worked in countless languages and used plenty of frameworks (and done a ton of PHP development) but I really don't understand Laravel.
You have to do a big dance of putting files in all right places and implementing all the right interfaces -- as you would with any framework -- but Laravel doesn't seem to give you anything for your trouble. Take, as one example, validation -- you still have to write virtually everything yourself! There are some very basic hooks and some wire but that's all. For all the trouble, I expect more actual features from my framework.
Putting files in the right places? You can technically put them anywhere you like, and just use proper namespacing.
For example laravel defaults to App/ for models.. so App\User which is ugly if you have 50 models. I ALWAYS use App\Models\User instead, so I move it to the App\Models folder, put all my other models there and presto, chango.
The opinionated flavour makes a lot more sense in a large team - I can pickup a Laravel App, and if it has followed convention, run composer install and be productive within a matter of minutes.
You don't have to do everything yourself, most things are abstracted and easily accessible.
It's a framework, it's job is to make it easy to structure the site and handle common tasks for you. Laravel does have validation built in. You might have to put custom rules to use every now or then, but I don't see a way around that.
But laravel sure has its cost when it comes to performance - it's not possible to have it both ways.
Laravel has a weird validation abstraction but you still have to do all the work. I'm used to being able to define my model have all my validation rules derived automatically (so I'm not repeating myself everywhere) and displayed automatically. Laravel just makes you learn a whole bunch of new conventions and functions but you still have to do it all yourself.
I don't see the value of:
validate('title' => 'required');
vs.
if (empty('title')) $errors[] = 'Title is required.'
Especially when this happens at the controller level.
To be fair, validation at the controller level is recommended only for simple cases. See form request validation [1] for more complex situations that require better code decoupling.
That being said... yes, the validation system is lacking. For instance, there's no built-in way to perform sanitization before validation, nor normalization afterwards. Definitely one of the parts that I like less about the framework.
That form request validation is such a strange level of abstraction. It makes far more sense to me to validate the model than to validate each individual HTTP request.
Why have a separate class/component that's highly tied to single controller or action? It just seems like dividing non-reusable logic up between files for no good reason.
In the 80% case you are totally right, and having automatic validation depending on the model would be easier. However, I would argue it is not a good fit for Laravel, and that in the 20% case it creates more problems than it solves.
It doesn't suit Laravel very well because it uses Eloquent and its Active Record approach to models. This means that the model already has way more responsibilities than it arguably should. Now you also want to make it responsible for validations...
In the 20% case, you may have different validation rules for different actions (you can PATCH an object with a subset of fields, or you can set a field during creation but not during update, or whatever you can think of (it happens at some point). Also, validation is oftentimes depending on the user's permission (this field can only be set by supervisors, or only administrators may set a price lower than XXX$, or... you get the point I hope.
Finally, you don't need to do anything to "validate each individual HTTP request" from the coding side. If all your actions that refer to the Thing model have the same validation rules, just create a ThingRequest object with the rules once and inject that as a parameter to your controller methods. Laravel automatically resolves that object, filling and validating it before giving it to you, as in:
class ThingController {
function store(ThingRequest $request) {
$thing = new Thing($request->validated());
$this->save();
flash()->success('Thing saved');
return redirect()->route('things');
}
}
And that's it, this includes validation (as defined in ThingRequest), with the possibility to add custom validation messages and all.
> In the 80% case you are totally right, and having automatic validation depending on the model would be easier.
That's my point! It seems to be a common refrain for Laravel. A good framework should make the 80% super easy -- that should be the trade off. For the last 20% you can do some easy manual validation in the controller -- hardly a big problem.
> This means that the model already has way more responsibilities than it arguably should.
Not a solid argument for Laravel...
> Now you also want to make it responsible for validations...
If I have a model validator that requires every basket to have at least 3 eggs of different colors then that validates the user-interface and can validate the command line process that adds a purple egg to every basket. With Laravel, validation is far too tied to web requests. And if you have multiple models that work together in different combinations in a controller you're creating different CombinationOfThingRequests to validate it.
> If all your actions that refer to the Thing model have the same validation rules, just create a ThingRequest object with the rules once and inject that as a parameter to your controller methods.
So you have a ThingRequest that exactly validates a ThingModel -- that's not very reuseable. How many different controllers exactly manipulate a ThingModel that the request is identical across them all? How many actions even do that? If this ThingRequest is responsible for validating more complex relationships, like the basket/egg example above, that means my HTTP request object is querying my database! If that's not the wrong level of abstraction, I don't know what is.
My opinion is that the most valid separation of concerns in MVC puts the application state in the model -- it's the thing that is valid or not valid.
I get that there are places where you need more specific validation and that can easily go in the controller.
What I can't imagine, and maybe you can help with this, is when you'd need to reuse validation across controllers that doesn't make sense the model?
I absolutely could not understand why Laravel divides things the way it does and I just did not like it. Request classes are a concept that don't even need to exist, and don't, in other frameworks.
The simpler the abstraction, the more likely the end product will not be a disaster if it is a critical system.
Frameworks are development speed enhancements but frequently are not "better" in terms of mechanical function. Even "major" PHP applications built on frameworks (i.e. Magento 2) frequently lose site of those abstractions and create fundamentally flawed products where the solution is you need a software developer to spend hours on it just to make the thing "work" as advertised.
This rush to abstract everything is good for developer productivity, to a point, but I've rarely seen it result in a better/saner product.
Though it's not like you don't need experience with those same packages if you go the laravel way.
A developer shouldn't have an issue working with either. It's all PHP and all sane PHP frameworks are mostly based on the same concepts, with some tradeoffs here and there...
One of the great developments in the PHP eco-system is the use of components and the inter-op standards developed around them [1].
For many years now, "frameworks" such as Symfony and Zend have been mainly been a set of components with an optional thin framework layer. So, not frameworks in the traditional sense.
For those interested, another great resource is "Create your own framework on top of the Symfony Components":
As a former php dev (15 years ago), it fills my heart with joy every time I see PHP-FIG and composer related innovation. They are the best things which could have happened to PHP.
3 years ago, I made a (not so successful) youtube series of building a website from scratch using php[1].
I'd basically record myself coding for 1h then add a voice over it as I speed up the video 3x.
Although my English falls apart fairly quickly, (if you ignore that) it is a good way to see the entire process of building a framework and understanding what each part does.
A lot of the things in this article are covered there, with a little bit of the why.
I wanted to improve my PHP skills so I researched and taught myself how to build a PHP framework myself, without composer or any third party libraries. This was a while ago so it was for PHP5 and I used CodeIgnitor and CakePHP as my inspirations because that was what was chosen in the previous places I had worked at so I was familiar with them. I enjoyed the process and I learned a lot.
I encourage people to build their own framework without composer as a learning experience if they're looking to level up their PHP knowledge. I plan on going through it again from scratch but following modern standards: PHP7, PHP-FIG, strict_types
PHP has been in a weird place for nearly a decade now in technical forums like HN where it is mocked endlessly often to signal a superior technical understanding by people who would not deign to use it. As if its the only language with shortcomings.
Yet it continued to be used in some of the most scalable and widely used apps of our generation from Wikipedia, Wordpress, Facebook, Slack and more.
It often feels other languages marketing teams have preyed on it in many ways to gain attention. And there has been some kind of war against simplicity that places an unearned respect for 'clever' abstractions under the guise of scalability often in pursuit of resume padding, or 'best practices' entryism and gaining influence in projects via package managers and the like.
Anyway, if this is how people use PHP these days, why not just use Java? I guess deployment is different (PHP is not compiled), but code/concepts seem pretty much the same at this point if you want to use this style of programming.
I'd say that web programming architecture has been converging between most languages. What's shown here is:
- Setup a library tracking system (composer, the autoload stuff)
- Setup basic Dependency Injection (using code in this case, but the same could be done through config files or annotations)
- Parse requests into a request class
- Setup a middleware chain, including a router, and dispatch a request through it
How is this different from flask/django (python), rails (ruby), or gin (golang)? I'd say the basic concepts are pretty much the same, except maybe the library handling part. In other words, I don't think there's enough "meat" in this example to appreciate actual relevant language differences.
Also, you can write "java-like, enterprisey" code (Symfony) that values explicitness over magic, or go the other way around following the "convention over configuration" mantra, and end up at Laravel that is much more Rails-like.
Finally, PHP is still has several advantages over java for many people out there:
- Every request starts from scratch, meaning it is impossible to accidentally provoke side-effects on other requests
- The package system (composer) is just a package management system, and hence MUCH simpler to understand than ant/maven/ivy, that are entire build systems that also want to control testing, deployment, and everything
- Development is faster-paced thanks to the lack of compilation. You can even easily setup an environment with auto-reloading and just "save updated code" -> "see result in less than a second".
- You can deploy your app to any of a horde of (cheap) hosting providers and let others deal with the ops side. The service may exist in java-land, but it certainly isn't as ubiquitous.
- PHP programmers are cheap (yes, cheaper than java-programmers).
...or C# or anything else. I programmed in PHP for many years and I agree. I mean there are good reasons for maybe not using Java but it's hard to imagine a good excuse to start PHP these days if you don't already know PHP.
On the other hand, things in PHP-land are improving at such a rapid pace (but without the churn of JavaScript) that if you are a PHP developer there isn't much reason to switch to something different but similar.
I think there is strong sense of “we’re not the old PHP anymore, we cut our hairs and wear suits with ties now” in the community.
In a lot of fronts it means mimicking Java, but I think it still is more flexible (and less reliable as the other side of the coin).
It’s still very easy to drop down to “quick and dirty” code anywhere it’s needed, and it still benefits from a very low bootstrap cost to deal with single command/requests.
So how would you represent an absence of a value? In an enum that'd be easy, but there is a semantic difference between an empty string and a null string.
Or would you propose sending a boolean to indicate null as well as a string in a data type?
Well, two layers of factory classes, one calling the other, plus a big xml blob is pretty Java specific. I'm open to to common counter examples in some other language.
Interface based polymorphism is pretty useful. Been thinking more functionally lately, and can’t remember needing it. Parametric polymorphism ( aka generics ) are still useful for the immutable state graph.
There's no such thing as web application development "without a framework".
There is only a choice between using someone else's framework, and inevitably building your own. If you reject all third-party frameworks, you will end up reinventing a bunch of design patterns from other frameworks. You will end up writing your own libraries to do the things the framework would have done. And you will -- no matter how good or fast it feels to you -- end up spending more time in the writing and maintenance of your private "non-framework" than you would have spent in deploying an existing one off-the-shelf.
That's not true. I've worked on large applications with frameworks (CodeIgniter, Symfony) and without frameworks (but with composer packages). In the beginning you might spend a little more time on wiring things together, but on a large enough application your framework will always get in the way somehow and you will have to find workarounds.
For large projects, I strongly prefer a frameworkless approach. If you do throwaway apps for an agency, then a framework is probably the better choice.
You chose a set of libraries. You installed them. You used them. And by "used them", I mean you wrote code which called into them and which wired together all the various pieces to make a coherent web application. I know you did this, because if the libraries had come with a magical "make all these things work together" function for you to use instead, you would have dismissed that as a framework.
You don't want to call that combination of libraries and in-house wiring-together code a framework. I get that. But that's what it is, whether you want to call it that or not.
And I'm sure that you don't see it as a maintenance burden right now. It never feels like a framework or a burden at first, because it's all made up of this code that you wrote and that you understand and that you control, and it feels great! For a while, at least.
But sooner or later you will realize you have built your own in-house web framework, and that now part of your business is to be a web-framework developer, instead of a whatever-your-company-actually-needed-to-make developer, and that being a web-framework developer is not a very fun business to be in.
And you will hire more people, and they will have to be trained on this thing-you-refuse-to-call-a-framework, but they'll recognize the patterns sooner or later, and will wonder out loud why it's missing this or that feature that the off-the-shelf frameworks have out of the box, or why this particular part of its API is so weird and cumbersome (it made sense back when the codebase was much smaller and only a couple people worked on it, you'll tell them, sheepishly).
And maybe some of them will roll up their sleeves and try to add what's missing or clean up the historical weirdness, and maybe some of them will get tired of working on this thing that won't add to their résumé and leave, and others will just do their best to get work done, but at a much slower pace because they're working with a framework built by people who hate frameworks, and still others will start to agitate for just going and getting a proper framework off the shelf and using it already, and you will end up having some very interesting and perhaps very heated team meetings, and you'll realize that you're spending way too much time as a team talking about tools and technologies and not nearly enough talking about products and bugs and features and this is not going as well as it was back when everything seemed so simple and easy in the world of "frameworkless" development.
This is the iron-bound web developer's counterpart to Greenspun's Tenth Rule, and in my experience there is no escaping it.
Was hoping for a built-in mechanism for HTML-aware, injection-free templating given PHP is invoked via an SGML processing instruction from otherwise static HTML. Instead what's shown is massive Java-ish meta boilerplate for trivial HTTP request/response abstractions.
For learning, this is great. For actual apps, this is plain stupid. Not to mention that no one has the time to cook up a framework every time one wants to build an app. Or all the rest of the components that are missing here. This whole PHP without a framework--whether it be creating your own framework or using raw PHP--trend seems like it's promoted only by inexperienced devs who don't need to work on real project in real companies in real life. I would literally fire someone if the insisted on doing this for wasting company resources and time unnecessarily.
I'm seriously not sure if this is satire. It starts off with a simple example, and then goes down a rabbit-hole of massive complexity to ultimately do the same thing. This reminds me of the many OOP articles that were common shortly before the turn of the century, which would take as an example a perfectly straightforward and simple-to-understand piece of code and then bloat it into an asinine multilayered monstrosity by applying a generous amount of "OOP best practices and patterns" while straight-facedly enumerating all the alleged benefits.
When you first started with PHP, you may have used includes or requires statements throughout your app to bring in functionality or configuration from other PHP files. In general, we want to avoid that because it makes it much harder for a human to follow the code path and understand where dependencies lie.
Autoloading just means that when your application needs to use a class, PHP knows where to look for it and automatically loads it when it's called for.
How in $deity's name can you say that specifying immediately the exact path to the file included, in the file that includes it, is "much harder to follow" than hiding it behind the indirection of the autoloader and whatever it does!? Honestly, WTF!?
(Maybe the joke here is that everyone is just pretending to admire the emperor's new clothes, in which case I apologise.)
Yes, unfortunately I don't think it is satire, unless they've gone to immense effort... see the guy's twitter feed, etc.
The author recommends building some kind of abstract structure factory which has perhaps five external dependencies per codeblock, a composer file, vague notions like dependency injection, auto-wiring, containers, routing, middleware, request factories, response interfaces, a class hierarchy and an obtuse non-production webserver in mental overhead ... lauding the design because he says it complies with a bunch of numbered standards that allow you to swap out your layers-of-assumption components.
This is blatant false economy. Nobody ever swaps out components. Nobody in fire-and-forget webdev land cares about standards. Just get the thing out the door, keep it simple, and thus keep it maintainable.
As others have commented, explicit code is clearer. Clearer code has less bugs.
This is the 'new PHP' from ~1995, seamlessly using decades of high efficiency improvements to kernel caches, networking gear, the interpreter itself and webservers. Zero complexity, not a class in sight, and definitely no middleware. It's a great language, when not misused.
I get downvoted when I say anything remotely negative about PHP, in threads devoted to PHP, but perhaps my thoughts will make sense if I emphasize that I used to love PHP. It was my first real language, and I built my first business around it. That was in the year 2000. That was in the era before modern package managers, when PHP's huge standard library was a tremendous benefit, because the alternative meant using something like Perl, where you had to download every module from CPAN and cobble it together yourself. PHP was a dream compared to that.
But 18 years have passed. Every language now has very good package managers. There is an abundance of dynamic languages, most of whom are more consistent than PHP.
I'm not going to waste your time with a long PHP rant. I just hope that everyone is aware that the huge benefits that PHP offered in 2000 are no longer valid. If you are programming in PHP, you owe it to yourself to explore some of the many options that are out there. There has been incredible innovation among software languages since 2000, but PHP has mostly tended to follow a conservative path, mostly imitating Java.
For anyone who won't be bored by another PHP rant, I wrote my thoughts on this subject back in 2014:
Because every time someone rants against PHP, they do so in the same way you've done, saying things like "If you are programming in PHP, you owe it to yourself to explore some of the many options that are out there".
All you do is insult the language, and subsequently, the intelligence of those who continue to use it. Many of us have looked at - and heavily used - other languages, and choose to come back to PHP for many (not necessarily all) projects. Your assumption that we're all morons who program in PHP because we're too stupid to try other options is misplaced. You looked elsewhere and preferred what you found. Good for you. Some of us who looked elsewhere found that every language has its faults, and that PHP does the job just fine. Particularly since the performance improvements in later PHP 5.x versions, and finally the leaps and bounds gained in PHP 7, the language is more than good enough for most tasks.
I've done projects in C, NodeJs, Ruby, and yes, even Python. Python fanboys in particular seem to think their use of the language is an indicator of superior intellect or programming ability. The whole "I am smarter/better than PHP developers" gag is really, really, old.
For me the biggest non-starter with PHP is the abuse of doc comments and annotations as well as the sheer waste of space which has now been blessed in PSRs as the idiomatic way to write "modern" PHP. This same modern PHP often fills a full screen with only a few lines of real code. You could be forgiven for concluding that someone influential in PHP-land is trying to out-Java Java. PHP is a waste of space, literally.
We evalued PHP for a GraphQL/REST backend and we found some really good points: the design of Symfony, the ACL system, the huge productivity gain of API Platform (https://api-platform.com/). In the end we discarded the whole stack anyway because of the heavy use of docblocks annotations which made our test code hard to read and hard to debug.
But even if both of your points were true, the point is to look at what is happening in other languages and frameworks. Every day you spend learning about PHP is a day that you are not learning about the languages that are really moving the industry forward to interesting new places. Ask yourself, honestly, how many interesting new ideas will you learn from studying PHP, versus the more versatile (as in more platforms, and also the frontend) languages such as Javascript/Node, or the more innovative such as Go or Rust or Clojure or R or Julia? And I'm not even mentioning the more experimental languages, such as Shen or Lux.
Every day you spend learning about PHP is a day that you are not learning about the languages that are really moving the industry forward to interesting new places.
I continue to be baffled by this sort of "novelty-chasing" --- do I really care about "interesting new places" or "interesting new ideas"? No; and in fact I'd rather not, because it takes time and energy away from actually solving useful practical problems, besides the ones you create yourself in chasing after the latest cruft.
PHP is slow on an absolute scale, but chances are that a minimal, straightforward application written with it can perform better than something with a bloated framework on top in a different language. That takes true skill and experience, not something you can get if you're continuously jumping around trying to chase the fashion trends.
As someone who has witnessed several major trends in programming come and fall, the amount of churn (and encouragement thereof) in the web community is astoundingly unsettling.
Try writing a web app in Luminus (Clojure) or Phoenix (Elixir). I guarantee you will be enlightened. The danger, however, is that you may lose your tolerance for OOP languages thereafter.
Elixir/Phoenix is great and promising but you don't get everything you have in Symfony out of the box. For example the EEx template system is behind Twig (I especially miss inheritance) and Auth/Autorization is kind of a mess.
The ecosystem is also smaller and deployment in Elixir is still a work in progress (mismatch between Mix and Erlang releases).
Maybe you don't realize this because you haven't studied them, but "bloated framework" is unknown in Go or Clojure or Rust. Each of these languages tends towards minimal frameworks. Clojure, in particular, is known for its composeable libraries which make frameworks a bit of a sideshow for that community. Go is known for having enough in its standard library that some aspects of frameworks are not needed.
About this:
"because it takes time and energy away from actually solving useful practical problems,"
You can not know that without first studying other languages. You might find that you are 10x more productive in Rust. You can only find out by studying Rust.
But you bound the conversation in ways that I didn't when you write:
"in the web community"
I feel that developers can learn a great deal if they study projects that don't necessarily have anything to do with Web programming. Nothing in the article or on this page necessarily restricts us to only considering Web programming.
"It's not about the tool, it's how you use it."
I wouldn't use a hammer to go fishing. Nor would I use a saw to turn a screw. Nor would I use a frying pan to tune a piano. It helps to learn about a lot of different kinds of tools, because over the course of your career, you might be confronted with diverse tasks.
> I continue to be baffled by this sort of "novelty-chasing" --- do I really care about "interesting new places" or "interesting new ideas"?
Is this a troll? No you don't need to care. Feel free to go live off roots and tubers in the forest. Or write some COBOL. Anything is justified if you're putting "interesting new ideas" in quotes.
I worked with PHP full-time for several years and energetically rationalized away the time I invested into building that expertise. I liked it, I was getting things done, it would help me get jobs in the future. Utter nonsense. What a waste of my life.
Eventually I snapped out of it. Turns out you can just move to places Silicon Valley, there are jobs at awesome companies working with the cool modern technologies. You don't need anybody's permission, just do it. Want to write Haskell/Go/Rust/Elixir/Clojure every day? Want to work with ML or robots or big data or whatever floats your boat? Just go do it. You don't need to sit there writing PHP as the world passes you by.
PHP is a backwater. People live there and tell themselves that it's fine, good as any place really, can't imagine anything better, probably wouldn't like it anyway. Or they just stop thinking about it.
PHP was never in fashion. In the beginning it wasn't as powerful as Perl. Then it was looked upon as not serious compared to java or hobbist by the business asp crowd. At one point because of a facebook movie it was in fashion for a year but that created a I hate php backlash. Php has changed so much I'm seeing people rediscover it.
Remember java was cool or mongodb or node or ruby on rails. It feels like go is becoming less cool. I wonder what next year will bring? Perhaps php will be rediscovered when SV changes once again.
Some people could care less about SV. Or maybe they want to ship products their clients can handle after launch. Whether you like it or not PHP has created more value than any of those languages you mentioned. It's like you're saying it's better to be a Ferrari mechanic than a Toyota mechanic. The user does not care. So ship stuff that matters in whatever tool of choice.
Taylor Otwell says the same thing about laravel/php.
Mark Zuckerberg says the same thing about React / HHVM / Hack (PHP variant).
I'm sure Steve Jobs said the same thing about Objective C or Swift.
It's called an opinion, just because one person who spends more time investing in VCs, and just because we're debating an issue on a site, doesn't mean we have to take the creator of the site's past essays as the absolute truth...
Go, php, ruby, python, lisp variants ALL are the best script if A. it's the only one you know and you just want to launch something or B. You've done your due dilligence to figure out what you need, is it just a crud app? PHP is fine, is it a chat app? Well you might need erlang or elixir on the backend, or something with concurrency.
If you're spending 100+ hours debating on platform instead of building shit, then that's time you can't get back and that's wasted opportunity acquiring customers to a platform you could've had built last week -- if you weren't stuck in...confusion about what framework to build in, or spending all your time in tutorials because you picked the shiniest framework or language that is above your pay-grade so you have to learn everything.
> how many interesting new ideas will you learn from studying PHP, versus [...] languages such as Javascript/Node
This is on point! Programming PHP is not about diving deep into interesting language constructs or creating beautifully structured software - PHP is about getting things done, about starting hurdle-free and progressing rapidly. It goes against some "good development practices" but it works, see for example the single-file website remoteok.io from Pieter Levels: https://twitter.com/levelsio/status/938707166508154880
Love it. Back to the roots - one file, load it up in the editor, if one needs to debug something, just search for it. Yep. This is how it should be: easy to debug.
Every day you spend learning about PHP is a day that you are not learning about the languages that are really moving the industry forward to interesting new places.
That's "chasing shiny". Shiny is the cancer destroying the computer industry from the inside.
Any day not learning how to do web application development in LISP is a day wasted. The old tech is still cutting edge, way ahead of any new shiny garbage, because that garbage is decidedly not moving the industry forward, just introducing one more variation of making a computer do something. And that's extremely bad.
> But even if both of your points were true, the point is to look at what is happening in other languages and frameworks. Every day you spend learning about PHP is a day that you are not learning about the languages that are really moving the industry forward to interesting new places.
Which of those languages give you NaCl out of the box?
Your comments are very valid for 2014-era PHP, but I'm not sure you understand how much PHP has changed. The benefits PHP offered in 2000 are no longer valid because those are table stakes, absolutely. What about the benefits PHP offers in 2018?
> There has been incredible innovation among software languages since 2000, but PHP has mostly tended to follow a conservative path, mostly imitating Java.
PHP fans like to point out (tongue slightly in cheek) that PHP is the first major language to add modern cryptography to its standard library (libsodium in php 7.2). We can argue about how important that is, but it's also not wrong. And it certainly didn't copy that from Java. :) Further, I think some of your criticisms in the link have also not aged well.
> Every language now has very good package managers.
Not sure if composer is "very good," but it's generally worked out better for me than gem.
(Also, package managers are not an unqualified benefit. I like them for installing things I'm not developing, but as far as I can tell they essentially defer a legibility cost for developers. Sometimes worth it. Not always.)
> There is an abundance of dynamic languages, most of whom are more consistent than PHP.
I think it was Ralph Waldo Emerson who had some choice words about consistency. And this criticism has always rung a little hollow to me. I'd agree that some of PHP's dynamic multi-paradigm scripty siblings feel cleaner, but having written code in many of them, it's never felt like a major difference in productivity to sometimes have to pause and consider argument order or precise names. The lookup cost has always seem cheap on on par.
> I just hope that everyone is aware that the huge benefits that PHP offered in 2000 are no longer valid.
There's definitely a closing in the benefits gap since 2000. PHP is far from my favorite language. PHP is not right for many projects. There are still some benefits that PHP prioritizes that I think arguably aren't done better elsewhere
* Trivial deployment story. Your app is one or more files. Drop it in a directory on a wide variety of hosting environments. You're done! (Buuut, if you want something more involved, lots of choices available there too.
* The language is the template language (though there's other options). Some people consider this an anti-feature because it allows amateurs to build ill-organized applications around a dynamic-document-as-program paradigm. I think that's still a brilliant gateway that makes the marginal cost of moving from a static document to a dynamic one small while still allowing an easy transition to front controllers. And it means the templating performs at parity with the language itself and can do as much as the language can do.
Pair it with a simple routing library and model layer and it's as easy to build something reasonable quickly as it is with comparable Python & Ruby frameworks, often with fewer moving parts and similar magnitude of performance.
So sometimes when I have smallish web-facing projects (or projects I think I might want to distribute for others to run on the web), I still often find myself reaching for it, even with plenty of other options at hand, even with languages I like better.
Autoloading allows one to specify modules by their logical, namespaced identifiers rather than simply importing a file. One benefit is that one can swap out the implementation without necessarily changing the code. I've had to override some badly-behaved libraries that way.
Generally speaking, while I don't think this is satire, I would hate to see someone code this way, unless the point was simply to learn how the components of a web framework work together. This is not "framework-less PHP", it's just a DIY framework, and not a particularly good one. I think that attempting to create a web application without a framework is at best needlessly duplicative of effort, and at worst an open invitation to security flaws and spaghetti code.
The author says, "This is not an anti-framework screed," and it's certainly not polemical. However, I think it's probably more representative of the Zend-ecosystem way of doing things rather than PHP best practices: accretion, as opposed to design.
Some time ago there a guy that posted a "Show hn" showing his "lightweight templating engine in php". He parsed a HTML file and replaced <% %> tags with some text. It never occurred to him that php is actually a templating engine
Thank you. You stated what I was thinking much more clearly than I was able. I strongly prefer explicit code that states clearly what is happening without having to guess.
No, this is probably serious; this is The New PHP.
Seems we finally broke the fever of infectious imperative spaghetti and are coming around to OOP and patterns by following the trail left by JVM ecosystem and eating its droppings and clothing ourselves in its shed skin.
Huh. Now I can't tell if this one is satire as well.
You are on the mark for Java like OOP becoming popular in PHP. I think there are more people trying to do enterprise level work with PHP and they are taking lessons from existing software engineering practicies.
What I found interesting was a period around 2008 where PHP still had "easy deployment" as a pro in its belt. Some enterprise level projects looking for easy adoption chose PHP and tried to build as they would have in Java.
One example is Magento, and arguably it was the right choice at the time and has given it enduring popularity (if not endearment) for nearly a decade.
As more software engineers took web applications seriously they brought best practices and tech stacks with them, and you can see the PHP community really strive to level up.
But if I were to make a bold statement, it is web development in general that struggles producing solid reusable work. You see it in all languages. The only ecosystem I can think of that isn't disparate islands of unique wheel factories is Ruby, and that seems to be because people learn "rails" not ruby.
It's not that requires are hard to follow, it's just that you most likely don't want to mess around with requiring files manually instead of easily doing it by using autoloaders.
You can do it, but it's most likely a bad idea to mess around with it considering namespaces and such.
Autoloading is pretty simple. PHP knows exactly where to look for code, and you know exactly where to look for it too. Class names are mapped exactly to file names [1], so autoloading lets you simply use a class without needing to explicitly include the file.
There's a number of issues inherent in manual include statements:
- When you include a file, unless you include it using the absolute path, the path will be resolved using the include_path ini setting, which works just like the $PATH environment variable works to resolve the location of binaries. Typically, `include_path` will be set to something like `/usr/share/php:.:/some/other/dir". If I encounter `require_once 'Foo/Bar.php';` in some code, what file will that include? `/usr/share/php/Foo/Bar.php`, but maybe also `./Foo/Bar.php`.
- Relative includes are relative to the current working directory, so a different file may be including (or not found at all) depending on what directory I'm executing my script from. To avoid this, it's good practice to include files using `include __DIR__ . '/Foo.php';` to ensure we know exactly what file is included.
- Prior to autoloading, most dependencies were installed in a global location, e.g. `/usr/share/php`, which would then be part of include_path. Different projects on the same machine therefore had to have the exact same dependencies. Autoloading enables per-project dependencies.
- Using manual includes makes it much easier to have a poorly structured project. With autoloading, if I see `$bar = new Foo\Bar();`, then I know exactly what I'm getting: the class Bar, defined in the file `src/Foo/Bar.php;`. On the other hand, if I see `include 'bar.php';`, I have no idea what I'm getting. What's in the file? Could be class, could be bunch of random functions, could be mish mash of HTML and PHP spaghetti.
Same of these issues are manageable even without autoloading by following best practices, but unfortunately there's a lot of really bad code out there that doesn't. Autoloading (along with composer) completely solves a problem that used to exist in PHP. Anyone that actually uses PHP can attest to this. If you've ever worked on a project with a web of manual includes, it's a total nightmare compared to a properly structured project using autoloading.
Autoloading aside, the point of this article, IMO, is that it's quite easy to set up a well structured, maintainable, easy to understand project architecture without using a major framework. The central abstraction here is that all requests go to a front-controller, which then calls a function that accepts a representation of the HTTP request and returns a representation of the response. Having abstractions for Request and Response is much more manageable (and testable!) than having random print statements everywhere and using global variables like $_POST. This is same idea behind just about all web programming "frameworks" in any language. Of course this would all be over kill if all you needed was a "Hello World" page. But this isn't about hello world pages, it's about real projects that grow over time and need manageable structure.
Furthermore, this article advocates for dependency injection. Again, overkill on a hello world page, but in a real project explicit dependencies makes life so much easier.
[1] This is the de-facto standard. Sure you could technically write an autoloader that does weird things, but nobody--human or automated tools--does this in real code. It's not a problem in practice--autoloading in the real world makes things much more explicit than manual includes.
I'd also like to encourage everyone to strace a php run sometime and then tell me how great autoload is..
stat(path1/Class.php)\ Not found
stat(path2/Class.php)\ Not found
stat(path3/Class.php)\ Not found
stat(path4/Class.php)\ Not found
stat(path5/Class.php)\ found!
open(path5/Class.php)
read(path5/Class.php)
What seriously bugs me is that he uses object oriented programming as if it were the most natural, normal thing. Debugging an object oriented program is a nightmare because all the data and therefore the machine state is hidden, that's the idea.
If I were to write a website in PHP, I'd use functional programming and certainly no framework. And I'm still scarred from the Autoloader in Perl. Never again!
For one project, I used slim. It has routing, a simple container and that's about it. I made my own controllers and integrated them in. Super fast, for anything more I used composer packages.
I read this article and found it to be a great example of why we should NOT adopt modern PHP techniques at our company.
50 lines of code and contrived examples (is HelloWorld class a view or controller? AwesomeClass is a model?) get one line of HTML emitted in a barely readable way.
This article fails to motivate why each layer of complexity is added. It basically starts with the assumption that you want to use a framework and says "hey look you can do the same thing with 50 lines of boilerplate, not really, but kind of."
I would be much more impressed with an article that starts with the obvious way to write a PHP application (.htaccess, index.php, products.php, library/database.php, library/*.php) and then explains the actual problems that would make you want to opt for more complexity/organization/modern techniques.
In my day job, I work on an application based on Drupal 5. It's not necessarily "without a framework", but really it might as well be.
It has absolutely made me a better developer because I've had to delve into how the system works more than I ever did with Laravel (or Ruby on Rails, in a previous life). Things don't just work (hell, sometimes they don't work at all) and poking around until I really understand why is a healthy thing for any mid-level dev to do.
That being said, I do miss a lot of the modern niceties and it can be really frustrating to work this way. I'm glad for the opportunity, but I would also like to be able to use more modern dev tools in the future.
Drupal 5? Wow! I began my Drupal journey on the 4.6/4.7 'cusp' after working with J2EE & although I like Drupal because I can see the 'bigger picture' of the business logic being infused into the API, i.e. business problems solved = code as opposed to using something like Laravel & creating new untried, untested code all the time, I only really started liking coding with Drupal 8 as it's almost a complete rewrite from procedural to mostly OO.
The major problem over the years of fire-fighting various dubious installs of Drupal is people hack core and contrib modules making it impossible to maintain - if you use the APIs, grow modules & extend instead of hacking then it makes life a whole load easier - all I do to update my sites now is 'composer update --with-dependencies' (well, there's a few more lines to update the db if needed, export config from db to code, etc. but it's super-simple).
I hope you have applied a patch to protect against the latest security issue found, here's a link to an unofficial patch for 5:
I like to use the same approach, I even wrote a tutorial [0] and a book [1] about it.
That being said, I am still forced to use Symfony at my current job. It only gets in the way sometimes, it's not too bad.
On my previous job we went from CodeIgniter to frameworkless and I really liked that. Not having framework constraints working against you was really enjoyable to work with.
I recently gave Sylius, based on Symfony, a spin. I wanted to add a field to a product, editable in the admin area. The additional code and the extensions were ok. Some of the config changes are understandable but I thought it a bit much when the number of additions to configuration outstripped the amount of code required.
> So there you have it. With just 44 lines and the help of several widely-used, thoroughly-tested, reliably interoperable components, we have the bootstrap for a modern PHP application.
I haven't used PHP for almost a decade, but I agree with the sentiment of this article.
I built a web app back in 2009 in PHP and didn't use Code Igniter or Zend (basically the only two frameworks back then), opting to do it all by hand. And it ended up being a really valuable and formative experience. No matter what language I use, I understand how a web application really "fits together" under the hood and I think there's value there.
As a side-note, compared to Node.js or Rust or what-have-you, PHP just seems needlessly verbose.
I'm someone who uses a custom framework at work, and it's not verbose at all. Maybe I'm doing it wrong?
I just spl_autoload_register on a controllers directory.
Then based on the url, it creates a class for the first part of the url and passes in the rest... $class = new $class_name();
$class->index($url_parts);
That class always extends an output class which uses a template system to render a component. I also use an ORM with a models folder that has a bunch of static functions to get data in each model class.
I would love to hear from someone more knowledgable about the disadvantages of my approach or why this articles is a better way of doing it. Of course I use composer and use a bunch of libraries for aws, oauth, Google APIs... but for the actual framework I keep it simple and haven't had problems so far.
> I'm someone who uses a custom framework at work, and it's not verbose at all. Maybe I'm doing it wrong?
Probably, not, it was just my sentiment by looking over the code in the article :) I haven't used PHP for almost 10 years, so I have no inkling of what "modern" PHP looks like.
Symfony 4 looks and feels like a slightly odd java Spring setup.
Annotations are ugly as hell in PHP but thats a result of not having annotations supported in the language itself (you need an annotations preprocessor and they're all in comment blocks).
There is an rfc for annotations in php as a language feature, so maybe someday. When that happens, Symfony may as well be Spring for PHP.
> "...Code Igniter or Zend (basically the only two frameworks back then)..."
wat?!
i coded php in the early/mid 2000's and had at least a half dozen frameworks available to choose from even then. for example, i used fusebox after starting to create my own framework and finding that it already (mostly) did what i had wanted to do.
Modern PHP is great but it still has the same inconsistent API. I did PHP for many years and had to look up the manual all the time because functions have different conventions for arguments.
It does have a very large and inconsistent "stdlib", I agree. On the other hand, you very rarely have to look for 3rd party libs. Is node.js better because you have to trawl throgh npm for highly variable quality (and equally inconsistent) add ons (that typically pull in a spiderweb of other dependencies) ?
I've worked on PHP pretty much non-stop since PHP/FI
and while this is a good try, it goes off the rails telling people they need a DI library, container and how routes SHOULD work, which is pure hubris. I won't be pointing to this as a good example.
I’m not sure the barrier to entry is still so low.
Someone starting now would be splitting attention between “modern” concepts like presented in the OP, and the hacky/broken standard commands and quirks that persisted through the revisions.
I’d guess Ruby or Python would be easier for someone starting from scratch.
APCu is no longer a bytecode cache (if that's what you mean by userspace?) it's exclusively an in-memory k:v store
FastCGI sometimes scales better but also has increased latency because it adds a proxy layer vs mod_php where you sacrifice memory for more "direct" access.
Yes, that's what I mean by userspace. It's a hedge against startup time and separate process pools for fcgi. Php's answer to node.js's persistent processes.
- Sane, easy to use package/dependency manager that just works, every time (none of node/python/golang really have that, for entirely different reasons).
- Large stdlib that, while inconsistent, frees you from searching packages for everything (vs nodejs).
- I'm sure some will disagree, but php's documentation is top notch, easy to navigate, and with nice completion from user examples (you could say it is a mini-stackoverflow by itself). Golang's docs are good, python's are good but hard to navigate, node's are typically worse.
- PHP's ordered, possibly hash-backed possibly plain arrays are an abomination from a data structures point of view, but god are they handy! Golang is terrible here with its static types (fine) but lack of generics (just check how to sort a list of a non-primitive type).
1. I rarely have problems with package management in Python. I know pip has flaws but it's not enough of a pain point for me to see it as an issue.
2. I'd say Python is an easy match in this regard
3. Agreed about the docs - I still find the organisation of Python's docs a bit peculiar.
4. Handy data structures, you say? I think Python might have the edge here.
It's strange you don't mention PHP's biggest strengths: deployment and learning curve: You can begin on almost any commodity hosting with a simple text editor and no knowledge of Unix internals. The amount of extra stuff I had to learn to be productive in Python was huge at the time. It's got a bit better now with various simple deployment options but PHP still wins out for the beginner.
I think the biggest pro for PHP is its simplicity. By default you don't have to care about the server. You just place some text-files in a web server directory and open a website, easy. And dynamic languages tend to be easier accessible for newbies too. It is also a con, as some things are just not available (e.g. multi-threading), but in general that lets you focus on the application logic and lowers the entry barrier.
Traditionally, a major pro for PHP was also its broad availability for web space but that doesn't seem to be so important nowadays anymore.
Putting node, python and Go in the same place against PHP is kinda hard as those three are very distinct from each other already ;-)
Nodejs out of the box would ofc. be faster than PHP on something nodejs is born to do. But lets say we needed to do a bit of CPU work on each of these requests, then nodejs might struggle compared to PHP.
Both should be able to scale well in a "create a website and return the HTML"-scenario, and it's not unlikely that a PHP setup would be faster.
In a single page app thats mostly based on fetching data from an API nodejs would probably be faster.
About APCu: It's damn fast and very unlikely to slow you down, other stuff will probably bottleneck you way before APCu becomes a problem.
Use PHP as PHP, and nodejs as nodejs.
If you really need async in PHP or want to use PHP somewhat like nodejs then you should probably go for an extension and serve requests directly from PHP. I've had great experiences with that, serving over 500K simple HTTP req/s on a low end server.
But again, if max performance on a single server is so important then you should probably go for a compiled language anyways.
But php is going to have some inherent latency starting up a process for each request and an overhead of spinning up a new process for every request. If you need speed you shouldn't use any of three languages you just mentioned though. These days I think it's easier to find nodeJS developers. You can take a frontend developer and teach them nodeJS very quickly also. It's arguably just as easy to proxy from nginx as it is to setup a PHP sapi
It's not that bad anymore. We do have fcgi, fpm, and also
user space caches like apcu. You would have to try pretty hard to find a default set up that resulted in process per request these days.
It scales very well on a single host. Which has limits, but limits that exceed some percentile that most projects need. And things like redis take it even further. If you're pushing the limits of php, you probably have a nice-to-have problem tied to lots of incoming revenue. Similar to FB and HHVM.
I agree there's a scaling issue, but nobody is doing process per request anymore. Process pooling is a decade old or more.
Some people now boot an OS to serve each request, and reinstall the OS to deploy new changes. It's funny, even the objections to PHP haven't kept up with the trendy software practices.
I guess the objection to "spinning up a process" is actually a problem with slow PHP initialisation, though? A dinky server can spin up many thousands of processes a second. I'm pretty sure OS process overhead is nothing compared to whatever PHP or Rails or whatever else puts into your critical path, but the language/library/parsing requirements could kill you. (Though people still make this objection to CGI itself, not just PHP...)
The php "maybe process per request, if I'm being dumb, but probably not", vs AWS lambda "business as usual, here is a whole new os instance" is pretty amusing.
Lambda surely doesn't actually boot a new OS for every single request. I thought it stuck around for a set amount of time and you could even ping it to keep it warm?
There are interesting projects such as https://github.com/php-pm/php-pm which sets up a pool of 'warmed' workers to speed this up; I've never used that particular project in production but the approach seems reasonable, many of us are probably already handling background jobs using a similar architecture.
I'm using php-fpm with all production services since 2012 (mainly with nginx, but also with apache), never experienced any problems, so I'd highly recommend trying it out.
php-pm is very different to fpm, imagine running a heavy framework like laravel where it can take 100 ms to bootstrap a request; why not use a worker pool and delegate the request to it? that's php-pm.
Curious about the use of Dependency Injection here. I'm a Python guy and it rarely gets mentioned in my world as far as I'm aware. I always assumed it was mostly an artefact of static type systems.
Can anyone share their insight? Either in the context of Python or PHP.
The dynamicness of languages like Python make it relatively easy to do so. For example, it's difficult in Java to mock an http request if you can't inject a `HttpRequestor` (or so) to the object you're testing.
In Python, it is common practice to patch objects, which means that even though the code calls `requests.get()`, the call will actually be patched through to a mock. (in the Java world, this is possible with e.g. PowerMock, but generally frowned upon)
We used to spend 90% of our time determining the right nail to use, the right wood to use it on, and where best to place it, and only 10% of our time on selecting and wielding the hammer. Now we spend 90+% of our time figuring out which GenericAbstractToolFactoryManagerFactoryInterface to invoke and how to properly invoke it a in such a way as to coerce it to ultimately generate something that eventually might generate something else that will hopefully drive some sort of fastener into something in such a way that will possibly hold it together, and the rest debugging why instead it is generating a generator that generates chisels that are chopping away at the foundation.
Yes, that's an exaggeration, but how much so? We are smart people, we do figure out how to use these complex combinations of systems to build functioning (bloated monstrosities of) applications. But are they really reducing technical debt or adding to it?
Are these systems really going to be easier to maintain in a few years when they have 357 dependencies that have each evolved over time (and or been abandoned)? Easier to optimize, when that means modifying what's going on under the hood of those dependencies? Easier to extend, when doing so would lead to conflicts with those dependencies?
I'm predicting that the next wave of discovery and hype in the field will be focused on improving productivity while reducing technical debt by removing the cruft that we're building now and replacing it with something simpler and more to-the-point.