Hacker News new | past | comments | ask | show | jobs | submit login
PHP 8 (php.net)
472 points by pow-tac on Nov 26, 2020 | hide | past | favorite | 267 comments



Facebook’s backups were written in PHP. Well, the second version was, anyway. (The first version didn’t work so well.) By backups, I mean the central MySQL databases with profile and post information; not media or messages. The “Crown Jewels,” so to speak.

It was written by an engineer in a week or so and then handed off to me. I was a storage guy with some programming chops. Fewer chops than I thought.

Multiprocess, forking, long-lived, server-side, I/O intensive PHP. And it worked brilliantly. Over the following years, it scaled from a backup set of a few hundred TB to many, many petabytes.

I extended the code quite a bit, fixed a bunch of bugs (it was version 0 when it launched, no hate to the guy who wrote it), and added statistics for reports and coverage.

The main reliability problem ended up being when we switched to HPHP, the predecessor to HipHop. Since the primary and largest customer of this code was the web front-end, changes there would often break our backend code. One I remember was changing fork() to only start a new green thread; saved $millions on the front end, completely broke backups. We ended up getting a special posix_fork() function or something from the HPHP team that restored the old behavior.

Eventually I rewrote it in Python 2.7. It took me two complete attempts and then a further six months of tweaking to get it anywhere near as stable as the PHP version, even with brilliant guys like Haiping Zhao constantly re-weaving the carpet under our feet. I never did like it as much as the PHP version.


PHP is surprisingly good at multiprocess and forking. Though their are plenty of things that can go wrong with using pcntl_fork() in regards to memory/sockets.(Most base PHP classes are not written with explicit multiprocess handling.) I have written a couple different message queue/worker systems in PHP with forking and it always surprised people when they ask what language the system is written in.


I'm confused by your use of the term "backups" do you mean backend?


I think they literally mean backups of critical data, managed by PHP code.


Barracuda Backup was also written in PHP - including code to backup VMware servers, receiving data from the Windows agent, and connecting to Linux servers via SSHFS/CIFS, etc.

It worked surprisingly well, using similar multiprocessing techniques.


Can you elaborate a bit on what that code did? You said it a backup system talking to a MySQL? But there was a different front end and a different back end system that were both dependents on it?


Sorry, I wasn’t very clear. The backups were of MySQL databases and we stored them for a period of time (it was in the Terms of Service). When I say “back end” or “backend” I mean internal servers, that didn’t directly take HTTP requests. This means everything from databases to backup hosts to other data stores to dashboards. “Front end” means web servers that did take HTTP requests and served facebook.com. PHP development at early Facebook was always focused on the latter, for good reason.


Question I possibly couldn't ask a more appropriate person: how were the long-running server processes managed?

I really want to use PHP to manage backend-type, long-lived stuff... in a way that is relatively lightweight and self-managing, and idiomatically tolerates the occasional bit of unparseable syntax on script load or mis-named function call, without throwing a hissy fit.

Like... the only thing that'll typically ever knock php-fpm completely over is generally a script-triggered interpreter segfault, which is Bad™, exceptional, and (given php-fpm's collective uptime on all installations everywhere) vanishingly rare. Fatal error? FCGI response message passed upstream. Script exceeded execution time? Hard timeout (and message passed upstream). CLI SAPI? Clunk; no more script execution for you. I've always felt a bit left out in the cold by this, just in terms of how the language itself handles this edge case.

I guess I probably just stop whining and go setup systemd unit files or similar. That would definitely make the most sense in a production environment; I should probably build the muscle memory.

It's just that, for slower-paced and/or prototype-stage projects that don't have a clear direction... my brain's trying to reach for an equivalent of `php -S` that isn't there, and... I guess it's really easy to get idiomaticity-sniped, heh. ("But this project isn't a thing yet... and systemd unit files go in /etc, which is like, systemwide... and I forgot the unit file syntax again..." etc etc)

TL;DR, if this made sense :), did you ever encounter this sort of scenario, and how did you handle it? A $systemd_equivalent, language-level patches, shell script wrappers, cron, ...?

Oh, another curiosity - whenever remembering how pcntl_fork() works I usually have to reach for `killall php` a few times :) (especially when the forks are all using 100% CPU... and I accidentally start slightly too many...). How was killall isolated from nuking important server processes? Shebang line? Renamed interpreter binary (...probably not)? Different user accounts?

Thanks very much for reading :)


I think your first question is asking about something different than we did at the time (PHP 5.x). There was no central process that “ran” the backups—is that what you mean? There was a cron job on each backup server that started the work (systemd would do the job nowadays). The code would figure out what database servers it was responsible for and kick off those jobs, then exit on completion. Reporting and restaging to central storage was another set of crons, and so on. So though they ran for hours or days, the PHP processes had a well-defined start and terminus. The “master” process on each host started the worker children, did some housekeeping, wait()ed for hours, and took note of the exit codes. What you’re trying to do sounds a lot harder.

If you’re missing a magical command that sets up a test environment, I recommend writing it in shell, PHP, whatever, and sticking it in $HOME/bin. Or a makefile with a target so you can just run “make testserver” or the like; that way it will stay with the project. Or scripts in $PROJECT/bin or $PROJECT/scripts. Doesn’t really matter as long as it’s documented in the README and simple to execute. It’s permissible and customary to have a cleanup command, as well, if you started a background process. You could even have those start and stop commands create and then disable a systemd unit—that way you won’t have to look it up every time.

> How was killall isolated from nuking important server processes?

In general we didn’t isolate our processes against signals, because there was occasionally reason to send them. When we did send them, we sent them precisely. If a few kill -9s didn’t stop a backup then there was almost certainly a disk issue on the host and it was stuck on a kernel I/O system call, and we’d “nuke” the host (send it through a self-diagnosis and reimage cycle; cloud analogy: terminate and reallocate). It was definitely a cattle-not-pets environment. Other backup hosts would take up the slack.


Thanks very much for replying! Apologies for response latency...

Cron jobs make a lot of sense for periodic batch work.

It's interesting you used PHP to start and manage child workers (I recall reading somewhere in the docs about PHP being unable to report error code status correctly under certain conditions, but I can't find it right now).

Regarding environment, I was mostly pining about PHP's lack of a "correct"/idiomatic way to handle genuinely fatal conditions (like syntax errors) in a way that meant the binary would stay alive. I'm suddenly reminded of Java's resilience to failure - it'll loudly tell you all about everything currently going sideways in stderr/logcat/elsewhere, but it's "difficult enough" to properly knock a java process over (IIUC) that it's very commonly used for long-running server processes.

PHP-FPM has this same longevity property, but the CLI was designed to prefer crashing. I just always wished I didn't have to bolt on an afterthought extra layer to get reliability. So I wondered if I could learn anything from this particular long-running-process scenario. Cron is hard to beat though :)

Hmm. Automating the systemd unit creation process. Hmmmm... :) <mumbling about not knowing whether su/sudo credential/config sanity will produce password prompts>

And... heh, that's right, `kill` exists. Need to step up my game and stop `killall php`-ing. Good point.

Thanks again for the insight.


I met Haiping at the HipHop pre-launch thing where they brought some non-facebook-folks in to learn about it. I really liked him.


Why did you switch to Python? Surely it wasn't as perfomant and you already had a working solution.


Mainly to get off HPHP and relieve both that team and ours of the constant coordination and toe-mashing. We thought “modernizing” the code would be a better investment than jerry-rigging the Zend engine back into our infrastructure. I think it was the right call.

Also, with Python we could interact with other services using basic Thrift bindings, and even provide our own endpoints. With PHP, all RPCs and queries were prebuilt into our standard libraries with custom glue code that increasingly made non-Zend assumptions. Again, we could have made it work, but we would be swimming against the current.

All the rest of the database management code ended up being moved to Python, and benefitting greatly, so it eventually worked out.

In summary, organizational concerns.


> Mainly to get off HPHP

Did you consider "moving back" to PHP instead of emigrating to Python? Given that the code was originally written for PHP that sounds like the easiest way out of any problems caused by HPHP. Was it politics which led to the decision that HPHP was the only allowable PHP engine?


If we wanted to continue to run Zend we would have had to build out the entire supporting toolchain, from system package up. FB servers at the time ran on an ancient Linux distribution (I don’t remember if it was ever made public so I won’t say) with security patches and a modern kernel, so the system PHP was 4.2 or something similarly unusable. I think our server team eventually disabled the package because it kept causing problems when it was inadvertently installed.

