Logo

dev-resources.site

for different kinds of informations.

PHP Frameworks: hidden errors to avoid

Published at
12/30/2024
Categories
php
beginners
symfony
laravel
Author
spo0q
Categories
4 categories in total
php
open
beginners
open
symfony
open
laravel
open
Author
5 person written this
spo0q
open
PHP Frameworks: hidden errors to avoid

Frameworks such as Symfony (7.2 at the time of writing) or Laravel are highly customizable and encourage good practices, regardless of your experience and skills.

However, you may still introduce design, security, or performance issues.

Symfony: don't call the $container directly

❌ This one is a classic but still heavily used by developers:

 class LuckyController extends AbstractController
  {
      public function index()
       {
        $myDependency = $this->container->get(MyDependencyInterface::class);
        // 
       }
Enter fullscreen mode Exit fullscreen mode

It's possible because the parent AbstractController defines $container as protected:

protected ContainerInterface $container;
Enter fullscreen mode Exit fullscreen mode

Source: Symfony - GitHub

While it does work, it's a bad practice for various reasons:

  • it harms readability
  • it's harder to test
  • it relies on global states ($container)
  • it could lead to incompatibility issues in the future, as Symfony evolves

âś… Use dependency injection in the constructor instead:

 class LuckyController extends AbstractController
  {
      public function __construct(private MyDependencyInterface $myDependency) {}
Enter fullscreen mode Exit fullscreen mode

Eloquent ORM: don't use raw queries blindly

Eloquent allows writing SQL queries quite conveniently.

Instead of writing SQL queries directly, developers can use PHP wrappers to interact with database entities.

It also uses SQL bindings behind the scene, so you get injection protection for free, even with untrusted inputs:

User::where('email', $request->input('email'))->get();
Enter fullscreen mode Exit fullscreen mode

❌ However, when you use helpers like whereRaw, you may introduce vulnerabilities:

User::whereRaw('email = "'. $request->input('email'). '"')->get();
Enter fullscreen mode Exit fullscreen mode

âś… At least, always use SQL bindings:

User::whereRaw('email = :email', ['email' => $request->input('email')])->get();
Enter fullscreen mode Exit fullscreen mode

N.B.: the above example does not make sense, but it keeps things simple. In real-world use cases, you may need whereRaw for optimization purposes or to implement very specific where conditions.

Laravel: what about CSRF?

With CSRF attacks, hackers force the end users to execute unwanted actions on an app in which they're currently authenticated.

Laravel has a built-in mechanism to guard against such scenario.

Roughly speaking, it adds a token (hidden field) to be sent along with your requests, so you can verify that "the authenticated user is the person actually making the requests to the application."

Fair enough.

❌ However, some apps skip this implementation.

âś… Whether you should use the built-in middleware is not relevant here, but ensure your app is secured against CSRF attacks.

You may read this page for more details about the implementation in Laravel.

Please secure AJAX requests too.

Eloquent ORM: queries are not optimized "automagically"

Eloquent allows eager/lazy loading, and supports various optimizations, such as query caching, indexing, or batch processing.

However, it does not prevent all performance issues, especially on large datasets.

❌ It's not uncommon to see such loops:

$users = User::all();
foreach ($users as $user) {
    // some code
}
Enter fullscreen mode Exit fullscreen mode

But it can lead to memory issues.

âś… When possible, a better approach would leverage Laravel collections and helpers like chunk:

User::chunk(200, function (Collection $users) {
    foreach ($users as $user) {
        // ...
    }
});
Enter fullscreen mode Exit fullscreen mode

Check the documentation for more details.

N.B.: It works, but don't forget those helpers are only meant to ease the implementation, so you have to monitor slow queries and other bottlenecks.

Symfony: SRP services

As the documentation says:

useful objects are called services and each service lives inside a very special object called the service container. The container allows you to centralize the way objects are constructed. It makes your life easier, promotes a strong architecture and is super fast!

In other words, you will write custom services to handle specific responsibilities for your application.

❌ The documentation is right. It aims to promote a strong architecture, but it's not uncommon to read services that break the Single Responsibility Principle (SRP):

class OverComplexService
  {
     public function __construct(
        private ProductRepository $productRepository,
        private InvoiceRepository $invoiceRepository,
        private EmailService $emailService,
     );
  }
Enter fullscreen mode Exit fullscreen mode

âś… You must respect that principle. It will be easier to test and maintain.

Symfony: public vs. private services

❌ With Symfony, you can use $container->get('service_id') to call any public service.

We saw earlier that calling the $container like that is considered as a bad practice.

You may not resist the temptation to make all services public, so you can retrieve them by their ID almost everywhere in the project.

Don't do that.

âś… Instead, keep most custom services private and use dependency injection.

Wrap up

Hopefully, you will avoid what I like to call "latent errors" or "hidden errors" with frameworks.

If you don't know how to implement it, trust the framework, but be aware some mechanisms may not be enabled by default.

symfony Article's
30 articles in total
Favicon
From Legacy to Modern: Creating Self-Testable APIs for Seamless Integration
Favicon
Symfony Station Communiqué — 10 January 2025 — A look at Symfony, Drupal, PHP, and other programming news!
Favicon
Symfony Station Communiqué — 03 January 2025 — A look at Symfony, Drupal, PHP, and other programming news!
Favicon
Exploring PHP Frameworks: In-Depth Comparison of Laravel, Symfony, and CodeIgniter
Favicon
WebForms Core Technology in PHP
Favicon
symfony
Favicon
Best PHP, Laravel, and Symfony conferences to attend in 2025
Favicon
PHP Frameworks: hidden errors to avoid
Favicon
Handle your Symfony assets without WebpackEncoreBundle, ViteBundle or AssetMapper
Favicon
Hello from Symfony
Favicon
Symfony Station Communiqué — 27 December 2024 — A look at Symfony, Drupal, PHP, and other programming news!
Favicon
Build a Symfony 7 boilerplate using FrankenPHP, Docker, PostgreSQL and php 8.4
Favicon
SymfonyCon Vienna 2024: Recap of our Experience
Favicon
Using Memcache for Session Storage in Legacy Symfony 1.4/1.5 Projects
Favicon
Doctrine’s Collection filter method - a double-edged sword
Favicon
5 Ways to Optimize Symfony Application Performance
Favicon
Symfony Station Communiqué — 06 December 2024 — A look at Symfony, Drupal, PHP, and other programming news!
Favicon
Symfony monitoring library implementation
Favicon
Symfony Station Communiqué - 29 November 2024. A look at Symfony, Drupal, PHP, and programming news!
Favicon
How To Handle Custom S/DQL Queries On Different Database Engine with DoctrineExpression
Favicon
Symfony Station Communiqué — 15 November 2024. A look at Symfony, Drupal, PHP, and programming news!
Favicon
Another Way to Structure your Symfony Project
Favicon
Automate Symfony EventSubscriberInterface::getSubscribedEvents()
Favicon
Using Symfony’s HeaderBag as a Service: A Debugging Superpower in API Contexts
Favicon
Creating focused domain applications. A Symfony approach (Saving the entity)
Favicon
Symfony Station Communiqué — 11 October 2024. A look at Symfony, Drupal, PHP, and Programming News!
Favicon
Symfony Station Communiqué — 08 November 2024. A look at Symfony, Drupal, PHP, and programming news!
Favicon
Introducing PHP Env Manager: Simplify Environment Management in PHP Applications
Favicon
Creating focused domain applications. A Symfony approach (Returning the result)
Favicon
That Strange PHP Code in Frameworks and CMSs

Featured ones: