PHP Reddit – Telegram
PHP Reddit
34 subscribers
292 photos
37 videos
24.9K links
Channel to sync with /r/PHP /r/Laravel /r/Symfony. Powered by awesome @r_channels and @reddit2telegram
Download Telegram
Weekly help thread

Hey there!

This subreddit isn't meant for help threads, though there's one exception to the rule: in this thread you can ask anything you want PHP related, someone will probably be able to help you out!

https://redd.it/1k46h74
@r_php
I want to optimze this code, Now it just pending, not getting rendered html

public function getFilterData(Request $request)
    {
        try {
            $sbu = $request->sbu;
            $location = $request->location;
            $customer = $request->customer;
            $salesRep = $request->salesRep;
            $asAt = $request->asAt;
    
            $html = ''; //html table
    
            //common style
            $styles = [
                'borderTop' => 'border-top: 2px solid #000;',
                'borderBottom' => 'border-bottom: 1px solid #000; border-bottom: 3px double #000;',
                'textAlign' => 'text-align: right;',
            ];
    
            $count = 1; //count
    
            $data = $this->requiredData($sbu, $location, $customer, $salesRep, $asAt, $request);
    
            //grouped data
            $groupedCollection = $data->groupBy('cti');
            
            //all sum
            $totalAmountSumAll = 0;
            $paymentSumAll = 0;
            $balanceSumAll = 0;
            $oneOverDueSumAll = 0;
            $twoOverDueSumAll = 0;
            $threeOverDueSumAll = 0;
            $fourOverDueSumAll = 0;
            $fiveOverDueSumAll = 0;
            $sixOverDueSumAll = 0;
            $lateFeesSumAll = 0;
            $totalDueSumAll = 0;
    
            //set table data
            $callingCod = '';
            if ($groupedCollection != null) {
                foreach ($groupedCollection as $key => $group) {
                    $customerCode = isset($group[0]['cusCode']) ? $group[0]['cusCode'] : null;
                    $customerName = isset($group[0]['cusName']) ? $group[0]['cusName'] : null;
                    $callingCode = isset($group[0]['cCodeGMoNo']) ? $group[0]['cCodeGMoNo'] : null;
                    $mobileNo = isset($group[0]['gBNo']) ? $group[0]['gBNo'] : null;
                    //set calling code
                    $cCode = $this->callingCode($callingCode);
                    if (!empty($cCode) && isset($cCode[0]['callingCode'])) {
                        $callingCod = $cCode[0]['callingCode'];
                    }
                    $html .= '<tr>
                        <td></td>
                        <td colspan="4"><strong>' . $customerCode . ' : ' . $customerName . (!empty($mobileNo) ? ' | +' . $callingCod . ' ' . $mobileNo : '') .  '</strong></td>
                    </tr>';
    
                    //customer wise sum
                    $totalAmountSum = 0;
                    $paymentSum = 0;
                    $balanceSum = 0;
                    $oneOverDueSum = 0;
                    $twoOverDueSum = 0;
                    $threeOverDueSum = 0;
                    $fourOverDueSum = 0;
                    $fiveOverDueSum = 0;
                    $sixOverDueSum = 0;
                    $lateFeesSum = 0;
                    $totalDueSum = 0;
    
                    // Apply chunking to the group processing - chunk size of 100 can be adjusted
                    $chunkSize = 100;
                    $chunks = array_chunk($group->toArray(), $chunkSize);
                    
                    foreach ($chunks as $chunk) {
                        // Process each chunk of items
                        foreach ($chunk as $item) {
                            //get date difference 
                            $asAtDate = Carbon::parse($asAt);
                            $effectiveDate = !empty($item['invoiceDate']) ? $item['invoiceDate'] : (!empty($item['cicDate']) ? $item['cicDate'] : (!empty($item['odInvoiceDate']) ? $item['odInvoiceDate'] : null));
                            $effectiveDate = Carbon::parse($effectiveDate);
                            $overDueVal = $asAtDate->diffInDays($effectiveDate);
    
                            //over due
                            $oneOverDue = 0;
                            $twoOverDue = 0;
                            $threeOverDue = 0;
                            $fourOverDue = 0;
                            $fiveOverDue = 0;
                            $sixOverDue = 0;
    
                            if ($overDueVal >= 1 && $overDueVal <= 7) {
                                $oneOverDue = $item['amount'] - $item['paymnt'];
                            } else if ($overDueVal >= 8 && $overDueVal <= 14) {
                                $twoOverDue = $item['amount'] - $item['paymnt'];
                            } else if ($overDueVal >= 15 && $overDueVal <= 30) {
                                $threeOverDue = $item['amount'] - $item['paymnt'];
                            } else if ($overDueVal >= 31 && $overDueVal <= 60) {
                                $fourOverDue = $item['amount'] - $item['paymnt'];
                            } else if ($overDueVal >= 61 && $overDueVal <= 90) {
                                $fiveOverDue = $item['amount'] - $item['paymnt'];
                            } else if ($overDueVal > 91) {
                                $sixOverDue = $item['amount'] - $item['paymnt'];
                            }
    
                            $balance = $item['amount'] - $item['paymnt']; //balance
                            $lateFee = $item['lateFee'] - $item['stlmntDiscnt'];
                            $totalDue = $balance + $lateFee; //total due
    
                            $html .= '<tr>
                                <td>' . $count++ . '</td>
                                <td>' . ($item['tty'] == 1 ? 'INV' : ($item['tty'] == 2 ? 'CHQ RTN' : ($item['tty'] == 3 ? 'CRD NO' : ($item['tty'] == 4 ? 'OTH CRD' : '')))) . '</td>
                                <td>' . (isset($item['invoiceNo']) ? $item['invoiceNo'] : (isset($item['inhandChequeNo']) ? $item['inhandChequeNo'] : (isset($item['oldInvoiceNo']) ? $item['oldInvoiceNo'] : ''))) . '</td>
                                <td>' . (!empty($item['invoiceDate']) ? $item['invoiceDate'] : (!empty($item['cicDate']) ? $item['cicDate'] : (!empty($item['odInvoiceDate']) ? $item['odInvoiceDate'] : '-'))) . '</td>
                                <td>' . (isset($item['invoiceNo']) && $item['invMrf'] !== null ? $item['invMrf'] : '-') . '</td>
                                <td style="text-align: right">' . (isset($item['creditPeriodDays']) ? $item['creditPeriodDays'] : 0) . ' Days' . '</td>   
                                <td style="text-align: right">' . $item['remngDays'] . ' Days' . '</td>
                                <td style="text-align: right">' . ($item['amount'] !== 0.0 && $item['amount'] !== 0 ? number_format($item['amount'], 2) : '-') . '</td>
                                <td style="text-align: right">' . ($item['paymnt'] !== 0.0 && $item['paymnt'] !== 0 ? number_format($item['paymnt'], 2) : '-') . '</td>
                                <td style="text-align: right">' . number_format($item['amount']  - $item['paymnt'], 2) . '</td>
                                <td style="text-align: right">' . ($oneOverDue !== 0 && $oneOverDue !== 0.0 ? number_format($oneOverDue, 2) : '-') . '</td>
                                <td style="text-align: right">' . ($twoOverDue !== 0 && $twoOverDue !== 0.0 ? number_format($twoOverDue, 2) : '-') . '</td>
                                <td style="text-align: right">' . ($threeOverDue !== 0 && $threeOverDue !== 0.0 ?  number_format($threeOverDue, 2) : '-') . '</td>
                                <td style="text-align: right">' . ($fourOverDue !== 0 && $fourOverDue !== 0.0 ? number_format($fourOverDue, 2) : '-') . '</td>
                                <td style="text-align: right">' . ($fiveOverDue !== 0 && $fiveOverDue !== 0.0 ? number_format($fiveOverDue, 2) : '-') . '</td>
                                <td style="text-align: right">' . ($sixOverDue !== 0 && $sixOverDue !== 0.0 ? number_format($sixOverDue, 2) : '-') . '</td>
                                <td style="text-align: right">' . ($lateFee !== 0.0 && $lateFee !== 0 ? number_format($lateFee, 2) : '-') . '</td>
                                <td style="text-align: right">' . ($totalDue !== 0.0 && $totalDue !== 0 ? number_format($totalDue, 2) : '-') . '</td>
                            </tr>';
    
                            $totalAmountSum += $item['amount'];
                            $paymentSum += $item['paymnt'];
                            $balanceSum += $balance;
                            $oneOverDueSum += $oneOverDue;
                            $twoOverDueSum += $twoOverDue;
                            $threeOverDueSum += $threeOverDue;
                            $fourOverDueSum += $fourOverDue;
                            $fiveOverDueSum += $fiveOverDue;
                            $sixOverDueSum += $sixOverDue;
                            $lateFeesSum += $lateFee;
                            $totalDueSum += $totalDue;
                        }
                    }
    
                    //set customer wise sum
                    $html .= '<tr>
                        <td></td>
                        <td></td>
                        <td></td>
                        <td></td>
                        <td></td>
                        <td></td>
                        <td></td>
                        <td style="' . $styles['borderTop'] . ' ' . $styles['borderBottom'] . ' ' . $styles['textAlign'] . '">' . ($totalAmountSum !== 0.0 && $totalAmountSum !== 0 ? number_format($totalAmountSum, 2) : '-') . '</td>
                        <td style="' . $styles['borderTop'] . ' ' . $styles['borderBottom'] . ' ' . $styles['textAlign'] . '">' . ($paymentSum !== 0.0 && $paymentSum !== 0 ? number_format($paymentSum, 2) : '-') . '</td>
                        <td style="' . $styles['borderTop'] . ' ' . $styles['borderBottom'] . ' ' . $styles['textAlign'] . '">' . ($balanceSum !== 0.0 && $balanceSum !== 0 ? number_format($balanceSum, 2) : '-') . '</td>
                        <td style="' . $styles['borderTop'] . ' ' . $styles['borderBottom'] . ' ' . $styles['textAlign'] . '">' . ($oneOverDueSum !== 0.0 && $oneOverDueSum !== 0 ? number_format($oneOverDueSum, 2) : '-') . '</td>
                        <td style="' . $styles['borderTop'] . ' ' . $styles['borderBottom'] . ' ' . $styles['textAlign'] . '">' . ($twoOverDueSum !== 0.0 && $twoOverDueSum !== 0 ? number_format($twoOverDueSum, 2) : '-') . '</td>
                        <td style="' . $styles['borderTop'] . ' ' . $styles['borderBottom'] . ' ' . $styles['textAlign'] . '">' . ($threeOverDueSum !== 0.0 && $threeOverDueSum !== 0 ? number_format($threeOverDueSum, 2) : '-') . '</td>
                        <td style="' . $styles['borderTop'] . ' ' . $styles['borderBottom'] . ' ' . $styles['textAlign'] . '">' . ($fourOverDueSum !== 0.0 && $fourOverDueSum !== 0 ? number_format($fourOverDueSum, 2) : '-') . '</td>
                        <td style="' . $styles['borderTop'] . ' ' . $styles['borderBottom'] . ' ' . $styles['textAlign'] . '">' . ($fiveOverDueSum !== 0.0 && $fiveOverDueSum !== 0 ? number_format($fiveOverDueSum, 2) : '-') . '</td>
                        <td style="' . $styles['borderTop'] . ' ' . $styles['borderBottom'] . ' ' . $styles['textAlign'] . '">' . ($sixOverDueSum !== 0.0 && $sixOverDueSum !== 0 ? number_format($sixOverDueSum, 2) : '-') . '</td>
                        <td style="' . $styles['borderTop'] . ' ' . $styles['borderBottom'] . ' ' . $styles['textAlign'] . '">' . ($lateFeesSum !== 0.0 && $lateFeesSum !== 0 ? number_format($lateFeesSum, 2) : '-') . '</td>
                        <td style="' . $styles['borderTop'] . ' ' . $styles['borderBottom'] . ' ' . $styles['textAlign'] . '">' . ($totalDueSum !== 0.0 && $totalDueSum !== 0 ? number_format($totalDueSum, 2) : '-') . '</td>
                    </tr>';
    
                    $totalAmountSumAll += $totalAmountSum;
                    $paymentSumAll += $paymentSum;
                    $balanceSumAll += $balanceSum;
                    $oneOverDueSumAll += $oneOverDueSum;
                    $twoOverDueSumAll += $twoOverDueSum;
                    $threeOverDueSumAll += $threeOverDueSum;
                    $fourOverDueSumAll += $fourOverDueSum;
                    $fiveOverDueSumAll += $fiveOverDueSum;
                    $sixOverDueSumAll += $sixOverDueSum;
                    $lateFeesSumAll += $lateFeesSum;
                    $totalDueSumAll += $totalDueSum;
                }
    
                // Rest of your code for total sum rows remains unchanged
                $html .= '<tr>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>';
    
                $html .= '<tr>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td style="' . $styles['borderTop'] . ' ' . $styles['borderBottom'] . ' ' . $styles['textAlign'] . '">' . ($totalAmountSumAll !== 0 && $totalAmountSumAll !== 0.0 ? number_format($totalAmountSumAll, 2) : '-') . '</td>
                    <td style="' . $styles['borderTop'] . ' ' . $styles['borderBottom'] . ' ' . $styles['textAlign'] . '">' . ($paymentSumAll !== 0 && $paymentSumAll !== 0.0 ? number_format($paymentSumAll, 2) : '-') . '</td>
                    <td style="' . $styles['borderTop'] . ' ' . $styles['borderBottom'] . ' ' . $styles['textAlign'] . '">' . ($balanceSumAll !== 0 && $balanceSumAll !== 0.0 ? number_format($balanceSumAll, 2) : '-') . '</td>
                    <td style="' . $styles['borderTop'] . ' ' . $styles['borderBottom'] . ' ' . $styles['textAlign'] . '">' . ($oneOverDueSumAll !== 0 && $oneOverDueSumAll !== 0.0 ? number_format($oneOverDueSumAll, 2) : '-') . '</td>
                    <td style="' . $styles['borderTop'] . ' ' . $styles['borderBottom'] . ' ' . $styles['textAlign'] . '">' . ($twoOverDueSumAll !== 0 && $twoOverDueSumAll !== 0.0 ? number_format($twoOverDueSumAll, 2) : '-') . '</td>
                    <td style="' . $styles['borderTop'] . ' ' . $styles['borderBottom'] . ' ' . $styles['textAlign'] . '">' . ($threeOverDueSumAll !== 0 && $threeOverDueSumAll !== 0.0 ? number_format($threeOverDueSumAll, 2) : '-') . '</td>
                    <td style="' . $styles['borderTop'] . ' ' . $styles['borderBottom'] . ' ' . $styles['textAlign'] . '">' . ($fourOverDueSumAll !== 0 && $fourOverDueSumAll !== 0.0 ? number_format($fourOverDueSumAll, 2) : '-') . '</td>
                    <td style="' . $styles['borderTop'] . ' ' . $styles['borderBottom'] . ' ' . $styles['textAlign'] . '">' . ($fiveOverDueSumAll !== 0 && $fiveOverDueSumAll !== 0.0 ? number_format($fiveOverDueSumAll, 2) : '-') . '</td>
                    <td style="' . $styles['borderTop'] . ' ' . $styles['borderBottom'] . ' ' . $styles['textAlign'] . '">' . ($sixOverDueSumAll !== 0 && $sixOverDueSumAll !== 0.0 ? number_format($sixOverDueSumAll, 2) : '-') . '</td>
                    <td style="' . $styles['borderTop'] . ' ' . $styles['borderBottom'] . ' ' . $styles['textAlign'] . '">' . ($lateFeesSumAll !== 0 && $lateFeesSumAll !== 0.0 ? number_format($lateFeesSumAll, 2) : '-') . '</td>
                    <td style="' . $styles['borderTop'] . ' ' . $styles['borderBottom'] . ' ' . $styles['textAlign'] . '">' . ($totalDueSumAll !== 0 && $totalDueSumAll !== 0.0 ? number_format($totalDueSumAll, 2) : '-') . '</td>
                </tr>';
            } else {
                $html .= '<tr>
                    <td colspan="18">
                        <div role="alert" class="alert alert-warning alert-dismissible fade show" style="text-align: center;">
                           
                            ' . __("finance/reports/debtor_aging_details.data_empty_massage") . '
                        </div>
                    </td>
                </tr>';
            }
    
            return response()->json(['stts' => 1, 'data' => $html]);
        } catch (Exception $e) {
            dd($e);
            $randomErrorCode = errorLog(authrz_debtorAgingDetails("transaction"), $request, $e, $this->datetime);
            return response()->json(['stts' => 0, "mssg" => __('message.danger'), "rfms" => __('message.dangerRef', ['refr' => $randomErrorCode]), "burl" => '#']);
        }
    }


