❌

Normal view

The php2shell drama showed us where our priorities really are.

Nothing highlights PHP's core demographic quite like Ondrej getting a full year of funding in a week for legacy builds while the PHP Foundation barely gets a nod. We'll pay anything to keep PHP 5.6 on life support, but won't throw a dime at the heroes building the core language. Priorities, I guess!

submitted by /u/Antique_Mechanic133 to r/PHP
[link] [comments]

Released Commentify 4.4

Commentify 4.4 is out, with over 18k installs, MIT, Laravel Livewire comments for any Eloquent model. Tailwind or Bootstrap, nested replies, markdown, likes, reports, guests, optional Filament admin. PHP 8.3+, Laravel 12 or 13, Livewire 4.

What changed:

  • Filament: a modal used to reuse the first record's comments component. The Livewire thread is now keyed to the record and the thread name, so the modal shows the record you opened and two threads on one model do not collide. CommentsEntry::make() drops that thread on an edit or relation manager form.
  • Notifications: with the flag on, a reply notifies the parent author. A top-level comment notifies the commentable's user when that relation exists. The notification is queued and waits until the transaction commits. The mail button is included only when the comment URL is on your app.url host, so a request referer cannot send the recipient off your app.
  • Minimum PHP is now 8.3.

Install guide:

https://docs.commentify.pro/installation

submitted by /u/usamamuneer to r/PHP
[link] [comments]

I made a pixel-art Halloween quest to resurrect RoadRunner. Live run Oct 31 at 16:00 UTC πŸŽƒ

When RoadRunner 3 came out, some people took it as the beginning of the end. Right here on r/PHP:

So EOL for RR soon?

Rumors travel fast, and by now some folks are pretty sure RoadRunner is dead.

Well. Tomorrow is Halloween, and that's a chance to resurrect RoadRunner. πŸŽƒ

So I made an interactive pixel-art quest for it. It's a multiplayer game: you make a little pixel character, and everyone's characters walk around the same shared scene, so you see what the others do in real time.

The bar is already open: https://halloween.roadrunner.dev

It starts in a viking bar. The owl behind the counter swears RoadRunner can be brought back: something about pumpkins, a ritual, and a magical place nearby. Grab a mug, find someone to clink with (no clink, no drink: house rules), shoot some flies and listen to the owl's gossip.

πŸͺ° Rumor has it that everyone who swats 100 flies before the ritual starts will get a superpower.

πŸ•“ Saturday, Oct 31, 16:00 UTC: the ritual

Your local time

That's when the doors to the pumpkin patch open and we go through the whole story together, live, with the owl leading the way. What happens after that… you'll have to be there. No spoilers.

Join the crowd, clink mugs with strangers and help with the ritual 🍺

Missed it? Play it again. And again.

After the live event I'll step down as the game master and switch the game to autopilot for a week. No moderator needed: hit the goal of a scene and the story moves on by itself. Bring your friends and play the whole thing from the bar to the very end, then start over, as many times as you like.

You don't need to play. Watching is fine, and it works on your phone. More people means a bigger ritual and more beer.

How it works

The backend is PHP. The stack:

  • PHP with the Spiral framework
  • RoadRunner: HTTP, KV, locks, jobs, metrics (no nginx)
  • Centrifugo for WebSockets
  • Valkey and in-memory KV storage
  • Prometheus and Grafana
  • PixiJS on the frontend

All of it runs on one VDS: 2 Γ— 3.3 GHz CPU, 2 GB RAM, 15 GB NVMe. By my estimate that's enough for about 200 active players. Let's find out tomorrow 😈

How it all fits together, with diagrams and code: https://halloween.roadrunner.dev/how-it-works

Live metrics in Grafana: https://halloween.roadrunner.dev:3000/d/hellowin/hellowin

Yes, the irony of running "RoadRunner is dead" on RoadRunner is intentional.

See you at the bar. πŸΊπŸŽƒ

submitted by /u/roxblnfk to r/PHP
[link] [comments]

Site compromised, interesting implementation of a persistent virus

Hello PHPers :)