And if we went that route, we would have had to build Thrift bindings and write all the glue code for any other internal service we wanted to talk to. They all had official client libraries, but they weren’t built for Zend anymore, and since they were frequent targets of micro-optimizations, they would no longer run on it. We would have been the sole maintainers of this alternate distribution and libraries, as well. And THEN we would have had to talk to the server team and convince them that it’s cool install this custom package that directly conflicts with some of the most important code we run that’s literally maintained by a team of PhDs and industry luminaries, but we pinky swear it won’t mess up. (Ever built a .deb or .rpm?) That would have been politics, but it never got that far.

Another team had already done the work for Python to “compile” your script and all its dependencies into a self-executing compressed file. All you had to do to talk to another service was import the client libraries, write your logic, run the packager, and ship the binary. (Very Go-like, in retrospect.) It was already widely used and well-supported, as a group effort. I even fixed a few bugs. So, for this particular niche at this particular company, PHP was a victim of its success elsewhere.


Did you use those backups often?


Why? Have you lost some "friends"?


Apparently some of the deprecations will make this the most backward compatibility breaking version jump of PHP since V4 to V5. (Read a german interview here: https://www.heise.de/news/PHP-8-im-Experten-Check-Der-erwart...)

There's a long report on Wordpress and PHP 8 and it's not pretty: https://developer.yoast.com/blog/the-2020-wordpress-and-php-...


Reading the list of things that worry them makes it clear that it's not so much php is breaking bc than it is wordpress lack of cleaning and linting for so long catching up to them.

I mean seriously the first thing they list as a worry is that arithmetic operators will now throw an error when one (and only one) of their operand is an array or resource (eg array + array support remains, it's really int + array or string + file_descriptor, things like that). This is literally a case that makes no sense in the code ever, not one of the "php used to do something magical for us" but "php used to keep silent about this buffonery", so if your code does that you have bigger worries ...

Almost every single one of those things are easy to fix, in that it requires mostly time not much if any redesign, and almost every single one of those things are also deprecated or on their way out since at least a decade.


> it's really int + array or string + file_descriptor, things like that

I haven't personally used PHP in years, but was curious about this. Based on some quick/dumb experiments it appears int + array has thrown errors as far back as PHP4:

- http://sandbox.onlinephpfunctions.com/code/0b2f22ea881b36e58...

- http://sandbox.onlinephpfunctions.com/code/0e5fb752fc3ec28e8...

Is the post talking about some other scenario? Maybe the new thing is that it's now specifically a TypeError?


Yes, was warning / log previously, now it throws. So what was a warning and just going on is now an exception that interrupts.


int + array has indeed been throwing errors for a while for the basic arithmetic operations, but not for slightly more complex operations such as modulo, and there are plenty more weird combinations that used to work:

https://3v4l.org/IuoGO


It also sounds as though the internal type checking is going to be a large developer load as well. In PHP7, internal functions return null for type mismatches, and in PHP8, they raise a TypeError. This means going back through every case where they call an internal function and wrapping it with a try/catch for TypeError, in addition to checking for null. That sounds like a pretty significant workload change.


Or just make sure you pass the correct type to the functions. It's easier and probably more correct as well.


If you rely on type labels on your functions and variables, you should rarely require a try/catch to handle type errors for internal functions.


> This is literally a case that makes no sense in the code ever,

Speaking as someone that hates PHP but still appreciates that it has its uses: You’re speaking from one perspective. There are others. That operation is perfectly valid and well-defined in Matlab where it increments all members of the matrix/vector by the scalar.


But PHP didn't do that, it just silently ignored the operation or returned zero. That behaviour doesn't make any sense.


This is actually a perfect example of why I don't like these magical overloads for what looks like basic mathematical operations.

It's perfectly obvious to everyone what adding 2 numbers does. It works the same in basically any computer language. What happens when you add a number to an array though? There is no universal obvious rule, it depends on whatever was convenient for whoever initially wrote that overload. You just have to remember what it does in this language. Maybe it appends it to the array, maybe it does the operation on the first or last entry of the array, maybe it does it to everything in the array, or does something else entirely. Does it modify the array in place, or create another copy with the change? Woe betide anyone who forgets what it does there or gets it mixed up with another language. Better IMO to at least have functions with clear names for doing these sorts of things.


Did it php use to do that? Otherwise your point is invalid.


> There's a long report on Wordpress and PHP 8 and it's not pretty

This is an awkward side-effect of WordPress core team largely neglecting PHP code quality issues for the last decade or so. With good reason – improving such a large codebase is a massive, mostly-thankless task.


I worked at WordPress for half a year, and I'm no expert, but the code reviews there were more intense than any I've ever experienced. Every line of code gets reviewed before it gets committed, and if the commit is longer than 20 lines or so, it undergoes an additional scheduled review as well as pre-commit review. They also have pretty good code sniffers that ought to catch errors like OP mentioned.

The reason they're concerned, I think, is because they try to protect users who have plugins that came from their plugin repository, where the same code quality rules don't apply. WordPress has always been huge on backward compatibility.


> WordPress has always been huge on backward compatibility.

Yes, and I think that's ultimately the root of its challenges.

A fear of breaking things means WP shies away from large-scale changes that would help it become a modern-looking PHP app.

I wrote this two years ago, and WordPress's basic architecture hasn't changed since: https://medium.com/@muglug/improving-wordpress-with-static-a...


> A fear of breaking things means WP shies away from large-scale changes that would help it become a modern-looking PHP app.

They are strongly advocating Javascript as the future of WordPress right now, so I'm not sure if they would like it to become a modern looking PHP application.


I'm working on some of these "future of WordPress" projects right now, and I don't think PHP is going away any time soon. The JS-future for WordPress is more to do with the editing experience than anything else -- the entire rendering pipeline, backend, and rest API is still PHP, and I'm not aware of any plans to change that.

The main difference with the future of WordPress is that instead of templates (which describe the structure of a site) being written in PHP, they will be written as blocks so that they are user-editable. I would say it's more apt to say that "blocks" are the future of WordPress. The block editing experience is written in JS, but serialized block markup is backwards compatible with HTML, so no JS is needed to render blocks once they are serialized.


Interestingly the one other mainstream language that manages to mess up

- equality

- type coercion

- array handling

and more to the same degree as PHP :-)


> The reason they're concerned, I think, is because they try to protect users who have plugins that came from their plugin repository, where the same code quality rules don't apply.

Then start making the quality rules apply. Or produce code quality ratings for plugins and display them for people to make decisions on.

Making sure that WP can keep working with lower-quality plugins in the name of 'compatibility' just ensures that WP is, at best, a mixed-bag.


It's a tradeoff they've made. Allowing the plugin store to be a free-for-all creates a very low barrier for entry, and the marketplace is thriving and well populated as a result. They've added metrics you can use to assess quality, in the form of compatibility reporting, user reviews, stars, etc.


WordPress core team members and users are welcome to get involved in PHP development and providing feedback on proposals.

They are notably absent, and so people who write modern PHP - or wish PHP was a different language - are the ones influencing language development.


> And so people who ... wish PHP was a different language are the ones influencing language development.

That's definitely been my impression. I used to be a professional PHP developer, still use it occasionally for personal projects, and appreciate the language, warts and all, even if I can't truly say I love* it -- but I'm only half-joking when I quip that PHP has evolved from its roots as a cargo cult version of Perl into a cargo cult version of Java.


> - but I'm only half-joking when I quip that PHP has evolved from its roots as a cargo cult version of Perl into a cargo cult version of Java.

It's a joke in so far as it is funny - but it's absolutely correct. When you only look at the language... When looking at the VM, Java has an absolutely world class VM, with great engineering and decades worth of research poured into it.

PHP has... no such thing.


I was definitely talking about the syntax. I'm not a huge fan of Java (as I suppose the joke already demonstrated), but I also notice how many places start out with PHP or Ruby or Python and end up moving to, if not Java, a language running on the JVM. So I still appreciate it. :)

To give PHP its due, it can be very fast -- although the more you use it "the modern, right way," the slower it seems to get. I can't help but wonder how much of that is an impedance mismatch between "your program starts over from scratch with every HTTP request" and "structure your program so that by the time every class is instantiated and interface is implemented, ten thousand lines of code have been processed with each request." No matter how great its optimization and caching may be, a Laravel or Symfony app just has a whole lot of overhead relative to any framework in another language that doesn't have PHP's zero-state approach.


"by the time every class is instantiated and interface is implemented, ten thousand lines of code have been processed with each request."

Haha so true... the first time I stepped through a running Laravel app line-by-line in debug mode in order to understand it better, I was worried my F11 key was going to wear out ;)


