PHP: The latest news in the PHP world

5 readers
1 users here now

Share and discover the latest news about the PHP ecosystem and its community. Please respect r/php's rules.

founded 1 year ago
MODERATORS
51
 
 
The original post: /r/php by /u/D8duh on 2024-12-15 17:37:31.

Hi,

I'm trying to get back into coding PHP but I see that a lot of people recommend Laravel framework. I havent done much coding in about 6+ years besides some css/html. If I wanted to learn Laravel, do I need to relearn PHP first?

Last time I coded in PHP, version 7 had just been released. And back then I just did it for fun so didn't really do anything too advanced.

Thanks in advance for the help. ✌️

52
 
 
The original post: /r/php by /u/stonedoubt on 2024-12-15 05:35:33.

Here's the main class implementation:

<?php

namespace App\Services\Screenshot;

use HeadlessChromium\Browser;
use HeadlessChromium\BrowserFactory;
use HeadlessChromium\Page;
use EchoLabs\Prism\Prism;
use EchoLabs\Prism\Enums\Provider;
use EchoLabs\Prism\ValueObjects\Messages\UserMessage;
use Imagick;

class CleanScrollingScreenshot
{
 private Browser $browser;
 private ?Page $page = null;
 private array $hiddenElements = [];

public function __construct( private string $chromePath = 'chrome', private array $browserOptions = ['headless' => true] ) { $factory = new BrowserFactory($chromePath); $this->browser = $factory->createBrowser($browserOptions); }

public function capture(string $url): string { try { $this->page = $this->browser->createPage(); $this->page->navigate($url)->waitForNavigation();

    $html = $this->getPageHtml();
    $screenshot = $this->takeInitialScreenshot();

    $distractingElements = $this->analyzePageContent($html, $screenshot);
    $this->hideElements($distractingElements);

    $cleanScreenshot = $this->takeFullPageScreenshot();
    return $this->createScrollingGif($cleanScreenshot);

} finally {
    if ($this->page) {
        $this->page->close();
    }
}

}

private function getPageHtml(): string { return $this->page->evaluate('document.documentElement.outerHTML')->getReturnValue(); }

private function takeInitialScreenshot(): string { $screenshot = $this->page->screenshot([ 'format' => 'png', 'fullPage' => true, ]);

$tempFile = tempnam(sys_get_temp_dir(), 'screenshot');
$screenshot->saveToFile($tempFile);
return $tempFile;

}

private function analyzePageContent(string $html, string $screenshotPath): array { $prompt = <<<EOT


Analyze this webpage HTML and screenshot to identify distracting elements that should be hidden for a clean scrolling screenshot. 
Focus on:
1. Advertisements
2. Fixed navigation bars
3. Popup modals
4. Cookie notifications
5. Newsletter signup forms
6. Social media widgets
7. Chat widgets

For each element, provide:
1. A CSS selector to target it
2. Why it's considered distracting
3. Confidence level (0-100)

Return the analysis in JSON format like:
{
 "elements": [
 {
 "selector": "string",
 "reason": "string",
 "confidence": number
 }
 ]
}
EOT;

try {
    $response = Prism::text()
        ->using(Provider::Anthropic, 'claude-3-sonnet')
        ->withMessages([
            new UserMessage("HTML:\n{$html}\n\nAnalyze according to instructions:\n{$prompt}")
        ])
        ->generate();

    $analysis = json_decode($response->text, true);
    return array_filter($analysis['elements'], fn($element) => $element['confidence'] > 75);

} catch (\Exception $e) {
    return [];
}

}

private function hideElements(array $elements): void { foreach ($elements as $element) { $this->page->evaluate(sprintf( 'document.querySelector("%s").style.display = "none";', addslashes($element['selector']) )); $this->hiddenElements[] = $element['selector']; }

$this->page->evaluate('window.scrollTo(0, 0)');
usleep(500000);

}

private function takeFullPageScreenshot(): string { $screenshot = $this->page->screenshot([ 'format' => 'png', 'fullPage' => true, 'captureBeyondViewport' => true ]);

$tempFile = tempnam(sys_get_temp_dir(), 'clean_screenshot');
$screenshot->saveToFile($tempFile);
return $tempFile;

}

private function createScrollingGif(string $screenshotPath): string { $source = new Imagick($screenshotPath); $width = $source->getImageWidth(); $height = $source->getImageHeight(); $viewportHeight = 1080;

$fps = 30;
$duration = 10;
$totalFrames = $fps * $duration;

$animation = new Imagick();
$animation->setFormat('gif');

for ($frame = 0; $frame < $totalFrames; $frame++) {
    $progress = $this->easeInOutQuad($frame / $totalFrames);
    $scrollY = (int)($progress * max(0, $height - $viewportHeight));

    $frameImage = clone $source;
    $frameImage->cropImage(
        $width,
        $viewportHeight,
        0,
        $scrollY
    );

    $frameImage->setImageDelay(100 / $fps);
    $animation->addImage($frameImage);
    $frameImage->destroy();
}

$animation->setImageIterations(0);
$animation->optimizeImageLayers();

$outputPath = tempnam(sys_get_temp_dir(), 'scrolling_screenshot');
$animation->writeImages($outputPath, true);

$source->destroy();
$animation->destroy();
unlink($screenshotPath);

return $outputPath;

}

private function easeInOutQuad(float $t): float { return $t < 0.5 ? 2 * $t * $t : 1 - pow(-2 * $t + 2, 2) / 2; }

public function __destruct() { $this->browser->close(); }


}