I want to optimize above function and can't affect to its calculation and ui  

https://redd.it/1k488xh
@r_php
Backup laravel mail Sender

Is there a way to have a bacup mail Sender, example: my main sender returned some kind of error, so the app tries to send in another one.

I did some research and find nothing about it.

https://redd.it/1k4efo7
@r_php
Laravel but static?

A while back I did this small static site using jigsaw plus some simple form handling in php. It worked fine, wasn't my favorite to work with, and I kept thinking I should just have just gone with insert framework here behind cloudflare with some aggressive caching... But something something sunk cost lets just keep going.

Fast forward maybe 6 months, and I see the static pages feature in tempest and I have a "yeah that makes perfect sense, why didn't I think of that" moment.

So since I already have a bunch of blade templates for this site I decided to see what it would take to get static pages in laravel. Simpler than I expected...

https://github.com/ssnepenthe/mostly-static

It's a bit rough around the edges and I doubt I will spend much time improving it/cleaning it up. But I thought I would share in case anyone else finds it useful as a starting point for doing something similar.

https://redd.it/1k4tnzl
@r_php
Have very small PHP/MySQL/HTML project, not sure best place to post it

I've looked at /phpjobs and /forhire and not sure the best place to post a request. I see some other websites, like Upwork, as well. But my project is pretty small and self-contained and I want to find a reliable freelancer.


Short version is that I have a website, six pages, with some read-only MySQL calls. I programmed it myself back in 2008, and hired a designer for the look and feel. I have work to do on the website (broken links, old information), but before I do anything I need to bring the PHP up from 7.3 to current 8.4. I haven't programmed anything in years and don't have the head for it anymore (I manage teams in a mainframe iSeries environment). So I need someone to review the code and update any decremented commands, and there are two widgets that no longer work, which probably have common solutions.


So this is a small project, maybe 10-15 hours, with no follow-up projects. I will post more information in a real "for hire" post, but right now not sure where is best to post it to get the right freelancer.

https://redd.it/1k4t64f
@r_php
TALL stack + Filament = Built an invoicing app in under a week

Hey everyone,

I’ve been working with Laravel for over 10 years now, and honestly, with the TALL stack and Filament, building things has never been easier. I have been using excel 😅 to generate invoices for years and it occurred to me that I can build something with Livewire to generate and manage invoices.

Thought I’d try putting something together with Filament + Livewire, and within a week (just a few hours a day), I had a working app. It might be useful for some of you as well.

Check it out: **plaininvoice.com**
No signup or anything—just a clean way to generate and download invoices.

https://redd.it/1k4x64t
@r_php
My Career Plan: Specializing in WordPress and Beyond

I want to specialize deeply in WordPress — and only WordPress. That means I won’t follow any other PHP frameworks anymore. My goal is to be able to build any type of system using WordPress just the way I envision it.

For example, I want to be capable of creating custom themes, booking systems, movie ticket reservations, food ordering platforms, online course platforms like Udemy, and more — all powered by WordPress.



Besides that, I also plan to study Node.js and Vue.js (or React.js), as well as technologies like Docker, Redis, Kafka, Message Queue systems, and design patterns.



So, if I follow this path, will I have a stable and promising career in the future?





https://redd.it/1k4xmf1
@r_php
Best Practices for uploads/ Directory Versioning and Filesystem Permissions in Symfony

# Question de support

# Question 1 : Gestion des versions du répertoire uploads/

Faut-il :

Versionner un répertoire `public/uploads/` vide (avec `.gitkeep`) tout en ignorant son contenu via `.gitignore` ? Exemple :/public/uploads/\ !/public/uploads/.gitkeep
Ou y a-t-il une meilleure solution pour s’assurer que le répertoire existe après le déploiement ?

# Question 2 : Autorisations du système de fichiers pour uploads/

Est-ce que ces approches sont recommandées ?

1. Utilisation des ACL (préféré) : \`\`\`bashHTTPDUSER=$(ps axo user,comm | grep -E '\[a\]pache|\[h\]ttpd|\[\_\]www|\[w\]ww-data|\[n\]ginx' | grep -v root | head -1 | cut -d\\ -f1)Pour var/ (cache + logs) et uploads/

sudo setfacl -dR -m u:"$HTTPDUSER":rwX -m u:$(whoami):rwX public/uploads sudo setfacl -R -m u:"$HTTPDUSER":rwX -m u:$(whoami):rwX public/uploads

Question de support
Question 1 : Gestion des versions du répertoire uploads/
Faut-il :
Versionner un répertoire public/uploads/ vide (avec .gitkeep) tout en ignorant son contenu via .gitignore ?
Exemple :
/public/uploads/

!/public/uploads/.gitkeep



Ou y a-t-il une meilleure solution pour s’assurer que le répertoire existe après le déploiement ?
Question 2 : Autorisations du système de fichiers pour uploads/
Est-ce que ces approches sont recommandées ?
Utilisation des ACL (préféré) :
    Pour var/ (cache + logs) et uploads/

HTTPDUSER=$(ps axo user,comm | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\ -f1)
sudo setfacl -dR -m u:"$HTTPDUSER":rwX -m u:$(whoami):rwX public/uploads
sudo setfacl -R -m u:"$HTTPDUSER":rwX -m u:$(whoami):rwX public/uploads

s

# Support Question

# Question 1: Versioning the uploads/ Directory

Should we:

* Version an empty public/uploads/ directory (with .gitkeep) while ignoring its content via .gitignore? Example:/public/uploads/\* !/public/uploads/.gitkeep
* Or is there a better alternative to ensure the directory exists after deployment?

# Question 2: Filesystem Permissions for uploads/

Are these the recommended approaches?

1. Using ACL (preferred): \`\`\`bashHTTPDUSER=$(ps axo user,comm | grep -E '\[a\]pache|\[h\]ttpd|\[\_\]www|\[w\]ww-data|\[n\]ginx' | grep -v root | head -1 | cut -d\\ -f1)For var/ (cache + logs) and uploads/

sudo setfacl -dR -m u:"$HTTPDUSER":rwX -m u:$(whoami):rwX public/uploads sudo setfacl -R -m u:"$HTTPDUSER":rwX -m u:$(whoami):rwX public/uploads

Support Question
Question 1: Versioning the uploads/ Directory
Should we:
Version an empty public/uploads/ directory (with .gitkeep) while ignoring its content via .gitignore?
Example:
/public/uploads/*
!/public/uploads/.gitkeep



Or is there a better alternative to ensure the directory exists after deployment?
Question 2: Filesystem Permissions for uploads/
Are these the recommended approaches?
Using ACL (preferred):
bash
For var/ (cache + logs) and uploads/

HTTPDUSER=$(ps axo user,comm | grep -E 'apache|httpd|_www|www-data|nginx' | grep -v root | head -1 | cut -d\ -f1)
sudo setfacl -dR -m u:"$HTTPDUSER":rwX -m u:$(whoami):rwX public/uploads
sudo setfacl -R -m u:"$HTTPDUSER":rwX -m u:$(whoami):rwX public/uploads

2. User/Group Permissions:
- Should the webserver user (e.g., www-data) and deployer user be in the same group?
- Example setup:
      sudo usermod -a -G www-data deployer  # Add deployer to www-data group
sudo chown -R deployer:www-data var/ public/uploads/
sudo chmod -R 775 var/ public/uploads/ # RWX for owner/group, RX for others

2. **User/Group Permissions**:
- Should the webserver user (e.g., `www-data`) and deployer user be in the same group?
- Example setup:
bash
sudo usermod -a -G www-data deployer # Add deployer to www-data group
sudo chown -R deployer:www-data var/
public/uploads/
sudo chmod -R 775 var/ public/uploads/ # RWX for owner/group, RX for others


https://redd.it/1k539wi
@r_php
Pre-RFC Associated Types

Posting this on Reddit, because why not.

A few weeks ago, motivated by the RFC about allowing never as a parameter type, I started writing a proof of concept for "Associated Types" which are "generics"/"template" types limited to interfaces as they do not have a lot of the complexity relating to generic types on concrete classes, as the bound type can be determined at compile time rather than run-time.

Internals email post is: https://externals.io/message/127165

PoC on GitHub is: https://github.com/php/php-src/pull/18260

https://redd.it/1k571ns
@r_php