Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

LucasFecko's avatar

Facades, Laravel and Nette, rant and comparisons

Hi guys,

I don't have a blog (not much time for that) but I want to say some things and this is the fitting place. In June I started working in a company that has some of the biggest projects in our country, I gained some experience and I am pretty happy there.

As I was becoming more friendlier with the developers working there, I started mentioning Laravel and that we should build a small project (if we will have one) in it.

The main framework we use at work is Nette, for a world very unknown framework but a pretty strong tool in developing PHP applications. I am okay with it, but I prefer Laravel more. Last week, small project came and I pulled Laravel, and the discussion began. I need to mention, that these guys are older than me and have 7+ years experience with PHP and are very strict about deployment processes, object oriented programming and code cleanup. I have 3 years of experience and this experience was gained just by me working alone on my projects, so this job is the first time I work in team.

The two things, they were pretty furious about were facades and service locator pattern, adopted by Laravel. They think that this approach breaks the underlining principle of object oriented programming, that basically everything is accessible everywhere, thanks to facades and service locator. My argument was that thanks to this approach, laravel is so popular, because newcomers can quickly create stuff here, but I agreed with them about facades. I think they are a small evil, because in a big app (I have one in Laravel, it's an app with one year of my personal development almost everyday) you will become flooded with them and pretty lost. I am starting to abandon them and I am preparing to refactor my own project through Christmas, and also prepare it for Laravel 5, when that becomes stable. Anyway, their argument about why not to use facades was:

1.) It's ugly (I understand this, for a guy that loves clean code and OOP, seeing so many "static calls" must be a nightmare) 2.) In your application lifetime, you can't change the object you gain from this facade, because you have no idea how it was instantiated. Here they mean that when there is a request to the application, and in the beginning you begin to use an object gained from facade, and somewhere later you decide that you want to have something changed in this object, or that you want the same object but with different constructor property, you just can't simply switch it, because you have no control over how it was created. Here I partially aggre too.

Anyway, after some arguments and my demonstrations of things we agreed that we can use Laravel, but this are the rules:

1.) Absolutely no facades must be used, everything must be instantiated or resolved from IoC container 2.) Everything must be namespaced (controllers, models, commands, migrations, seeds, everything was reworked and properly namespaced) this was okay with me, it's a more L5 approach and since L5 is still not stable this is basically a preparation for migration to L5 3.) Facades are only allowed in blade templates (well, it's convinient there :))

So my journey to completely abandon facades began, I will now show you how I have stripped down facades from controller domain, so here is the beginning of my BaseController class:

<?php

namespace App\Controller;

class BaseController extends \Controller
{
    protected $app;

    protected $view;

    protected $request;

    protected $redirect;

    protected $auth;

    protected $session;