I was tasked to look into two compromised WordPress sites. The people who own them, tried to remove the virus but failed. I wanted to describe what the virus was doing.

Overall this is a self-propagating, self-healing, obfuscated, hidden executor virus with size-padding evasion tactics.

It generated the following files and directories:

  • /home/foobar/public_html/wp-content/.sc_494g1672
  • /home/foobar/public_html/wp-content/.gk_eb46c3gc
  • /home/foobar/public_html/wp-content/.kk_cb505c82
  • /home/foobar/public_html/wp-content/ab743742.zip
  • /home/foobar/public_html/wp-content/uploads/2026/10/ab743742.zip
  • /home/foobar/public_html/wp-content/plugins/agile-beacon-go
  • /home/foobar/public_html/wp-content/plugins/hyper-proxy-cue
  • /home/foobar/public_html/wp-content/plugins/nexus-curator-rig
  • /home/foobar/public_html/wp-content/plugins/swift-keeper-dex
  • /home/foobar/public_html/wp-content/mu-plugins/.bt_hyper-proxy-cue
  • /home/foobar/public_html/wp-content/mu-plugins/.pv_hyper-proxy-cue
  • /home/foobar/public_html/wp-content/mu-plugins/.sd_hyper-proxy-cue
  • /home/foobar/public_html/wp-content/mu-plugins/.swm_hyper-proxy-cue
  • /home/foobar/public_html/wp-content/mu-plugins/hyper-proxy-cue.php
  • /home/foobar/public_html/mu-plugins/hyper-proxy-cue.php

Each compromised site received its own hash, thus the ab743742 you see above is the unique hash for this compromised site. The value re-appears in several places.

The virus infects the functions.php of the current theme, it adds a variable with the contents of the ab743742.zip file. When the site runs, the variable contents are gzdecode'ed gzinflat'ed and stored as the above zip file, which gets extracted under the plugins directory.

The virus generates a self-preserving "must-use" plugin under the mu-plugins directory.

The virus creates its own admin user in the SQL table wp_users and modifies WordPress files so that its own admin user is invisible.

Finally, the virus creates the .sc_[HASH VALUE] directory under wp-content which stores a specially crafted PHP cli script. This script is executed via exec() or other similar function, once its loaded the script deletes itself so it only remains resident in memory. This monitors all the above files and re-generates the whole infection.

At first glance, the virus tries to access a master server and receives instructions. In this case, it started adding hidden URLs inside the generated WordPress pages.

A few interesting things about this virus:

  • It uses token_get_all() to validate its own PHP syntax before making modifications to the site, so that does not corrupt the site and get noticed.
  • It uses function_exists() to test for various functions, so it can understand what it can do to its host server.
  • It generates a padding size for modified files, so that it matches the target size and avoid detection from scanners that check file size.
  • It generates various "sidecar" files with quality markers in MD5, a version file, rate limits (regenerate itself every 4 minutes) and a write race/lock flag.
  • It executes hidden commands from wp-content/.sc_[HASH VALUE}.php files that act as commands imported from its master control server.

The following strings can used to grep/search for the infection:

  • SCV:
  • SC_TH_BEGIN
  • hyper-proxy-cue
  • _sc_fam
  • _sc_commit

Let me know if you need more details!


EDIT with information about the plugin

The plugin has its own replication and cleanup code. It detects the presence of itself by looking for the string /* SCV:x.x.x */ where x.x.x is the version number of the virus. If there is a newer version then it overwrites itself.

It replicates by scanning various directories like /home, /var/www. It also modifies advanced-cache.php and object-cache.php.

The main code does:

  • List Ethereum JSON-RPC endpoints and contract addresses.
  • Receives an Ethereum contract with remote commands.
  • It sends server information like domain, plugins, admin users+passwords, session cookies, etc.
  • It receives remote code and executes it.
  • It has some obfuscated code to detect legitimate plugins, it modifies some of them.

Interestingly, it uses wp_generate_auth_cookie() to generate an admin session that sends this back to its control server, thus the attacker can login to wordpress without knowing the password of the admin.

On the front-end side, it adds Javascript code that runs its own Service Worker for intercepting web traffic.

It does various other things that I can't be bothered to write about :)


