Skip to content

PHP Still Pays

PHP, Laravel, WordPress and the bills they quietly keep paying

t/php_still_pays

Modern PHP, Laravel, Symfony, WordPress plugins, legacy PHP 5 codebases that refuse to die, and the jokes. Yes, we have heard them all. PHP 8 is actually good and we will fight you on it.

13 members
16 posts
Created May 2026
+1

Community rules

3 rules for t/php_still_pays

  1. Post the PHP version

    5.6 and 8.3 are different languages. Say which one you are stuck on.

  2. The "PHP is dead" joke has been made

    Once per thread is enough. Bring something new or bring code.

  3. Argue with the post, not the person

    Disagree as hard as you like. Insults, slurs and dogpiling get removed, and repeat offenders get removed too.

Moderated by Ayesha Siddiqui

Discussions

2

Showing 16 posts.

Posts in t/php_still_pays

11

  • Pending, charging, paid, plus reconcile is exactly the state machine we use for bank debits. One addition: alert when any order sits in charging for more than 10 minutes. That alert has found two gateway outages before the gateway told us.
    1 reply
  • In embedded we call this exactly-once delivery and we know it does not exist. Good that PHP people discover it too.
    1 reply

  • Accepted answer

    Haan Faizan, bilkul wahi masla hai, and it is not basic, half the Laravel devs in Pakistan have sent double emails because of this. Redis queue mein jab worker job uthata hai, Laravel use retry_after seconds ke liye reserve karta hai (default 90, config/queue.php mein redis connection). Agar job 90 second mein khatam nahi hui, Laravel samajhta hai worker mar gaya aur job wapas queue mein daal deta hai. Doosra worker utha leta hai. Ab dono chal rahe hain. Exception koi nahi, isliye tumhe kuch dikhta nahi. Fix, isi order mein: 1. config/queue.php mein redis ka 'retry_after' => 600, aur worker ko --timeout=540. Rule: timeout hamesha retry_after se kam. Job class mein bhi public $timeout = 540; rakh do. 2. Asli fix: ek job mein 500 emails mat bhejo. Ek job per student dispatch karo, Bus::batch se, taaki progress aur failures dikhein. Har job 2 second ki hogi, retry_after ka sawaal hi khatam. 3. Idempotency: fee_receipts table mein (student_id, term) unique rakho aur sent_at save karo. Job shuru mein check kare, already sent hai to return. Phir job teen baar bhi chale, parent ko ek hi email jayega. Maine ye May mein Horizon wali post mein likha tha, wahan supervisor config bhi hai. Principal sahab ko mera salaam 😄
    1 reply

  • Accepted answer

    We've had Octane on FrankenPHP in prod since spring for an ecommerce API, about 2.5M requests a day, so a similar shape. What we learned: 1. --max-requests=500 to start. We went to 1000 after a month of watching memory. A PDF library leaked about 2MB per 100 requests, max-requests hides that nicely. Set a container memory limit as well, belt and braces. 2. Auditing singletons: grep every ->singleton( in your providers and ask "does this closure touch request(), auth(), session or anything tenant-ish". If yes, make it ->scoped( instead. Scoped bindings get reset between requests under Octane. Then grep app/ for static properties that aren't constants. That found two more for us. 3. Anything left over goes in the flush array in config/octane.php. 4. Write one test that sends two requests as two different tenants through the same app instance and asserts nothing bleeds. Cheap, and it caught a regression in July. 5. FrankenPHP over Swoole because there's no PHP extension to compile and the Docker image just works. You lose Octane::concurrently, which is Swoole only. We never missed it. Staging lies, aye, but mostly about memory. Run it for a week at 10% of traffic behind the load balancer before you switch everything.
    1 reply
Meu cliente foi hackeado por um plugin 'nulled'. O que todo plugin WordPress precisa ter

  • Pana, a mí me pasó igual con un cliente en Valencia, plugin 'premium' gratis y al mes la web vendía pastillas en ruso jajaja. Lo de wp core verify-checksums no lo conocía, burda de útil.
  • Je ne parle pas portugais mais le code parle français 😄 nonce + capability + escape, c'est exactement ma checklist. Et les plugins nulled, j'ai nettoyé trois sites de boulangerie l'année dernière à cause de ça.
    1 reply
14

  • mehmet in a php thread is the most reliable service on this site. 100% uptime
  • Ayesha baji, Money class wala example humare school fees module mein laga diya. readonly ki wajah se ek bug pakda gaya jahan controller fee amount badal raha tha 😅 Mehmet sahab ke liye arz hai: enum mein jo likha hai janab, wahi chalega, C mein 47 daal ke, kaun sambhalega 🙂

  • Accepted answer

    Did this for 26 schools (a school ERP, same shape as your problem). My vote: one database, tenant_id, but do it properly. 1. Don't read the tenant from auth() inside the scope. Make a small TenantContext class, bind it as a singleton, set it in a middleware for web requests and inside the job's handle() for queued work (pass koperasi_id into the job constructor). The scope reads from TenantContext and throws if it is empty. Fail loud, never fail open. 2. Put the scope and a creating hook in one trait, BelongsToKoperasi, so a new model gets both by adding one line. The creating hook fills koperasi_id automatically. 3. Every unique index includes koperasi_id. member_number is unique per koperasi, not globally. Composite indexes start with koperasi_id. 4. One feature test per model: create data for two koperasi, act as one, assert you never see the other. Ours caught 3 leaks in the first month. 5. "We want our own copy": mysqldump with --where="koperasi_id=7" per table, zip it, done. A 2 minute script. Database per tenant is worth it when tenants need custom schema, when the regulator demands physical separation, or when one tenant is 100x bigger than the rest. For 40 koperasi with max 20k members you will spend more time running 40 migrations and 40 backups than you save. And the dinas report becomes 40 queries and a merge in PHP. yaar, not worth it. Ask the regulator question first though. If they say separate databases, the decision is made for you.
    1 reply
11

  • Good post. In Java world we have same problem with visibility timeout on SQS, message come back while first consumer is still processing. Different language, same bug kkkk
  • please, please do not "fix" the 403 on /horizon by making the gate return true. i have found open horizon dashboards on three bug bounty programs, one with full job payloads. bref, gate on email or on a role, voilà
    1 reply