Tutorial: Creating Clean Scrolling Screenshots with Chrome PHP and AI

Prerequisites

Before starting, install these packages:


Chrome PHP installation
=======================

composer require chrome-php/chrome

Prism for AI analysis
=====================

composer require echolabs/prism

ImageMagick (Ubuntu/Debian)
===========================

sudo apt-get install imagemagick php-imagick

ImageMagick (macOS)
===================

brew install imagemagick
pecl install imagick

Basic Usage

Here's how to use the utility:

use App\Services\Screenshot\CleanScrollingScreenshot;

// Create instance
$screenshot = new CleanScrollingScreenshot();

// Capture and save
$outputPath = $screenshot->capture('<https://example.com/'>);
rename($outputPath, 'final/screenshot.gif');

Advanced Configuration

Custom Chrome Path:

php $screenshot = new CleanScrollingScreenshot( chromePath: '/usr/local/bin/chrome' );

Browser Options:

php $screenshot = new CleanScrollingScreenshot( browserOptions: [ 'headless' => false, // For debugging 'windowSize' => [1920, 1080], 'debugLogger' => 'php://stdout' ] );

How It Works

  1. Page Loading: Loads URL in headless Chrome
  2. Analysis: Uses Prism/Claude to analyze page content
  3. Cleanup: Hides distracting elements
  4. Capture: Takes full-page screenshot
  5. Animation: Creates smooth scrolling GIF

AI Analysis

The AI looks for: * Advertisements * Fixed navigation bars * Popup modals * Cookie notices * Newsletter forms * Social widgets * Chat widgets

Elements with >75% confidence are hidden.

Error Handling

php try { $screenshot = new CleanScrollingScreenshot(); $outputPath = $screenshot->capture('https://example.com/'); rename($outputPath, 'final/screenshot.gif'); } catch (\Exception $e) { error_log("Screenshot failed: " . $e->getMessage()); }

Customization

Animation Settings:

php private function createScrollingGif(string $screenshotPath): string { // Customize these $fps = 30; // Frames per second $duration = 10; // Total duration $viewportHeight = 1080; // Viewport height }

Custom Element Detection:

php $prompt = <<<EOT Analyze this webpage HTML and screenshot to identify distracting elements that should be hidden for a clean scrolling screenshot. Focus on: // Add your categories 8. Auto-playing videos 9. Floating buttons 10. Interstitial banners EOT;

Performance Tips

  1. Memory Usage:

    • Lower frame rate for big pages
    • Reduce animation duration
    • Adjust viewport height
  2. Speed Optimization:

    • Use powerful machine for Chrome
    • Adjust page load timeouts
    • Consider parallel processing

Lighter Headless Chrome

Personally, for scrapers or whatever other purpose I may have, I prefer to use ‘chrome-headless-shell’ which is a standalone and fairly portable headless chrome version that uses the old headless implementation.

npx @puppeteer/browsers install chrome-headless-shell@stable

If you didn’t know this, you can also generate pdfs and even take video using the screencast api via a headless chrome instance.


License

MIT License - feel free to modify and use as needed.

53
 
 
The original post: /r/php by /u/JancoPanco on 2024-12-14 14:35:38.

Hi, I’m interested in contributing to open source php projects. Can you guys recommend how or where to start? Are there any rules to this? Do I just open a PR and wish for it to be merged?

Any advice is welcome.

Thanks :)

54
 
 
The original post: /r/php by /u/2019-01-03 on 2024-12-14 12:04:19.

The SQL to generate this takes up a page, but if you're interested here's the queries.

 version   |   min |   max |
-----------+-------+-------+
NO VERSION | 175,180 [40.1%]
  5.0-5.2  |  3207 |      0
     5.3   | 31113 |     10
     5.5   | 17948 |      9
     5.6   | 19357 |    697
     7.0   | 26505 |    504
     7.1   | 28041 |    374
     7.2   | 22092 |    360
     7.3   | 12562 |    290
     7.4   | 23867 |  32167 [7.44%]
     8.0   | 22049 |    233 [0.05%]
     8.1   | 20110 |   5839  [1.4%]
     8.2   |  5046 |    996  [0.2%]
     8.3   |   546 | 215519 [49.9%]

At least 206,741 packages [47.8%] explicitly support unsupported PHP versions.

We should encourage people to only support PHP 8.x in their most recent versions.

I'm a part of this trend / problem. Only one of my 35 projects targets PHP 8.x as the minimum, and it was so it would support the latest Laravel.

So one of my New Years resolutions will be to upgrade all of my Packagist packages, except for 3 explicitly targeting all PHP versions, to support PHP 8.0 as a minimum for all future development.

This can be our Go-PHP8 moment.

55
 
 
The original post: /r/php by /u/lankybiker on 2024-12-14 11:41:06.

Had an idea

Many code bases get very slow when the database gets big. But many test driven code bases use small or even microscopic databases when running tests.

You could always create a massive database for testing but that brings a lot of problems

How about something that wraps pdo etc and examines the SQL. If the query seems complex then a delay is calculated and then a micro sleep is called before returning results.

Then in integration tests, you can use phpunits time limit functionality to enforce time limits, or maybe something more precise can be used

This way you can still use a tiny test DB but still get useful feedback on areas of the code base that are going to be problematic with large database

Obviously the trick will be creating meaningful and accurate delay calculation based on the SQL. I wonder if this has been done before somewhere?

56
 
 
The original post: /r/php by /u/femio on 2024-12-14 07:29:05.

Experienced dev, new to PHP/Laravel. My coworker consistently writes code like this:

$class = 'App\Entity\\'.$eloquent_model->namespace.'\\'.$eloquent_model->method;
  if (is_subclass_of($class, EntityInterface::class)) {
    if (app($class)->checkCondition($variable)) {
      $this->performAction($request, $user);

In other words, frequently calling classes dynamically by constructing their names as strings and calling methods dynamically via app. To me, coming from other languages and ecosystems, this seems like a code smell because:

  1. she claims this allows reuse of logic; to me, if we have to wrap it with all these conditions how useful is that reuse? It feels like unnecessary indirection and mental overhead
  2. my IDE can't properly track down uses of checkCondition or performAction easily; maybe there's an easy way to do so with tooling but it makes the code harder to understand when coming in new
  3. It's hard to tell the flow of a request. Looking at it, I have to conceptually think about all the namespaces and classes available just to reason about which class actually gets called at the end by seeing which ones return what value from checkCondition

This is done a lot throughout the code and in some places, even searching the codebase for a method name somehow doesn't turn anything up. Is this just a case of me being unfamiliar with modern PHP practices, or is it truly a code smell?

57
 
 
The original post: /r/php by /u/k3464n on 2024-12-14 01:34:12.

I am attempting to get into PHP really for the first. I believe I have the basics down pretty easily but I get lost in the weeds really easy. Especially when it comes to how to implement frameworks and knowing what built in functions exist.

As it stands, I can write a database manipulation web app. But I know there is so much more available.

How do YOU suggest this 40 year old to go about learning PHP effectively? I have some self taught HTML, CSS in my past, but nothing proper.

58
 
 
The original post: /r/php by /u/exakat on 2024-12-13 21:38:14.
59
 
 
The original post: /r/php by /u/Delicious_Sea_2153 on 2024-12-13 19:11:08.

Could anyone offer help if you know the solution to this issue??

first time creating a laravel project but im facing the problem where i cant even create the project because of the zip extension, i already unzippped it from php.ini by removing the ; but i still get the same issue.

Error says:

Creating a "laravel/laravel" project at "./test"

Installing laravel/laravel (v11.4.0)

Failed to download laravel/laravel from dist: The zip extension and unzip/7z commands are both missing, skipping.

The php.ini used by your command-line PHP is: C:\Program Files\php-8.4.1\php.ini

Now trying to download from source

- Syncing laravel/laravel (v11.4.0) into cache

- Installing laravel/laravel (v11.4.0): Cloning 0993d09dc8 from cache

Created project in C:\Users\aicha/test

Loading composer repositories with package information

Updating dependencies

Your requirements could not be resolved to an installable set of packages.

Problem 1

- Root composer.json requires laravel/framework ^11.31 -> satisfiable by laravel/framework[v11.31.0, ..., v11.35.1].

- laravel/framework[v11.31.0, ..., v11.33.2] require league/flysystem ^3.8.0 -> satisfiable by league/flysystem[3.8.0, ..., 3.29.1].

- laravel/framework[v11.34.0, ..., v11.35.1] require league/flysystem-local ^3.25.1 -> satisfiable by league/flysystem-local[3.25.1, 3.28.0, 3.29.0].

- league/flysystem[3.3.0, ..., 3.14.0] require league/mime-type-detection ^1.0.0 -> satisfiable by league/mime-type-detection[1.0.0, ..., 1.16.0].

- league/flysystem[3.15.0, ..., 3.29.1] require league/flysystem-local ^3.0.0 -> satisfiable by league/flysystem-local[3.15.0, ..., 3.29.0].

- league/flysystem-local[3.15.0, ..., 3.29.0] require ext-fileinfo * -> it is missing from your system. Install or enable PHP's fileinfo extension.

- league/mime-type-detection[1.4.0, ..., 1.16.0] require ext-fileinfo * -> it is missing from your system. Install or enable PHP's fileinfo extension.

- league/mime-type-detection[1.0.0, ..., 1.3.0] require php ^7.2 -> your php version (8.4.1) does not satisfy that requirement.

To enable extensions, verify that they are enabled in your .ini files:

- C:\Program Files\php-8.4.1\php.ini

You can also run php --ini in a terminal to see which files are used by PHP in CLI mode.

Alternatively, you can run Composer with --ignore-platform-req=ext-fileinfo to temporarily ignore these required extensions.

60
 
 
The original post: /r/php by /u/Sweaty-Ad-3837 on 2024-12-13 15:51:46.

Hi, I'm trying to figure out what is the best notebooks to issue in my company, the work is mainly laravel with everything it has to offer (some vue, some livewire...).

I'm currently using the Dell Latitude 5k having some inconsistencies.

Since my company is a Dell partner, my first option would be to upgrade to Dell Precision.

Same test: Fresh laravel install with debugbar on welcome page, nothing else.

A fresh laravel on latitude 5k with windows is getting ~300ms with 18MB memory

On my personal computer Macbook Pro M2 i'm getting around ~5ms with 1MB memory

From my research, it seems like the NTFS adds a lot of overhead, and it might be the issue.

Can anyone offer some insights on how to go about this?

Is it just computer capacity or the OS is the real issue?

61
 
 
The original post: /r/php by /u/RevolutionaryHumor57 on 2024-12-13 15:22:23.

Hey folks

I am wondering if there are other developers that would share my point of view on how PHP evolves.

I started my commercial career back in PHP 5.6, then I entered the PHP7 realm, and now it's PHP8.

Do I feel like I am using a PHP8 features? No, I may like enums / strict typing / null accessors but ffs I was using typescript during 5.6 era so I don't feel it like I am juicing PHP8

Do my performance falls behind? Also no

Sometimes I feel like people going crazy about passing named arguments is changing the world... I have never seen a good use for them (and bad quality code where there is no time to implement design pattern like builder or CoR does not count)

For most if not every new features PHP is giving to us, I just see the oldschool workaround, so I stay with them.

Like an old fart dinosaur

62
 
 
The original post: /r/php by /u/Lipsthorn on 2024-12-13 12:12:04.

Just wondering by looking at most scripts and colleagues. How long more until the community REALLY embraces PHP 8+ new features? Sometimes it looks like there is a resistance in absorbing named arguments, attributes and more. Why?

63
 
 
The original post: /r/php by /u/Warm-Fan-3329 on 2024-12-12 23:27:10.

Hi,

Looking for some help with the below code. I am trying to have the below code update all rows when $startdate = today's date. At this time, this functions but only updates 1 record at a time. What should I be doing to change this so that all records are updated at the same time?

while ($row = $stmt->fetch_assoc()) {

$startdate = "$row[startdate]";

$today = date('Y/m/d');

$id = "$row[id]";

if ( ($startdate == $today) ) {

$sql = "UPDATE availability SET startdate='NEW_DATE' WHERE id=$id";

$result = $conn->query($sql);

if($result)

{

echo "Data updated successfully.";

}

else

{

echo "Error occurred while updating the record!";

echo "Reason: ", $conn->error;

}

$conn->close();

64
 
 
The original post: /r/php by /u/P4nni on 2024-12-10 21:05:36.

Hello everyone,

I'm currently working on a project that has these basic entities:

  • Company
  • User
  • Inquiry

To retrieve and save those entities, I built Repositories according to the repository pattern.

Implementing the Repositories for the Company and User entities was simple, as those entities do not contain any other entities.

But now I'm planning the implementation of the InquiryRepository.

An Inquiry has a sender (User entity) and a receiver (Company entity).

So in order to instantiate an Inquiry the InquiryRepository has to query the CompanyRepository and the UserRepository.

This means at least 3 queries will hit the database to instantiate an Inquiry entity.

Those three database queries may not seem like a lot at first.

But the frontend should list around 20 Inquiry entities at once in the users profile.

With 3 database queries per Inquiry, we are at around 60 database queries per page load.

Some of those queries are even unnecessary as the sender will always be the current user.

This feels like way to many queries to me, so I'm thinking about runtime caching already instantiated entities.

But the benefits of caching may come with a truckload of more problems.

Having to think about all those (probably already solved) problems, makes me feel like I'm building my own makeshift ORM.

Now I'm wondering about these things:

  1. Is this feeling correct or am I just overthinking?

  2. Are those 60 database queries not a problem at all and I just shouldn't care or just cache the final 20 inquiries?

  3. Am I implementing/understanding the repository pattern wrong?

  4. Is it normal to built all those things or should I just use a fully fledged ORM like Doctrine?

In previous projects we used (and abused) the Active Record pattern.

Entities themselfs query all database tables they need data from, to reduce the total number of database queries.

Therefore I don't have much experience with the Repository pattern and ORMs.

I'd like to hear about your suggestions and experiences.

65
 
 
The original post: /r/php by /u/funkyoz on 2024-12-10 20:33:59.

Hi everybody.

I created an implementation to orchestrate multi agent llm application, using tools calls. I was inspired by OpenAI Cookbook and OpenAI Swarm python implementation. The package is very small and don't support the total features exposed by newest LLMs (like image or audio for multimodal applications).

Only OpenAI provider supported, but I'll also works to Anthropic and many others.

I'm searching some feedbacks and feel free to create pull requests.

https://github.com/FunkyOz/mulagent

66
 
 
The original post: /r/php by /u/noweh95 on 2024-12-10 19:17:42.

Discover how autoloading has revolutionized PHP development! earn how it simplifies code management avoids naming conflicts.

67
 
 
The original post: /r/php by /u/successful-blogger on 2024-12-10 15:45:37.

1st official release of the Devflow content management framework.

https://github.com/getdevflow/cmf/releases/tag/v1.0.0

68
 
 
The original post: /r/php by /u/restinggrumpygitface on 2024-12-12 12:04:46.

With all the buzz about 8.4 is anyone using it in production yet?

69
 
 
The original post: /r/php by /u/Practical_Race_3282 on 2024-12-12 10:11:40.

Hey everyone

Trying to get into Laravel, already have experience in JavaScript, Python and Go and have been programming for years.

Most tutorials online consider you a complete beginner, explaining how for loops work for example. Is there a way for me to get the syntax and the general php way of doing things faster?

70
 
 
The original post: /r/php by /u/winzippy on 2024-12-12 07:50:11.

Like so:

    class Foo {
        final protected string $bar;
    }

See example three in the manual: https://www.php.net/manual/en/language.oop5.final.php

71
 
 
The original post: /r/php by /u/Enough_University402 on 2024-12-11 20:24:57.

How would you also deal with migrations etc...

Ideally in a DDD architecture, where you have Entity objects representing your tables, etc...

72
 
 
The original post: /r/php by /u/prithivir on 2024-12-11 19:43:26.

Hello everyone,

I’m building a list of PHP books/courses written by indie authors: https://indieverse.dev/tags/php.

I’ve found that books by indie authors are often more practical and useful compared to those from big publishers like O’Reilly. Some even make their books available for free!

Do you know any great PHP books/courses by indie authors? I’d love to add them to the list. Let me know!

73
 
 
The original post: /r/php by /u/Tux-Lector on 2024-12-11 12:13:23.
74
 
 
The original post: /r/php by /u/viktorprogger on 2024-12-11 09:05:55.
75
 
 
The original post: /r/php by /u/noweh95 on 2024-12-11 08:20:54.

When PHP meets video games: how a superhero took flight in a Linux terminal using only ASCII and ReactPHP.

view more: ‹ prev next ›