PHP has an initial implementation on GraalVM

That is completely ignored by the community


A world class VM tied to a dinosaur language in which you still have to escape regex metacharacters.


The JVM is not tied to Java, which I think was a large part of adimitrov's observation. Kotlin, Scala and Clojure immediately come to mind. JRuby is also a fairly popular platform for Ruby. There's actually a huge list of other languages that run on the JVM, though.


What are you talking about? Java has raw strings (autoescaping) https://openjdk.java.net/jeps/378 Moreover Kotlin allows to have a state of the art language in a state of the art vm


Having no stake in this, I think that's a mistaken way of going about things. Wordpress is PHP's killer app. If people aren't getting involved, php team should consider outreach.


Part of the problem is PHP has no team. It's determined to be a meritocratic loose organisation of individuals, and so there's no entity to do outreach.

It's not my favoured governance model, but it is what it is.


"There's a long report on Wordpress and PHP 8 and it's not pretty"

I wonder if that's somewhat on purpose. Part of the remaining stigma with PHP is that people cite bad PHP examples from WP.


No, I think WordPress being the most installed PHP application on the net warrants the special attention to it.

https://w3techs.com/technologies/overview/content_management


Not sure I understand. I'm saying the PHP team didn't cede any deprecations to Wordpress this time. Meaning no special attention.


Sorry, I missunderstood what you were writing.

Yes, it doesn't look like they took special attention to WordPress when developing PHP 8.


As a PHP dev this is a really fair comment.

I think the other reason non PHP devs think we are in the dark ages is because when they google it, our documentation looks like it's from 2010. It's a bit of a joke really.


One other thing I always found iffy is the comment section. Why is the information there not reviewed and back-ported into the documentation? Sometimes, as on the page of the `DateTime` class, they actually contain crucial details!


Just tried it on a Laravel project I'm working on, on Windows. Worked flawlessly. On the downside, no noticeable performance improvements.

Report generation times:

PHP 7.4 = 67ms avg

PHP 8.0 = 66ms avg

This is getting the data from MySQL and massaging it for the templates. With Laravel's insane amount of indirection, of course.


Why would you expect performace improvements? Because of JIT? There's no reason to hope that JIT would help with that much, because it's I/O-bound anyways. And function calls in PHP are pretty efficient.



Oh, come on. Did you see the benchmarks? This is CPU-bound code, like multiplying numbers 100 000 times over. This has nothing to do with your typical use case.

And, yeah, performance improvements are always advertised.


>This is CPU-bound code, like multiplying numbers 100 000 times over. This has nothing to do with your typical use case.

I think a lot of people missed this. It's not the usual PHP workload for usual/basic web dev.


I never want to get within a mile of a wordpress website after reading this.


Wow, that Wordpress blog is bad. I have seen a lot of projects add support for PHP 8 in recent weeks and they were all kind of easy. Mostly waiting for upstream packages to be ready.

You get nice warnings for years about stuff to fix. If you ignore them because that is easier, there comes a point where it is so bad that you cannot recover.

I know the Wordpress codebase is nasty. But how and when are they going to fix these things? It is going to be so hard.


Wordpress is a bit special case though as it has tons of very old code and a lot of plugins, some of which aren't maintained anymore.


Reading this list reminds that nobody cares about the tech/engineering decisions of a product if it solves their use case.

That is shockingly poor practice and state of a code base for a product that powers so much of the web


I would like to hire you for a nsd + unbound high performance setup are you available? it seems the email in your profile doesn't work anymore.

do you have telegram or something?


Finally, after all these years, Named Arguments!

https://stitcher.io/blog/php-8-named-arguments


Look, 10 years ago I tried — really tried — to get the PHP team to adopt it. I am glad they finally came around:

https://www.mail-archive.com/internals@lists.php.net/msg4587...

Excerpt of the proposal:

So why am I saying all of this? Well, PHP up until 4 had a reputation for lots of bad coding style, spaghetti code, etc. With PHP 5 and better OOP, this reputation has lessened, especially with the great libraries out there (Zend Framework, Kohana, symfony, etc.) But there is still a problem. We (or at least I) would want PHP 6's reputation to be even better, and the reputation is largely based on how maintainable and cost-effective the code is, which is written by programmers actually using PHP. Blaming newbie programmers is one thing, and may even have some truth to it (PHP is simple - thus attracts newbies) but it's always good for a language to steer you in the right direction by default, and make it easier to write maintainable code.

PHP has a great opportunity to do this, by implementing a very simple change, turning all current PHP 5 code, and all code that will be written in the future, into maintainable code. Moreover, it won't break any existing code, like some other additions to PHP 6 might do. This one simple tweak will make PHP 6 code much more reusable and maintainable, just like namespace support will potentially make future PHP code more interoperable without having to write Artificial_Namespace_Class, like ZF and PEAR do.


Thank you for your efforts back then.

And now you stand vindicated!


Somehow one guy was really sure it will never happen:

https://www.mail-archive.com/internals@lists.php.net/msg4804...


Thanks for that! The only error I see in their implementation is that we can't use variables for the name like:

  $name = 'foo';
  myFunction($name: 'bar');
Thankfully, we can still pass an array with the spread operator like:

  $name = 'foo';
  $array = [$name => 'bar'];
  myFunction(...$array);
I wonder if this would work:

  $name = 'foo';
  myFunction(...[$name => 'bar']);
Thankfully it's rather unlikely that someone would use a variable for the name anyway.

Where this will bite people is when they do meta programming with functions that process functions and function signatures.

Maybe I'm missing something, but I find this to be another tragically missed opportunity. It's just unnecessary friction where there didn't need to be any, which makes me sad. At least they can add variable name support someday, because it's easier to allow something restricted than restrict something that used to work. Hopefully there is a "good reason" for this oversight.



i'm not sure it's a good thing readability wise. I would have liked to see struct definitions + adhoc struct definitions and destructuring instead of that.

Some frameworks like Symfony relied too much on shoving unstructured array options as arguments though, so if it helps making API strictier...


I don't understand why pretty much no language does that these days. I think the argument is that your IDE should do this, and it does in some cases, but still...


You can get a much more powerful alternative for "free" if you support de-structuring assignments (in arguments).

JavaScript Example:

    function test({a,b,c}) {
        console.log(c,b,a)
    };
    
    test({
        a: 1,
        b: 2,
        c: 3
    });
If you have this there's really no need for named arguments anymore. If you add features to your de-structuring, your "named arguments" will have them too (things missing for JS specifically: optional objects, TS support to specify types for the destructured objects inline instead of repeating the entire thing).


It is not more powerful. You cannot do this for example:

    function hello($name='Joe',$title='dear')
    {
        echo "Hello $title $name";
    }
    hello('Sue');
Try here: https://3v4l.org/6MZHh

With your object properties approach, you always have to use the variable "names".


Mixing implicit positional and named parameters is a misfeature. The named parameters should have a distinct syntax like other systems do, e.g. :$ twigil.


Python, Kotlin and C# all support named arguments, and they're pretty popular languages. And also... there's Visual Basic.


I guess you can add dart and maybe ruby and elixir if you accept that they treated as a map/keyword list on the receiving end of the function.

Edit: Ruby apparently made them first class citizens back in 2014. Ive been oblivious to this for years... wow.


Crystal supports named arguments.


There have been 5 major threads about PHP 8 in the last few months:

https://news.ycombinator.com/item?id=24866190

https://news.ycombinator.com/item?id=24235440

https://news.ycombinator.com/item?id=24320024

https://news.ycombinator.com/item?id=24150731

https://news.ycombinator.com/item?id=23955197

A couple of those are more technically specific (to JITs and named arguments) but the vast majority are just the usual comments about PHP in general. Nothing wrong with that, of course, except that there gets to be too much of it.