    public function __construct(\Illuminate\Foundation\Application $app)
    {
        $this->app = $app;
        $this->view = $app->make('view');
        $this->request = $app->make('request');
        $this->auth = $app->make('auth');
        $this->redirect = $app->make('redirect');
        $this->session = $app->make('session');
    }

I have stripped down comments and changed the namespace to App, but this one here is my real life code how I approached this. This BaseController class is extended by every other controller, where in class constructor, the $app object is always typehinted and sent to parent constructor, where objects more specific to current controller class are handled as usual. These instances are just the beginning, I will be adding more as I will need them. This will create a BaseController class with usable instances of my frequently used tools. Overall I am not happy with my own approach. I think this can be better, but I just haven't figured it now or my knowledge is not that good, since I am not that experienced. How would you guys approach this?

The next thing I want to mention are some differences between Laravel and Nette, and what was mentioned in discussion.

You see, there will never be a perfect framework, and every one will have it's small quirks. Laravel offers you direct control over most of your application, so you can control flow from the route to your database. In Nette, you are working with components. Think of components as an objects, that are completely self sufficient, and are filling some particular task. For example, let's have a login form. In Nette, you would create Login component, and this component will handle everything that is connected with login, that means rendering the template, logging user in, accessing the database, everything. In your presenter (Nette uses presenters, Laravel has controllers) you will just instantiate this Login component object and his output will be rendered template, that is then send from presenter to master template and echoed out. This component, if having a form in it, somehow ALONE handles routing. Basically, there is a magic behind the scenes there, that will handle your form processing. You don't need to set up any routing for the form POST method, Nette will handle this. I don't like this, because I as a developer want to have control over this. Sure, it's a quick way to build stuff, but I don't like it when I don't see in it.

The neat thing about components is that you basically can reuse them where you like, wich leads to lesser code writing, and you can have multiple same forms on one page and each of that form is an instance on it's own. You can mimic this approach in Laravel, but every time you want to use your component elsewhere, you need to set up new routing for it.

Nette developers are also very proud about their routes. Since form routes are somehow magically handled, nette router file for big application can have only at maximum 15-20 routes. Compared to my biggest project, that has around 400 routes. I will be very happy with L5 and it's route caching :).

My opinion about this, I am more inclined to Laravel approach, but I also like the components idea, that forces you to build in more OOP way, where your actions are trully represented by objects, and you are not just blindly smashing things in controllers or repositories. Actually Nette trained me to work in more OOP style thanks to this. I used to smash all my work in my repositories, now I have more structuralized handling of things.

Let's move on. Nette and forms. Man, I hate forms in Nette, they are just terrible. The biggest mistake in my opinion is how validation is tightly bundled to forms. Here is how you build forms in Nette:

/**
     * 
     * @return \Nette\Application\UI\Form
     */
    public function createComponentLoginForm()
    {
        $loginForm = new Form;
        $loginForm->setAction($this->link('this#loginform'));
        $loginForm->addText('email', 'E-mail')
            ->setRequired('%label is required.')
            ->setAttribute('placeholder', 'E-mail')
            ->addRule(Form::EMAIL, 'E-mail is not in correct format');
        $loginForm->addPassword('password', 'Password')
            ->setAttribute('placeholder', 'Password')
            ->setRequired('%label is required.');
        $loginForm->addSubmit('login', 'Login');
        $loginForm->onSuccess[] = $this->loginFormSucceeded;
                $loginForm->onFailure[] = $this->loginFormFailed;
        return $loginForm;
    }

Again, a real life code. As you can see, forms in Nette are components on it's own. I personally think that this looks messy and is mixing too much stuff together, that should be separated. Nasty stuff. Laravel has forms like a boss.

I hope my last topic today, let's compare IoC container bindings of these two frameworks. I will provide again real life example of advanced binding in Laravel and in Nette, of the same thing. Laravel:

<?php

namespace App\Provider;

use Illuminate\Support\ServiceProvider;
use App\Model\Post;
use App\Octopus\Storage\MongoStorage;
use App\Social\Scraper\Scraper;
use App\Social\Scraper\Services\Atom;
use App\Social\Scraper\Services\Facebook;
use App\Social\Scraper\Services\Instagram;
use App\Social\Scraper\Services\Twitter;
use App\Social\Scraper\Services\Youtube;

/**
 * Class GeneralProvider
 * @package App\Provider
 */
class GeneralProvider extends ServiceProvider
{
    /**
     * please register general classes here
     */
    public function register()
    {
        $this->app->bind(array('\App\Social\Scraper\Scraper' => 'socialscraper'), function ($app) {
            $config = $app->make('config');
            $socialScraper = new Scraper();
            $socialScraper->addService('facebook', new Facebook());
            $socialScraper->addService('twitter', new Twitter($config->get('social.twitter')));
            $socialScraper->addService('youtube', new Youtube($config->get('social.youtube')));
            $socialScraper->addService('instagram', new Instagram($config->get('social.instagram')));
            $socialScraper->addService('rss', new Atom());
            return $socialScraper;
        });
    }
}

Here we are having one of my self-made tools, Social Scraper (I will make open-source on github when it will be finished). It's a tool that is scraping information from social profiles or RSS feeds, for example you will provide your facebook profile URL and ask for your name, or your Facebook ID, and this handy tool will give you that, via Facebook API. In this binding we are seeing a neat two-way binding, one for a typehinting and one for name binding to be maked from app (this is by the way nowhere mentioned, somebody should write a blog post about it). In the binding I am also registering services, that are available in scraper. This is what binding was made for, you will set up your stuff and you can happily call it ready for you.

Ok, let me show you Nette's way, minified version, with only one service prepared:


facebookScraperService: App\Social\Scraper\Service\Facebook(%social.facebook%) scraper: class: App\Social\Scraper setup: - addService(@facebookScraperService)

So, weird syntax, right? Yes, Nette has developed it's own syntax regarding configuration files, that are with .neon extension. In the first line I am binding Facebook service to facebookScraperService, and with that percentages I am getting config data from config file. under that I am preparing my scraper with Services.

The thing about this is, that it is way cleaner and you have less writing to do. You don't need to create various providers, register them and sending your $app instance through callbacks. You have everything in one file and it's very readable when you get used to it. Here nette wins.

This wasn't direclty a comparison between IoC's, those are for both framework on the same lever and both are great. But Nette wins here with better registering.

Laravel also wins with already implemented database migrations and seeding, much better command environment (artisan), and that it has ORM (Nette chose to go with NotORM).

At the end of day laravel wins, as a more friendlier and popular framework, with amazing community and so many tools and functions to use :).

OK, thats all guys, thank you for reading. I am looking forward to any input!

0 likes
3 replies
milon's avatar

Nice article. I really like your writing. Please keep going. I have learned a lot from your article.

2 likes

Please or to participate in this conversation.