I also posted this in /r/Wordpress but the post was removed by the moderators, so I'm posting on /r/PHP to raise awareness

submitted by /u/Maria_Thesus_40 to r/PHP
[link] [comments]

Canvas: an open-source PHP framework that runs alongside your legacy code

I’ve been building Canvas, an open-source PHP framework. I built it for myself. It started because I wanted to modernize an existing PHP application incrementally and couldn’t get the integration I wanted with Symfony. Over time it grew into a standalone framework for building new applications that can also run alongside existing PHP code. I’m happily using it in my projects because it works the way I like it to, and I open sourced it so anyone who wants to can use it too.

It is deliberately similar to Symfony in some regards: it uses Symfony’s HttpFoundation, routes are annotations on controller methods, and the ORM is a Data Mapper like Doctrine. Where it differs:

  • Legacy Bridge: Canvas checks its own routes first. If it does not find a match, it will fall through to your existing PHP files. E.g. The Strangler Fig Pattern. Legacy files can use Canvas services through a canvas() helper.
  • AOP for cross-cutting concerns: instead of a middleware pipeline or kernel events, authentication, logging and caching are aspects declared with InterceptWith on a controller method or class, with before/around/after phases and priorities. Aspects are inherited, so a base controller’s aspects apply to all its subclasses.
  • Contextual dependency injection: resolve different implementations of the same interface in different situations. The context can be static, as with Laravel’s contextual bindings, but Canvas also lets you compute it per request, declared directly on the annotation.
  • ObjectQuel: a QUEL-inspired query language instead of DQL. Relationships are traversed with via, and queries that outgrow DQL, such as window functions or recursive traversal, stay in the language instead of dropping to raw SQL.

I designed it this way because I think explicit structure, clear boundaries between responsibilities, and endpoint behavior that is easy to discover make a codebase easier to work in.

I’ve also written a technical comparison with Laravel and Symfony covering routing, dependency injection, persistence, and the trade-offs involved.

If you find it interesting, I'd be happy to hear your thoughts.

submitted by /u/Big_Tadpole7174 to r/PHP
[link] [comments]

This Week In PHP Internals | Oct 29, 2026

Preface: what follows is the word-for-word transcript of the spoken dialogue in the video, chapter by chapter with timestamps, for anyone who'd rather read than click through. If this digest is still too long for you, we recommend copying it into your LLM of choice and asking for a summary of our summary.

Cold Open (00:00)

A week after two critical bugs in PHP's own engine, someone asked the internals list to stop. No new features and no cosmetic deprecations, until PHP has a formal spec and four independent implementations, written in formal-methods frameworks. Four people who work on PHP replied. One of them called fixing PHP's bugs a money problem.

Hello world, it's Thursday, October 29, 2026, and here's what happened This Week in PHP Internals. 15 stories this week, so let's get into it. But first,

AI made building software easy, and owning it hard. Scalpels installs open source apps into your own Laravel Cloud or Forge account in one click, so your data never leaves your infrastructure. There are 15 apps in the catalog, from a private Composer registry to a mail trap for staging. The Free plan is zero dollars, forever, and Laravel bills you directly for the hosting. There's even a guide to patching PHP on your own servers. Scalpels launches this Saturday, October 31st, at scalpels.app.

Spec Debate (01:21)

This week's top story: after last week's emergency releases, Brian Nguyen argued that PHP's two critical bugs show the cost of having no formal specification and only one implementation. He proposed a living spec of the bytecode and the parser, executable semantics in research frameworks like K and PLT Redex, and testing any second runtime against WordPress, Laravel and Symfony. His first mail said it was not an embargo. The next morning, he opened a second thread asking for one, until four formal implementations exist. He wrote: "Not adding a feature cannot break apps. Not deprecating (integer) cannot break apps. A corrupt allocator can."

Rowan Tommins doubted a spec would have helped, since memory management is exactly what differs between implementations. And on .NET, he pointed out that if 0.01% of Microsoft's roughly 200,000 employees work on it full time, that's still twice as many as have ever been paid to work full time on PHP. Sjoerd Langkemper wrote: "I think PHP is not starved for bugs. The bottleneck is bugfixes." And Larry Garfield wrote: "This is a money problem, just like most major OSS projects. It's nothing more complicated than that."