This is a harder problem than it seems, because popular projects always get generic discussion (btw if you hate something that's still a kind of popularity!) and the alpha and beta releases always get posted and frequently get upvoted for the same (popularity) reason. There's a longer explanation about this here if anyone cares: https://news.ycombinator.com/item?id=23071428.

We downweight generic subthreads when they get stuck at the top of the page, but only sporadically, since it requires manual monitoring. (Btw, emailing hn@ycombinator.com when you notice a generic top subthread in any discussion is always super appreciated! Downweighting those is probably the biggest single thing we can do to improve thread quality.) As for why generic discussion is worse: it's repetitive and contains less information. More on that:

https://hn.algolia.com/?dateRange=all&page=0&prefix=true&sor...

https://hn.algolia.com/?dateRange=all&page=0&prefix=false&so...


Thanks for the explanation – I was wondering why it jumped from the top spot.

This particular post might want to get a reprieve – not because the discussion is interesting, but because the news itself – PHP 8.0.0 being released – is reasonably important.


See also the splash page: https://www.php.net/releases/8.0/en.php


Out of curiosity, why match expressions became popular for non functional languages? Without pattern matching on datatypes via cons expression (x::xs matching) it is just another kind of switch or if/else. Why do people promote this? here a nice comment on this topic: https://ocaml.org/learn/tutorials/data_types_and_matching.ht...

"So one Really Cool Feature of functional languages is the ability to break apart data structures and do pattern matching on the data. This is again not really a "functional" feature - you could imagine some variation of C appearing which would let you do this, but it's a Cool Feature nonetheless"


Pattern matching has been proposed in a separate RFC: https://wiki.php.net/rfc/pattern-matching


It simplifies the expression of if/then/elsif/elsif/else, even if it's not total.

Why not steal it?


One reason to not add it might be that it makes the language larger and more complex.

Also, the semantics of match are a bit different than the similar switch, since match does strict type checking and switch doesn't. While this isn't bad as such, it's kinda confusing that the language doesn't behave consistently.


but why all of a sudden languages started to add this? Maybe the function itself needs to be simplified, maybe there is a design issue. i am failing to see how "if else" can be simplified via a synth sugar.


It's a switch statement that's an expression. That's a nice ergonomic improvement when you want to assign the result to a variable. Especially as it allows you to use a non-mutable variable whereas otherwise you'd have to make it mutable.


I wouldn't compare it to a switch statement, because a switch statement - even though it looks similar - has fundamentally different control flow.


one benefit of match over switch is that it uses === and not == internally. So it does not suffer from type coercion problems.


One reason for PHP specifically is that in PHP switch performs type coercion whereas match does not.


> 0 == 'foobar' // true

That's PHP7 behaviour that's updated in 8 to return false. I'm not a PHP basher, I really like it these days, but why the heck was that example ever evaluating to true?


'foobar' is coerced into a number, which fails for the obvious reason. So it becomes 0, which means the expression is "0 == 0".

Terrible, terrible, behaviour but there are lots of similar examples in PHP because it evolved over time rather than being designed as-is. Some of these things are being fixed over time, like this very example, others can't/won't be.


> Terrible, terrible, behaviour but there are lots of similar examples in PHP

So true.

One I ran into recently was comparing hashes that start with '0e' and contain only a numeric component after that prefix. Failure to use the identity operator means that you can have two different hashes returning... equality. PHP apparently thought it a good idea to coerce that into 0 raised to an exponent, which of course always yields zero. e.g.:

    php > var_dump('0e41235843934' == '0e61193475532');
    bool(true)
Yeah, I know: The correct (and only) way to write this is to use the identity operator (===) but it's not at all intuitive. For those of us who are used to this it's fine since it's a force of habit, but for those who aren't it'll lead to unexpected behaviors. The only saving grace is that the quality of PHP code out there has been slowly (slowly!) improving over time, thanks in part to composer and ecosystem/cultural changes.

But it's also not outside the realm of possibility that someone won't eventually forget to add an extra '=' and induce a very difficult bug to isolate...


Is this fixed in php 8? I did not think this was possible as there is no type coercion and not well documented. [1][2]

Noticed "0.2" == "0.20" as another example

[1] https://www.php.net/manual/en/language.operators.comparison.... [2] https://www.php.net/manual/en/language.types.type-juggling.p...


> Is this fixed in php 8?

I don't know. It's one of those cases where fixing it to do the "right" thing would potentially break a lot of software depending on this sort of erroneous behavior. Part of me wants to say "I hope so" and part of me is kinda terrified at what might happen if they did. Shouldn't be difficult to fix, but it would definitely take some time.

Someone should know if there's a decent linter that would pick this up to make it easier to fix, I would imagine!

> I did not think this was possible as there is no type coercion and not well documented.

I think when applying the equality operator (==) in lieu of the identity operator (===) between strings PHP uses heuristics to decide what to do. If it looks like a number, it coerces it into an int or a float. As an example:

    php > var_dump('1e12' == 1e12);
    bool(true)
As ridiculous as I think it is, I also take the approach that it's just what PHP does. Weird, maybe a bit eccentric, probably a contributor to difficult-to-find bugs, but it's just something we have to keep in mind. Perhaps I'm feeling charitable because it's Thanksgiving!


It is well documented that strings are converted to integers when comparing with integers.

It is well documented that when converted to integers, strings containing a number at the start will be converted to that number, and drop any string after, e.g. '1eabc' becomes 1.

It's also been a best practice for a looong time (since something like PHP 5.4) to use === to test for equality.


> It is well documented [...]

Yes, it's documented, but it doesn't make it any less obnoxious. IMO the thought of implicit conversion is absolutely asinine.

But, in fairness, PHP isn't the only language that does this. Python, at least, is more sane.

> and drop any string after, e.g. '1eabc' becomes 1.

In defense of PHP, it does yield a NOTICE if you attempt to apply certain operations to implicitly cast strings (e.g. addition), so there's that.

Suffices to say that while I've written PHP for years, I'm quite comfortable with its idiosyncrasies, it doesn't mean I don't find them appallingly brain damaged. :)

FWIW the identity operator (===) is also a best practice in JS for nearly identical reasons which also exhibits similar (and in some cases nearly identical) implicit casting.


Yes, implicit conversion in both PHP and JS are brain damaged by today standards, but that's life with legacy cruft.


> but that's life with legacy cruft.

So true.

I can't really complain. Well, I can, and that's what I've been doing in much of this thread.

It's mostly just yelling at the sky for no good reason other than to make myself feel better at this point, if I were to be completely honest with you.


Still in js "0.2" == "0.20" would always be false. My instinct would be that comparing two different strings would be false in php too.

The problem for me is working with a big legacy codebase. I'd rather have php break backwards compatibility and change === to ==.


> Still in js "0.2" == "0.20" would always be false. My instinct would be that comparing two different strings would be false in php too.

Nope.

I wish I were kidding. This is where PHP diverges from JS in a way that really will surprise people coming from JS (PHP7.something):

    php > var_dump("0.2" == "0.20");
    bool(true)
> I'd rather have php break backwards compatibility and change === to ==.

I have mixed feelings on this.

On the one hand, I desperately want to agree with you, and probably for all the same reasons. On the other hand, languages like PHP with their dynamic typing system make implicit conversion almost a necessity to retain the identity operator (===) because they strive not to break "too much" (for some value of "too much").

Although, I'd imagine your argument is akin to "well, just cast it to what you expect" (e.g. `(int)$_GET['value']`), and you're right. That's how it should be done, of course.

But, as you mentioned about legacy code bases... sometimes it's not that easy.


I see. This change prompts me as something that could break a lot of code running on web servers where the sysadmin updates to PHP8 assuming it will be backwards compatible. I wonder if they did any code searching to see how widely used such expressions are in the wild.


I don't think anyone reading the migration guide [0] is going to assume their app/lib is backwards compatible without some effort.

[0] https://www.php.net/manual/en/migration80.php


And anyone that knows the basics about semver


And people say C++ is a complicated language.


Yes because ('0' == 32) returning true makes more intuitive sense. There are languages without type coercion for comparisons (e.g. OCaml), but C++ isn't one of them.


In the absence of strict type checking it would be terrible, but == performs a loose comparison, and "foobar" cannot cast to any other number than 0. Perl will go about it the exact same way. Contrast this against strict comparison, "0" === 0, which will evaluate as false.


>Perl will go about it the exact same way.

No, Perl is completely different and IMO it's the only mainstream dynamically typed language that has sane comparison operators.

Perl has two sets of operators, numeric (==, +, *, <, >, <=> etc.) and stringwise (eq, ., lt, gt, cmp etc.). You can think of them as explicit (but concise) casts. For example, Perl's $foo eq $bar is roughly equivalent to Python's str(foo) == str(bar).

It is true that "foobar" == 0 returns true in Perl but, as I showed above, it does that for a completely different reason.


Maybe "foobar" should evaluate to NaN.


Does PHP have separate int and float types? NaN is a float value and I would expect 0 to be an int.


It does


I'm kind of surprised they'd change a core language semantic, even in a major update... won't this make upgrading to PHP8 for a large codebase hard to do with confidence?


That was certainly a concern. When instrumenting PHP to detect where the behavior changes and testing various codebases, I found that this actually happens much more rarely than I would have anticipated in advance. We're talking like 2 occurrences in the test suite of major frameworks.


Strict types (scalar type hints for method signatures) have been around since PHP 7, and since then I would say it is recommended to always use === (with type check) over == (no type check) so one would have enough time to upgrade it‘s code.

And it also just makes sense from the language design perspective to fix that behaviour. Having a major version coming is a good time to fix such stuff imho.


Strict comparison operators have been considered best practice since well before 7.0


== is loose type.

=== is strict.


Is there any way to force the use of ===


Write `===` when you want to compare things.

There is no way to disable the `==` operator or make it do strict comparisons (yet)


    declare(scrict_types=1);


That isn’t what that does.


Enforce by code style tools.


Just a guess, but casting a string that's not a number to int would give you zero?


because (int)'foobar' is 0


JavaScript and php have the === which doesn’t try casting types.

Php has good documentation with examples which I appreciate :

https://www.php.net/manual/en/language.operators.comparison....


I suspect they copied that behavior from Perl.


Perl avoids this problem by having contexts, a bit like casts but with easier syntax, and by having separate numeric and string equality operators.


Is there a reason returning undefined instead of true in those cases (string doesn't look like a number) would be worse?


Very few functions in Perl does that. It will emit a warning instead.

As to why that is, perhaps someone with more Perl knowledge can chime in. I suspect it has to do with undef being inconvenient for signalling failure, since its evaluation will be context dependent (an array of undef is true but a numeric undef is false).

Type conversion is built into the language at a fundamental level. Languages that borrows the syntax but not the type model can be confusing in cases, but Perl is pretty consistent once you get the basics.


I'm pretty excited. though we've just moved off 5X at work (slow on the uptake..)

I like php. It fast enough, easy to learn (we've had new people pick it up).

Its my goto for web development, with some of the frameworks, it seems to have a balance of control and automation I like. Really like symfony for its forms and twig templating engine. Symfony makes a lot of things easy, but is flexible enough when you want to change something. (We like writing native db queries with pdo). It has a package manager (only 1 really, which makes that choice easier)

I continue to poke around with react and view js but if I end up using one, I'll just make synfony my json serving backend.


I've never used PHP. Now I'm learning it with Laravel for my personal project. This is after using C++ with ASP, C# with ASP.NET, Java with Spring and Spring boot at work.

The promise of rapid development is the main draw.


I find it really weird that the match expression is strict comparison, but everywhere else it's loose comparison. Don't get me wrong, I prefer strict comparison, and prefer strongly typed languages because of it, I just feel that this is a strange design choice.

In addition, the @ operator seems to have functionality changed, and there is plenty of other backwards incompatible changes to go along with it, and yet, one of the main reasons to not choice the @ symbol for annotation/attributes was because of backwards incompatibilities. Personally, I find the introduced syntax for attributes terrible, especially when @ is well recognised in the php community thanks to phpdoc annotations.


> I find it really weird that the match expression is strict comparison, but everywhere else it's loose comparison. Don't get me wrong, I prefer strict comparison, and prefer strongly typed languages because of it, I just feel that this is a strange design choice.

What is "everywhere else"? You usually explicitly need to specify the type of comparison you want by writing either == or ===. "switch" is a case where the comparison operator is implicitly "==". "match" using "===" instead is one of the primary reasons for introducing it.

> In addition, the @ operator seems to have functionality changed, and there is plenty of other backwards incompatible changes to go along with it, and yet, one of the main reasons to not choice the @ symbol for annotation/attributes was because of backwards incompatibilities. Personally, I find the introduced syntax for attributes terrible, especially when @ is well recognised in the php community thanks to phpdoc annotations.

The only change to "@" is that it no longer suppresses fatal errors, which was generally not an intended or useful effect. The only thing this affects in practice are error handlers that don't check for error suppression being active correctly.

The "@" operator is still very much needed for certain use-cases (e.g. I/O functions may throw expected warnings) and removing it was not even a remote possibility for PHP 8, and as such also not a candidate for the attribute syntax.

It is worth noting that PHP uses the same attribute syntax as Rust does.


Not a PHP dev, but I read a lot of it for work: based on the example provided, I gather the PHP community accepts that the non-strict behavior of ‘switch’ was undesirable, but it would be too difficult to break the non-strict semantics in an existing construct.

Likewise, the fact that ‘match’ is an expression rather than a statement encourages stricter semantics: although it’s technically unrelated to the type coercion issue, ‘match’ expressions should be easy to reason about locally, which isn’t the case for switch statements. This idea is encouraged by the fact that ‘match’ branches can’t continue across multiple lines: although technically ‘match’ could mutate some complicated global state, the intended use case is a constant or a simple function - easy to understand, and relatively gotcha-free. Gotchas should go in a ‘switch’ statement.

Seasoned PHP devs aren’t going to accidentally use the brand-new ‘match’ statement without careful study, and I don’t think the inconsistency is too big of a deal for newer devs: the overall principle is that ‘match’ is safer than ‘switch’ but less powerful.


Php was my first language I learned 15 years ago. On that way I really started to hate it because of all it's quirks. Many of those have been fixed and nowadays I really enjoy it again and it's my goto language for any web project.

It really hits a pragmatic sweetspot. It's really easy to deploy and frameworks like symfony give you all the power like rails but without the magic.


I must be very picky, because to this day I still don't like it at all. It sucks less than it used to maybe, but if I compare it to other languages, I still would rather use anything else.


I think you have to do webdev to really enjoy it, I never write PHP unless it's something with laravel.


As usual, it really comes down to personal preference. In the past year, I have managed a few things in Wordpress, wrote my own PHP, Flask and node sites; and after all that I would 100 % choose Flask or node over PHP.

Node has the advantage of same language back and front, "asynchronous" execution and having both dynamic typing and static typing with TypeScript. And huge ecosystem obviously helps as well.

Python also has pretty sizeable community and Django is probably a huge reason why a lot of people choose python over anything else. And the syntax, at least to me, feels much less cumbersome than PHP. But I have not tried PHP 8 at all.


I like flask and express, there are simpler than php franeworks like laravel so I can see why one would prefer using them, but django is weird and I could never get used to it. I always felt like there was too much magic.


Curious if that's a general aversion to dynamic typing, or specifically PHP.


The problems with PHP aren't really with the concept of dynamic typing as such, but rather with the somewhat curious semantics and really awkward standard library. These are relics from the past that are, unfortunately, very hard to fix without a "Python 3000 moment", and all the problems that brings. Although PHP 8 does fix a bit of it (various comparisons and operators are a bit better now) there's still a lot of it remaining, especially in the standard library IMHO.


They're a bit overblown now I feel, and I wouldn't throw out the language and ecosystem just because a comparator got fussy. You probably won't win any "Code is Art" contests, and if you want to do computer science work then why even waste the time hating PHP, it was never for that. PHP is a web application workhorse, and it's really exceedingly good at that task.


It's not just the comparison that's fussy; if that would be it then that would be fine. It's mostly the really messy, inconsistent, and difficult to use standard library that turns me off personally. And this isn't about inconsistent argument order or naming, I can deal with that as well, but stuff like not being able to create temporary files well, or not being able to check for specific errors in fopen(), and a long list of similar things. These are things that make writing simple, correct, and elegant programs very hard, or sometimes even impossible.


That's what I was trying to make sure I understood. There are people that just don't like dynamically typed languages.


PHP offers some type checking (and has for a long time, albeit very limited) which is getting expanded all the time, including in this release.


Nothing in their comment suggests anything about typing. They might love JavaScript or Python for all we know.


Same here, started off with PHP around a decade ago and couldn't wait to move to another server-side language. Nowadays it's much nicer to work with (as long as you avoid the warts) and PHP 8 looks to deliver another slew of welcome upgrades.

Only downside is that there does seem to be quite a lot of (non-trivial) deprecations which is understandable but I wonder how long it'll take for 8 to percolate into production...


Every single deprecation is a wart being removed, none of them are a python 2->3 kind of issue (it worked just fine but now I need to work to move it to the new stuff !), and it's all easily fixable in your code with minimal effort (but decent amount of time ... if you've not bothered to clean up warnings for the past decades).

The cases that are not replacable easily are things that should never have been written ever.


Same here, I started at the same time also with PHP.

But I never found back to PHP after switching to JavaScript in 2011. If something new comes out it usually runs JS.


One nice thing about php compared to Js is that you are not allowed to write async code. (except you use some extensions) So everything is simpler by design.


True.

On the other hand, most systems I worked with were async, so they fit really well into the JS model of programming.


Same as many web languages, PHP's heyday has a reason as many toolkits at that time were far less powerful and complicated for even simple things. Perl+CGI + all the server setup for a simple dynamic page? It's just unimaginable to many today's developer.

I started off with PHP3 and have a very great and hated time with it till v5. PHP for sure is difficult to maintain and very painful to debug, but it's not my reason leaving it. It's because JS began to pick up and started to do many tasks that requires no server rendering. The server sides started to become just API server, which no longer generate html on the fly. It's much scalable and easy to maintain.

Time flies, now I see the release of PHP 8 and I realise I have ditched it for a decade. Do I miss you? No.


> Perl+CGI + all the server setup for a simple dynamic page? It's just unimaginable to many today's developer.

TBH, I'm still not aware of any truly simple/easy way to get a dynamic HTML page.

Recently, I had to make a dumb utility app to render some dynamic data, and I wound up writing a Golang server with the HTML specified as a Go Template. But making it accessible on the publc internet still required spinning up a server, installing nginx, configuring SSL with Let's Encrypt (at least it was free) and futzing around with nginx `proxypass` directives for several hours.

It works, and I guess it's conceptually simple, but it was still an all-day ordeal to get it up and running from scratch.


That’s PHP’s wheelhouse.

If you don’t want to just use some shared hosting, grab any server and use the package manager to install Apache + PHP.

Drop HTML in the web root.

Whatever part of the page is supposed to be dynamic, you can literally just start throwing code in the middle of the HTML, mixing it all together freely.

It won’t be beautiful, but you can go from nothing to this in like 30 minutes or an hour.


Have you tried Caddy as your reverse proxy? It's much simpler compared to nginx and it has very robust, integrated LE support. It's also packaged for Debian and CentOS now.

Write a systemd unit file for your golang service, put Caddy in front of it and you are good to go. It's not a PaaS, but it's simple and shouldn't be too difficult to maintain.


> Write a systemd unit file for your golang service

Oh yeah, I forgot I had to do that, too! Another step.

I'll take a look at Caddy!


But now you know it. I do all that stuff for all my personal projects, but it is much faster because I already have servers and I have done it a couple dozen times now. I'm getting to know proxypass and caching directives very well. My first time took hours and much futzing. Once it becomes routine, I automate. I wrote my own build server in JS and bash, it handles webhooks, roll-back on fail and notifications. I've been meaning to mess with ansible.

It has even come in handy at work. I'm primarily a front-ender, but a start up I worked for had me continuously deploy my application to my own personal infra so it could be used immediately.

It is an ordeal at first, but nginx is so darn powerful it makes me feel like a wizard. If you want to avoid the arcane incantations, I'm sure Caddy would be a simpler option.


Azure Static Web Apps and then a bit of AJAX to pull in the data from a function (all deployed automatically in one go)

https://azure.microsoft.com/en-us/services/app-service/stati...

Not a dynamic HTML page per-se but a page with dynamic data.

I deployed one of my old hackathon apps with it, works well - https://memorylane.benbristow.co.uk/


What do you mean without the magic?


Ruby is extreme flexible in terms of metaprogramming in rails uses that very much. And ruby is not statically typed.

So if in rails you declare an active record model with belongs_to etc it's hard to keep track of what is really happening under the hood.

In php you have almost no runtime metaprogramming so the things that could happen if you read a piece of code are reduced to a smaller set of options that are easier to understand. well you have reflections but at least they are used in a more static way.


Ruby also raises an exception for a string coercion to an int when the string isn't an obvious int.


That's a local effect that can be avoided once you know the sematincs of the language. The issue with abused metaprogramming and monkey patching is that it results in global effects that are hard to track.

I would prefer to review a messy 50kloc php project over a messy 50kloc ruby project.


I was citing it as a good thing versus PHP's (and Perl's) "foo" == 0;// true behavior. I believe that still to be the right thing despite other issues Ruby has.


Then I agree of course!


I think they mean stuff in Laravel framework and Ruby on Rails. Like database access where you can just use it as an object without worrying about queries and such. This is great, gets projects up fast.... until you need to do something different. It generally comes at the expense of flexibility.


Most ORMs allow you drop down into RAW for all or part of the query, so you haven't really lost any flexibility.


How should one start learning with PHP these days?

My experience: hacked together a few PHP scripts over the years to notify me of a website change (5 minute cron job). Before that, I was a very good beginner with VB6 back in highschool.

There are a couple of ambitious database-driven website projects I would like to create, but I don't know where to start. I like the KISS philosophy, and I think PHP and MySQL would fill that. Is there an obvious alternative that I'm missing?

I was thinking of hoing through the w3schools PHP turtorial. Is there a better or more up-to-date resource?


It hasn't been updated since April 2020 but this website used to be a good resource for "modern PHP":

https://phptherightway.com/


Modern PHPs shining light is the Laravel framework and the ecosystem built up around it. If you're going to start a database-driven website projects in PHP there really isn't a good reason to not use and learn Laravel (or Lumen if you want something more lightweight).

That being said if you're not tied to PHP I'm not sure I'd necessarily recommend it. The obvious alternatives worth looking into are Ruby on Rails or Python with Flask or Django.


> PHP there really isn't a good reason to not use and learn Laravel (or Lumen if you want something more lightweight).