His fix is to get PHP-using companies to become significant PHP Foundation sponsors, or to put their own employees on PHP full time. Ben Ramsey asked whether Brian wanted PHP's maintainers to stop building PHP. Other runtimes were built by their communities, he wrote, and companies with the resources should be doing that work. Brian hasn't replied yet.

Links: Brian Nguyen, "From mono-implementation risk to spec" Β· Larry Garfield, "This is a money problem"

Security Follow-ups (03:02)

If you run PHP on Windows, there's one more update to install. On Monday, Shivam Mathur announced rebuilt Windows packages for PHP 8.2 through 8.5, with Brotli 1.2.1. That fixes a critical out-of-bounds write in the Brotli decoder, rated 9.2, which PHP can reach through the curl extension when automatic response decompression is on. It's off by default in curl, but HTTP client libraries can turn it on. The PHP versions don't change, and the dash-1 marks the rebuilt package.

And on Friday, php.net posted an informational advisory: "We suggest you set session.upload_progress.enabled=0 until the next regular bugfix release, to fully protect from an unlikely RCE vector." It needs an unusual combination of configuration and application code, so the full advisory, for a new CVE, comes with the next release. If you applied that setting as a mitigation last week, keep it in place.

Links: Updated PHP Windows builds for the Brotli fix Β· Informational advisory: session upload progress

Newcomer PRs (04:07)

About half of the pull requests from first-time contributors to php-src have been accepted, and the first success matters most. Artem Ukrainskiy went through a year of data: 831 pull requests from 219 people who opened their first one in that time. 418 were accepted, 157 closed without a merge, and the rest have no outcome yet. A first PR was accepted 29% of the time, and after a first acceptance, 66%. PRs with AI-written descriptions were accepted around 20% of the time, against 55%.

And speed matters. When a maintainer responds within a day, the median PR closes in about 20 hours. When the first response takes over a week, it's about 32 days. So he asked whether a bot is worth prototyping, one that checks the mechanical things as soon as a PR opens: missing tests, an empty description, the wrong target branch, an obvious duplicate.

Sjoerd Langkemper replied that his biggest friction as a newish contributor was opening a pull request and having nobody respond. Artem's question started from a new rule by Weilin Du, merged Saturday, that asks contributors, and AI agents, to review an existing fix instead of opening a duplicate. No maintainer has answered the bot question yet.

Links: Artem Ukrainskiy, "What happens to newcomers' PRs in php-src"

Scope RFC (05:30)

PHP has no object that represents a request, because until now a request has been one run of the engine, from startup to shutdown. That breaks down when one process serves many requests at once, and Frode BΓΈrli's Scope RFC gives each unit of work an identity: an HTTP request, a queue job, a CLI command. Code anywhere in that request can ask which scope it's in, and keep its own state, like a database connection, keyed by it.

Fibers and generators belong to the scope they were created in. The primary vote adds only that identity. Two secondary votes would make the superglobals and the session, and then the default locale and timezone, follow the scope. Code that never creates a scope behaves exactly as today, and there's already an extension and a polyfill.

Larry Garfield called it promising and tightly focused, but asked what it looks like with real dependency injection, rather than a service locator. He also called new scopes with empty superglobals a footgun for legacy code that reads $_POST. Frode replied that the server fills them when it creates the request scope, the same place that fills them today, and that he'll swap the examples for a container.

Links: RFC: Scope

Effect Declarations (06:46)

What if a function had to declare that it starts processes, reads files or makes network requests? Arsan Gamal proposed effect declarations, written after the return type, with optional parameters that narrow them, like the one command this function may run. A separate runtime mechanism would decide what's actually allowed. He named PHP2Shell, the finders' name for last week's vulnerabilities, as the motivation, and compared it to app permissions on a phone. He wrote: "My intention is not to promote process execution, but to make potentially dangerous operations explicit and controllable."

David Maye liked it, noted that a use-after-free couldn't be contained this way, and suggested prototyping it as an extension with attributes. Damian JΓ³ΕΊwiak asked the same thing: why new syntax instead of attributes? Larry Garfield replied that attributes work for static analysis, but for the engine to enforce it, backward compatibility is the problem. He wrote: "A new PHP release that fails on any function that has a print or fopen statement in it until you add new syntax not available in earlier versions is a complete non-starter." So his first question is how to make it piecemeal opt-in. Calvin Buckley added that these aren't algebraic effects, and suggested a name other than effects or capabilities.

Links: Arsan Gamal's proposal

Array Partition (08:12)

Splitting an array into the items that pass a check and the ones that don't takes two passes today, one of them negated. Ayoub Ezzini's RFC adds array_partition, which returns both halves in one pass, matching first, with keys preserved, so you can destructure straight into two variables.

mickmackusa asked for any number of groups, keyed by the callback's result, and Morgan for a result keyed true and false. Ayoub kept it to two. Partition means a two-way split in Ruby, Kotlin, Rust, Haskell and Laravel, he wrote, and PHP casts boolean array keys to 1 and 0, so a true-and-false result would quietly swap your variables.

Tim DΓΌsterhus said a co-worker hand-wrote his own array_partition just last week, and wrote: "It's a well-written, well-researched and well-argued RFC and I'm in favor of the proposal." Writing the polyfill Tim asked for turned up the open question: whether array_partition keeps references, like array_filter, or drops them, like array_find.

Links: RFC: array_partition()

Votes (09:22)

Two votes are open, heading in opposite directions. Sjoerd Langkemper's RFC to make hexdec, octdec, bindec and base_convert throw on invalid characters is at 25 to 1, and it closes November 1st. Muhammed Arshid's Filter enums RFC is at 2 to 11, with 1 abstention, and it closes November 4th.

Links: Throw exception for invalid characters in number base functions Β· Add Filter\Filter and Filter\Flag Enums

Quick Hits (09:44)

Quick hits. Sjoerd Langkemper reviewed Pratik Bhujel's Io\Terminal RFC and found two bugs. Pratik pushed fixes within a day, plus one he found himself, and the vote stays on hold.

Links: Io\Terminal RFC

Damian JΓ³ΕΊwiak planned the CSV extension vote for November 2nd. Tim DΓΌsterhus asked him to wait after the security release, and questioned giving CSV its own top-level namespace, so Damian postponed it.

Links: CSV extension RFC

Sjoerd also proposed openssl_get_channel_binding, which ties a login to the TLS connection it runs over, so mail and database clients can offer the PLUS variants of SCRAM logins. Tim asked why it returns null instead of throwing.

Links: openssl_get_channel_binding RFC

On blocking server-side request forgery in curl, Nicolas Grekas wrote "Yes, please make this happen!", for Symfony's HTTP client, and Levi Morrison asked why it should be curl-only rather than cover streams too.

Links: SSRF protection in curl

MΓ‘tΓ© Kocsis is keeping the length limit in his query parameters RFC, citing the recent CVEs.

Links: Query parameter manipulation RFC

Abbas proposed async and await keywords on top of Fibers, and Frode BΓΈrli replied that PHP should go the way of Go, choosing concurrency at the call site.

Links: async/await on top of Fibers

A developer who validates JSON from AI models asked the pattern matching RFC to keep a missing key different from null.

Links: Pattern matching RFC

And a proposal to call scalar extension methods without parentheses got a strong minus one from Rowan Tommins, for saving two characters per call.

TL;DR (11:15)

So that's the week. After last week's critical bugs, a call to freeze PHP until it has a formal spec met pushback, and Larry Garfield called the bug-fix bottleneck a money problem. Windows users have rebuilt packages to install, and php.net suggests one session setting until the next release. A year of data showed how much a newcomer's first pull request depends on a fast reply, Frode BΓΈrli's Scope RFC would give every request an identity, and array_partition arrived with Tim's support. Links below.

The PHP Foundation funds more than half of ongoing php-src commits, so if you use the language, maybe consider donating at opencollective.com/phpfoundation β€” or try guilting your employer into it.

If you found this useful, a like or a comment helps more people find it. And if you missed last week's episode, where two critical PHP vulnerabilities leaked a day before their fix, that's a good one to watch next. Thanks again to Scalpels.app for supporting this week's episode. We're Artisan Build. See you next week.

submitted by /u/ProjektGopher to r/PHP
[link] [comments]

PHP CLI workers don’t share opcache, so I made them: 70–80% less memory for Laravel queues

PHP's CLI doesn't share opcache between separately started processes, so every long-running worker compiles your whole app into its own private memory. With 8 Laravel queue workers that's 8 copies of the same compiled code, often 50–80 MB each.

I built queue-prefork to fix that for Laravel's queue:work and Horizon:

  • A small template process starts with opcache and no app code.
  • Each worker is forked from it with pcntl_fork() and then boots the app itself from the normal artisan entry. So nothing booted is inherited: no DB or Redis connections, sockets, singletons or RNG state. Only the compiled code is shared, through opcache's shared memory.
  • The pid your process manager started stays (a tiny /bin/sh stub for queue:work), so supervisord or systemd signals, timeouts and restarts behave as before.

Side-by-side benchmark, two identical Docker stacks on the same job stream, Laravel 13 with ~45 packages, 1 h each:

Setup Stock Prefork
8 Γ— queue:work, typical jobs 645 MB 192 MB (βˆ’70%)
8 Γ— queue:work, idle 455 MB 102 MB (βˆ’78%)
8 Γ— queue:work, heavy jobs 1,025 MB 524 MB (βˆ’49%)
Horizon, 6 supervisors 1,279 MB 240 MB (βˆ’81%)

Same throughput, 0 failed jobs, and less CPU, since new workers don't recompile anything. If any safety check fails, workers run as stock and the package tells you why.

Linux only for production; Laravel 11–13. MIT: https://github.com/tevkert/queue-prefork

Happy to answer questions about the fork and opcache side.

submitted by /u/Tevkert to r/PHP
[link] [comments]

One week after the PHP2Shell fix: about half of live sites on 8.2–8.5 show a patched release, and under 1% on 5.4–7.3 have moved. How we counted

I work at IPinfo, where we scan the IPv4 and IPv6 Internet. On October 22, the day after the fixed releases (8.5.12, 8.4.27, 8.3.36, 8.2.35), we started re-checking the same 1.46 million addresses that show a PHP version every day.

Where they started. In our October 14–15 scan, 1,105,160 addresses showed a PHP version. 409,494 of them (37%) ran 5.4–7.3, which is affected and gets no free official fix.

One week later. Of the servers that weren’t yet on a patched release on October 22:

  • Live sites on 8.2–8.5: 36.5% patched on day one, 47.5% by October 28 (41,707 of 87,865). Almost everything happened on the first day.
  • Default pages, panels and devices on 8.2–8.5: 23.0%.
  • Live sites on 5.4–7.3: 0.95% moved to a patched release (1,249 of 131,024).

Among servers still showing a vulnerable version, 47% now run 7.3 or older. For comparison, Wiz reported 5.7% for its customers’ cloud machines. The open Internet has a much longer tail.

How we counted:

  • Patched means the version string shows 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12 or later, lowest version per address.
  • We left out addresses that show PHP only on hosting control-panel ports (2082, 2083, 2086, 2087, 2095, 2096), and blocks where 64 or more addresses in a /24 (or /64) send the identical response. That’s one machine answering for many.
  • β€œLive site” means the page looked like a site in use in our October 14–15 scan, not a default page, login panel or device.
  • We dropped October 26 from the series. One large host’s proxy hid PHP versions on tens of thousands of servers for that day only.

Caveats:

  • Some hosts (GoDaddy, cPanel’s EasyApache packages) and distributions backport fixes without changing the version number, and TuxCare sells patched builds for 5.x–8.1. So these numbers are minimums.
  • We measure versions, not break-ins. CISA added PHP2Shell to its known-exploited list on October 26, but we can’t see who was attacked.

Happy to answer questions on the method. I write these up in a short brief: https://ipinfo.io/blog/internet-brief-1?utm_source=reddit_r_php&utm_medium=social&utm_campaign=php2shell

submitted by /u/seremot to r/PHP
[link] [comments]

Something feels off about this subreddit lately

I don't know if it's just me, but ever since last week (October 21 / php2shell), this subreddit has felt completely out of control.

It honestly doesn't feel like the same community I used to know anymore, and at least to me, it seems to be heading in the wrong direction.
I get that the php2shell caused a lot of attention, and that new people are naturally going to have questions about it. But at the same time, there seems to have been a noticeable increase in spam and low-effort posts that end up sitting at 0 upvotes.

Is it just me?

(I propably go touch a some grass for a moth and hope its just temporary)

submitted by /u/goodwill764 to r/PHP
[link] [comments]

Using Grafana OSS with PHP for Logs, Metrics and Traces

Hey folks,

I am new here but old PHP user and I think its time to give some more love to the PHP community.

I recently created a video and also wrote a blogpost about using Grafana with PHP for bringing observability to your applications.

It is purely focused on using open source tools integrations. (No AI or agents involved).

Here is the link to the video:
https://www.youtube.com/watch?v=SEN5wfb2gDY

The video description also contains the link to the GitHub repo. and also to the blogpost (English and German versions).

I hope it will be helpful!! πŸ™‚

submitted by /u/usmanlinux to r/PHP
[link] [comments]

pdo_duckdb 0.9.0: DuckDB 2.0 through PDO, and the upgrade traps (storage version 69, silently empty commits, $1_0)

pdo_duckdb is my PDO driver for DuckDB, the in-process analytical database. 0.9.0 bundles DuckDB 2.0.0 GA in every prebuilt binary. The last version I posted here was 0.5.0, so this covers 0.6.0 through 0.9.0, starting with what changes for your code when you move to 2.0.

What breaks on 2.0

  • New files are unreadable by 1.5. 2.0 writes storage version 69, and 1.5 reads only 64 to 68 (IO Error: Trying to read a database file with version number 69). Existing 1.5 files keep their format. If a 1.5 process shares a new file, open it with new PDO('duckdb:/data/shared.duckdb;storage_compatibility_version=v1.5.6').
  • Any failed statement aborts the transaction. Inside beginTransaction(), a parser or catalog error now aborts it too, and every later statement fails. On either version, commit() on an aborted transaction returns true and keeps nothing, so call rollBack() after a failure or set default_transaction_invalidation_policy=SYNTACTIC_ERRORS_DO_NOT_INVALIDATE.
  • Integer division by zero throws. 1 // 0 raises instead of returning NULL. Wrap it in TRY(...) or set error_on_division_by_zero=false.
  • x -> x + 1 lambdas are rejected. Write lambda x: x + 1, which also works on 1.5.
  • The PEG parser is the default, and it numbers parameters differently: $1_0 is parameter 10 under PEG and parameter 1 under the legacy parser. ? and :name are portable.

Source builds still work against DuckDB 1.5.3 and newer. configure detects 2.0 from duckdb_v2.h, since the 2.0 headers still report C API 1.5.6.

New in 0.9.0

  • PDO::DUCKDB_ATTR_NATIVE_STRUCTURES, an opt-in that fetches LIST, ARRAY, STRUCT, MAP, UNION, JSON and VARIANT as lossless PHP values instead of canonical strings.
  • VARIANT fetching, top-level and nested, and Appender input for it from arrays and objects.
  • Two PDO connections to the same file could lose writes and see stale reads. Equivalent paths now share one DuckDB instance, and transactions stay per connection.
  • Prebuilts for PHP 8.2 to 8.6 (8.6 as development builds) on Linux glibc and musl, macOS arm64, and Windows x64. They need PHP 8.2.35, 8.3.36, 8.4.27 or 8.5.12+, the October security releases; older patches build from source.

Security fixes since 0.5.0

0.8.0 carries the fixes from a security scan of the driver this month. An unclosed Appender in a reference cycle could read its PDO connection after gc_collect_cycles() or shutdown freed it. Hitting memory_limit during column setup could leave uninitialized type handles that were destroyed later. Earlier, 0.6.0 and 0.7.0 rejected DECIMAL types outside DuckDB's width and scale limits, a falsy force_mbedtls_unsafe that crashed the process, LOB binds over 64 MB, and Appender rows nested deeper than 128 levels.

pie install iliaal/pdo_duckdb

https://github.com/iliaal/pdo_duckdb

If you run DuckDB from PHP, I'd like to hear which 2.0 change hits your code first.

submitted by /u/Ilia0001 to r/PHP
[link] [comments]

JumPHP: write retro 2D games in PHP that run on desktop, in the browser and on phones

For the past few months I've been working on JumPHP, an open-source framework for writing 90s-style 2D games in plain PHP.

https://github.com/davidnurdin/jumPhp

The idea is simple: you write your game once, in PHP, and the same code runs in three places.

- On the desktop: a native window with sound, using PHP 8.3 and the SDL2 extensions.

- In the browser: PHP 8.3 and SDL2 are compiled to WebAssembly, so the game is a plain static web page. PHP runs on the player's machine; you don't need a PHP server, any static host works.

- On phones: the browser build ships with touch controls (floating joystick, buttons, fullscreen and landscape lock).

What it's for

- Platformers, shoot 'em ups, brick breakers, adventure games, puzzle games.

- Porting old games whose source code is available. Many C games from the 80s and 90s translate to PHP surprisingly well.

- Learning game programming with a language you already know, without switching to JavaScript, C# or Lua.

- Small multiplayer games you can share with a link.

What's in the box

- Scenes, sprites and animations, a camera, menus and HUD helpers, bitmap and TTF fonts.

- Saves (stored in IndexedDB in the browser), options and translations.

- Online multiplayer through a small relay server: rooms, 4-letter codes, quick match. The same code works on desktop and in the browser.

- A single CLI, bin/jumphp, that runs everything in Docker: PHP, Composer, Emscripten, tests, headless screenshots, browser builds, deployment. You only need Docker on your machine.

- An AGENTS.md that documents the whole contract, so you can also build a game with an LLM coding agent. Most of the games below were made that way, with me reviewing, testing and fixing.

The constraints are few: never block the frame (no sleep()), remember that integers are 32-bit in the browser, and use the engine's network layer instead of raw sockets.

What I've built with it so far

- Pong (bundled with the engine): against the computer, two players on one keyboard, or online. It's the reference game for the networking layer.

- Breakout (bundled with the engine): three lives, a new wall every level.

- Invaders: waves of aliens, shields, a bonus saucer. https://github.com/davidnurdin/php-invaders

- Moktar, a 1991 French DOS platformer, ported from OpenTitus (the open-source C engine for the game). Everything is PHP, down to the original file formats and an AdLib/OPL2 FM synth emulator that renders the original soundtrack. Play: https://moktar.mimichat.fr, code: https://github.com/davidnurdin/moktarPhp

- Sapiens, a 1986 prehistoric adventure game by Didier and Olivier Guillion. Its C sources were released under GPL v3 in 2018, and the port follows them function by function: a first-person 3D landscape, side-view fights, dialogues with the tribes, flint knapping. I also decoded the music files of the 1996 version (an undocumented Harmony Assistant format) to play the soundtrack with its original sampled instruments. Play: https://sapiens.mimichat.fr, code: https://github.com/davidnurdin/sapiensPhp

- Sonic PHP, a fan remake of the Master System game built on the same PHP + SDL2 + WebAssembly stack. It runs at 60 fps and has online multiplayer for up to 6 players (race, flag, rings, deathmatch). Play: https://sonic.mimichat.fr, code: https://github.com/davidnurdin/sonicGamePhp

Getting started

git clone https://github.com/davidnurdin/jumPhp

cd jumPhp

bin/jumphp new mygame "MY GAME"

bin/jumphp install mygame

bin/jumphp run mygame # desktop window

bin/jumphp build mygame # browser build

The new game starts from a small platformer skeleton you can replace bit by bit.

Feedback is welcome, especially from people who try to build something with it. And if you could bring back one old game in PHP, which one would it be?

submitted by /u/Womegle to r/PHP
[link] [comments]
❌