12 year professional PHP developer (in that it's been my main language, I've also written a lot of C# and TypeScript in that period) - I'd pick Symfony for any project I knew was going to last more than a few years before the inevitable re-write.

The problem is you don't see the difference until you've seen multiple large codebases implemented in both frameworks.

Symfony is harder to bootstrap a project with (though not really that true since 5) but in nearly every other way it gets more right than wrong.


Laravel is good and bad for the ecosystem at the same time. I've interviewed a lot of people lately who know laravel but not php. Similarly to people who claim they know react but fail in the most basic js questions.


Additionally Laravel abuses patterns like singletons and in general static methods. This is really a no-no for modern PHP, in my opinion. I think Symfony had a way better impact on the ecosystem.


To be fair, Laravel’s facades look like static method calls, but they’re actually not. They’re backed by the service container and can be swapped out for mocks etc just as easily as injected dependencies. They’re also totally optional, and in general are falling out of fashion within the community.


I could just never get used to Ruby syntax and how wordy it is.

PHP/C/perl-style syntax just feels much nicer/more natural to write and I've never been able to break out of that.

I guess it comes down to personal preference and what you started coding with.


Ruby "wordy" compared with PHP? You have to be joking. PHP is pseudo-Java in terms of verbosity. It's even worse than Java with its culture of space-wasting blank lines and fanfold doc comments.


Is Laravel better than Symfony? When I used PHP, the Symfony components were the best in the ecosystem.


"Better" is relative. Laravel is built on top of Symfony components FWIW.


> How should one start learning with PHP these days?

there is learning PHP and its standard lib, learning how to avoid all the PHP pitfalls (because there are a lot of them when it comes to webdevelopment) then learning some mandatory framework because that's how you get an actual PHP job. These 3 things are separate tasks.

For the first frankly it's the documentation + stackoverflow, the second is https://phptherightway.com/ , the third is the documentation of whatever framework you are using. Final step is to learn how to use whatever server that will front your PHP app, Apache or Nginx.


>w3schools PHP tutorial

I think a better approach is to think of a (very basic) project you want to create, and then claw and bite your way through it, until you have something that works. Then think of a way to enhance it, and go though the process again. Slogging through a tutorial is boring, and you have nothing to show for it when you're done.

PS: Don't listen to sneaky JavaScript evangelists. Wicked! Tricksy! False!


Lol, I appreciate everyone's advice, and I'll have to do research on it all to see what will work best for me.

I'm just reminded of Derek Siver's experience where he started CD Baby with PHP, and then tried rewriting it in order to use something other than PHP just because, but ended up sticking with PHP. Though he is a musician and not a professional programmer. However I'm not a professional programmer either, and I don't really want to become a sys admin to maintain the servers etc.


Agreed, that's how I learned. Also run it by someone that knows PHP so they can yell at you. I've used prepared statements ever since then


Have you considered SQLite? PHP has support for it built-in (php-sqlite3 package in Debian) and you wouldn't have to manage a database server. Concurrent requests should be fine since SQLite does R/W locking and supports transactions.

I can't personally comment on how well it works for websites but I have used PHP+SQLite for local ad-hoc GUI apps and it was a pretty nice experience.


My recommendation is to become familiar with the package manager composer

https://getcomposer.org/

Almost all community code today is distributed with composer, anything from libraries to frameworks. Regardless if you write almost everything yourself or use a full featured framework, composer is always good to learn.

And even when you are a follower of KISS there always things that you don't care enough about to write yourself, boring things like logging frameworks (Monolog https://seldaek.github.io/monolog/) or testing frameworks (PHPUnit https://phpunit.de/). And composer can also help you set up class autoloading, a must for modern PHP.

Here you can find packages to download with composer https://packagist.org/

Next I would look into different frameworks, not necessary to use them but to learn about them and from them. The 2 biggest today is Symfony ( (https://symfony.com/) and Laravel (https://laravel.com/). But there are others like Slim (https://www.slimframework.com/), CakePHP (https://cakephp.org/), Zend (https://framework.zend.com/) and many more. Try a few and get the feeling how they do things and if you like them.

For view rendering you can do that with PHP out of the box (just remember to escape output!) or you can use a template engine like the more advanced Twig (https://twig.symfony.com/) or the simpler Mustache (https://github.com/bobthecow/mustache.php). Plates (http://platesphp.com/) uses native PHP templates but helps you create reusable layouts. Some frameworks include a template engine, e.g. Laravel uses Blade https://laravel.com/docs/8.x/blade.

For database queries I recommend reading this excellent article

https://phpdelusions.net/pdo

Many frameworks include their own query builders and sometimes a database layer (ORM).

Some semi famous people within the PHP community just released a PHP 8 book, I have not read it though.

https://front-line-php.com/

They also have free videos about PHP 8

https://spatie.be/videos/front-line-php

Ask for help https://www.reddit.com/r/PHPhelp/

Discussions about PHP https://www.reddit.com/r/PHP/

Online PHP shell https://3v4l.org/

Good luck!


Thank you for the very in-depth reply!


Keep hacking, learn from your own mistakes, do this for 10 years. By the end of that time you should, for example, understand why we use Postgres instead of MySQL. :)


Every language I think about is better than PHP (Javascript, Python, Ruby). Personally I will choose Javascript / Node JS platform to start with.


why? Those three come with the same amount of quirkiness and issues. There is a reason why you have Typescript or golang, for example.


Typescript is just a much improved javascript, to the point of these two just being two dialects of the same language. I wouldn't make a distinction between the two. Performance-wise, as a servrr-side language, they both have the same strengths and weaknesses.


I got spoiled by PHP as my first language. It was so easy to get going. I was surprised to learn that other languages didn't work the same way, when integrating into a web server. Also it has always been rock solid. A bug in my code brought down only that request for that user, totally did not affect or even slow down responses to other users.

People have attacked its syntax forever. I avoided the worst of it by learning PHP around version 4, when it was moving away from magic quotes and register globals --- and I also had the sense to see that those were unwanted anyway. But I think the main reason that PHP hasn't bothered me is that I try to use it as little as possible. Let me explain.

I consider PHP a glue language, between my database and the user's browser. When you use a lot of glue, things get messy. I try to push things out of the middle layer to the edges, if they will fit. So I try to do a lot of data preparation in the database, through fancy queries, so that the data is mostly ready for the HTML template by the time it is received by PHP. It helps that my database is Postgres. For authentication, I try to lean on Apache, so that PHP would just have to consult the CGI variable REMOTE_USER. So PHP acts sort of like an extension language to Apache (even when I'm using PHP-FPM instead of mod_php). It takes the data from the database and wraps it in HTML. It takes the form submission from the user and hands it to the database (and most server-side data validation is in the database).

The people attacking its syntax sound like they are writing an awful lot of PHP per app. And maybe for some things you have to, but not for CRUD apps, I think. I try to keep the middle layer as thin as possible, and I would do that whether it was PHP, Python, or Perl.


> I was surprised to learn that other languages didn't work the same way, when integrating into a web server

Oh boy... I'm still not sure how you deploy a non-PHP webserver to be honest... every language seems to be doing something different, with php you just needed to drag & drop your files in the "public" folder.


It's pretty simple really. With php, your php sites consist of some php files that will be run by a webserver (apache, php-fpm, etc). When the webserver receive a http request, it will executes a php file that matched the request url, pass it the request body as input and send back the output as request response. On other languages, your app is typically deployed as the webserver itself, handling request directly (or indirectly with a reverse proxy in front of it) without executing any external process or terminating after each request.

The php model is simpler and easy to reason with, but many use cases in modern web development is not possible in this setup and requires you to write your app as a long-running webserver process (e.g. websocket model).


> I'm still not sure how you deploy a non-PHP webserver to be honest... every language seems to be doing something different

Coming from PHP and having used a bunch of different languages I can understand what you are saying.

Unlike PHP, the other languages run in a process that listens on a port (80, 443 or another). The single process continuously run and handles multiple requests.

Back then, I still had to use NGINX or Apache with PHP, and in retrospect I find that more difficult to understand than a script that listens on a port.


Caddy largely solves that problem. A config for a PHP app is usually about 4 lines long, see the example on this page: https://caddyserver.com/docs/caddyfile


I've never thought about it this way before, but it makes sense! I think I've been pushing things from the middle to the edges subconsciously but didn't have a solid understanding as to why. I got something out of this, thank you!


REMOTE_USER as in HTTP Basic auth? the ugly login prompt you can not logout of again?


That is one way, and I agree it's ugly, but Apache came out with form-based authentication in version 2.4, https://httpd.apache.org/docs/2.4/mod/mod_auth_form.html


Oh thanks! That's nice.


In my app, I use basic auth in place of captcha.

Every useragent going back to IE3 and NN1 support it.

I then set a cookie, and users never see the prompt again.

Cookies are sent on the first request, before auth happens.

In my extensive testing, even the most "non-techy" people are able to complete this task, while most bots fail at it.

If any bots start getting through, I can change the password.

For visitors I haven't met yet, I can give out guest credentials on the 401 page.


This Firefox extension adds a logout button:

https://addons.mozilla.org/en-US/firefox/addon/http-auth-enh...


you are doing it right. if you want to use fancy jargon for what you're doing say "I use apache as the controller, the database as the model and php for the view". that's how it's supposed to work since the first version of php/fi. php is primarily a templating engine.

but I disagree concerning register globals. I think it was the single thing that made php the most accessible language. we should bring them back but as a special variable with it's own prefix instead of $


Where's the best place to suggest a new feature or improvement for PHP?

I've always wanted to see `foreach` get a built-in iterator/counter so you don't have to create and use a counter variable manually.

Current way:

$i=0; foreach ($array as $key => $value) { echo "Loop $i of " . count($array); $i++; }

Possible new way:

foreach ($array as $key => $value, $i) { echo "Loop $i of " . count($array); }


For that code snippet specifically, you're actually better off pre-declaring the vars since the loop repeatedly calls `count($array)` but hopefully(!) its size doesn't change over time.

Is there such a function in php like "enumerate" in python, that yields a tuple of (counter, item) for each item in the first argument to enumerate? That is to say: is it possible to do what you're asking with composition rather than a language change?


Since count is it's own opcodes in the VM and php hashtables keep the number of elements around and don't have to be counted there shouldn't be much difference between reading a variable and calling count.

(Since some time in PHP 7, before that count() went via function call overhead)


https://wiki.php.net/rfc

IMHO that array/map data structure is one of PHP's biggest sin. So many bugs as the result of it and it makes a lot of codebases barely readable.


While not quite as ergonomic as your example, it's rather trivial to extend ArrayIterator to accomplish your goal:

    foreach ($iter = new IndexingIterator($array) as $k => $v) {
        echo $iter->index();
    }


You can do it very simple by writing a custom generator function:

foreach(myfunc($array) as list($key, $value, $loop)) {}

Maybe you can array destructuring at this place, i am not sure at the moment.

And your manual counting you do in myfunc() and just yield the values


I can't believe nobody has pointed out (yet) that PHP is the quintessential lambda :)

That said, it's been many (many, many!) years since I moved away from it, but I'm intrigued by the state of the JIT and the current coding style (last time I checked, around 6.x, it was growing to be verbose and full of backslash-adorned-namespacing).


"PHP was serverless before there was serverless"

However there is a difference: PHP has no deployment system included. But if you build that (not too hard) the difference isn't big ... (But with Lambda&others you outsource the management)


> PHP has no deployment system included.

SFTP? I mean, it's not included in PHP, but any linux system has it.


SFTP, rsync all work, to some degree NFS also is an option.

However that's just the technology. You need to build a solution around it, which monitors load and deploys the code as needed and scales down again and eventually in PHP you'd also expect that PHP Session management is integrated ... all doable and people did. The selling point of lambda is "it works" and "not your concern" (with the corresponding downsides)


Yes, the worst aspect of PHP is how a lot of library code uses fully-qualified namespaces inline instead of a "use" declaration at the top of the file. I've never understood why.


PHP 6 was never released, you are probably thinking of 5.3+


"Sometime before 7", yes.


A lot of the syntax of new features and features themselves are very close or identical to C#, which is a good thing in my book. It’s nice to see the language evolving in a more typed direction while still being super fast to start a project with.


I still love you PHP


Me too. For people on shared hosts (hundreds of small websites including small businesses), PHP is pretty much the only server-side language that you have access to (well, maybe aside from Perl).


I haven't touched PHP for a long time now. How is the Unicode support now? I remember having to use some special utilities to handle characters like "œ" properly.


You cannot use the "basic" string manipulation functions (strcmp, strlen, etc.) because these are not unicode-aware.

However, you have the multibyte string functions family that can operate in a wide range of encodings (including UTF-8 which is the default in any sane installation nowadays).

[1] https://www.php.net/manual/en/ref.mbstring.php


I think I had issues even with mbstring, for some characters like "œ". But maybe I'm wrong.


œ works fine with mb_strlen(). What might have been tripping you up is combining character sequences:

https://3v4l.org/DM4pC

Handling those "correctly" with a string length function gets complicated in any language, as there isn't a 1-to-1 mapping between Unicode codepoints and visible glyphs.


In PHP grapheme_strlen achieves what you're describing: https://3v4l.org/HPOb3


Yes, I think you nailed what my issue was.


I wonder what makes the Symfony Demo App not being faster with the JIT compiler (as shown on https://www.php.net/releases/8.0/en.php and https://susi.dev/php8-benchmark-jit-symfony).

Maybe because Symfony already caches things very efficiently/cleverly with OPCache?


The article you link to already explains it... ?

> The point is, if you look in the announcements and comments about what the JIT does you can pretty much guess why this is kind of the expected result. The JIT compiler improves performance for CPU-intensive work (for example calculating Mandelbrots) but not so much for the "default" kind of applications. We usually don't do all that many calculations.


Yes, I read that, but that's not really what I ask. What makes JIT improve performance only for CPU-intensive work? I don't understand the connection there.


Mostly because only cpu-intensive code greatly benefits from JIT. Serving a blog (like the demo) is not much cpu-intensive.


OO heavy code and functional heavy code can also benefit greatly from JIT compilation. The PHP8 JIT just doesn't have these optimizations yet.


Does PHP still has that weird flow where each request is its own process? afair PHP never had an http server baked in, I remember nginx with php etc ...


Yes, each request is handled by its own process. This might sound weird if you're used to other languages, but it's how every language used to work in the good ol' CGI days. PHP doesn't break backward compatibility easily, and I don't think it will ever break this one. Besides, once you get the hang of it, PHP's execution model is highly intuitive and beginner-friendly. You simply don't have to worry about a whole class of concurrency-related problems. Those problems are solved in C, not PHP.

Nowadays everyone uses PHP-FPM (again, written in C) which manages a pool of processes. Once a process is done serving a request, it is cleaned up and becomes available for serving another request. You can tweak the number of processes to control how much concurrency you want, or leave it to PHP-FPM to decide on its own. The process pool is much more efficient than the CGI method of setting up and tearing down a process every time, while preserving much of the conceptual simplicity.

PHP has had a built-in HTTP server since 5.4, but few people use it in production because PHP-FPM is so stable and performant.


The PHP doc advices you that the built-in server from PHP should be used only for development: https://www.php.net/manual/en/features.commandline.webserver.... But PHP-FPM is the most used nowadays, for sure.


I find the built-in web server very useful for running tests. Instead of setting up Apache or nginx on every CI build, you just fire up the built-in web server and point your tests at it.


I use it for small scripted jobs on my own machine that have to go through a proxy, I start the built-in server on the proxy root and point the script to the localhost address.


That's the best part


By weird flow do you mean “shared nothing by design”?


Surprisingly php these days is actually pretty fast even on forking webserver such as apache. This annoy me to no end because I prefer to use python and django and it can't match php performance on apache even though it handles http requests directly.


Are you using mod_python with Apache? If so, mod_wsgi is what you should be using for Apache + Django applications. mod_wsgi is fantastic and I see no issues with performance matching similar PHP setups via PHP-FPM.


I'm using gunicorn or uvicorn depending on the projects. Doesn't matter which wsgi server I used, the baseline performance level stay the same. For example, a simple django rest api endpoint with nested serializers took 45ms to render, which is similar to the time it take for freshly installed wordpress running on apache/php7.4 (docker) to render the homepage the same test server. All the rest api endpoint did was serializing values from database entries to json, yet it took the same time as a default installation of wordpress to render. Yes, django rest framework serializer is slow and maybe I should use something else, but if cpython is faster maybe there won't be a need to replace the serializer just for a performance issue.


That is not a problem with PHP itself, but the way that Apache/Nginx operates PHP. However, if you want to go full PHP, there is this extension that is pretty amazing (has a built-in server on it and more): https://www.swoole.co.uk/

ps: https://github.com/swoole/swoole-src/issues/1401 some performances benchmark (they compare it even with golang)


Does Swoole have any comparison to roadrunner (https://roadrunner.dev/)?


I tried many things from Apache with mod_php, nginx with php-fpm, Roadrunner and Swoole.

Apache and nginx are both great, both have pros and cons, although I would go with nginx and fpm as my first choice.

Swoole is totally different approach as it runs php as standalone server in a loop, just like python for example. It is great if you serve api but it kills the benefit of having each request isolated as you would have with nginx or apache. So you need to care about memory leaks, db connection pools etc. Also Swoole docs was not great few months ago.

Roadrunner is kind of between apache/nginx and Swoole. It is a golang server that can execute php in workers. For each worker once php is loaded it will stay in memory and it is super fast. The only downside on this one is that Roadrunner is developed by mostly one guy and not much you can find on the internet. Also Roadrunner features set is IMO very narrowed into what the company behind it needs at the time. IMO there is no clear vision where this project is going.


Really looking forward to the match expression syntax!


  0 == 'foobar' // false
> When comparing to a numeric string, PHP 8 uses a number comparison. Otherwise, it converts the number to a string and uses a string comparison.

Why do the conversion at all? Why couldn't this just be an error? I realise there is also `===` the strict comparison that typechecks arguments, but why not make that the default?


> Why couldn't this just be an error?

you mean crash your program? So your user finds a way to send you an int instead of a string, or vice versa, and now they can crash your webserver.


technically they'd just crash that one php process, not the whole web server. :)

I think the bigger 'why not' is ... 25 years of backwards compatibility.


Oh right ^^ that’s actually one really cool thing about php web apps, no easy denial of service attacks


(again) technically it could trigger a warning (actually, I thought perhaps it did that years ago??)

It's still pretty easy to DOS the server that is passing requests to PHP.

The 'shared nothing' approach has other benefits though - primarily not having to concern yourself with concurrency issues or shared memory resources. You can dive in to deep PHP and do that, but it's not something beginners need to be thinking about.


Though I still wish they officially support async I/O, this is an improvement, excited about this!


React php is worth checking out. Async stuff like websockets and non blocking redis subscriptions.


Interesting.

changes the shared nothing status of traditional php serving.

https://reactphp.org/


Daemons!


ReactPHP and all the other "async" frameworks became obsolete the moment Swoole entered the game.


Big disagree. They're just different. Swoole is like Golang, ReactPHP is like Node, in terms of runtime style.


What is React PHP?


Think of it like if PHP had Node's event loop runtime.

There's also Swoole, which is like if PHP had Golang's runtime (i.e. coroutines and such).



Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: