Resolving the $entry variable for custom routes somewhere but a Twig template I have several custom routes defined on the routes.php and, as usual, I am resolving the value of the template's entry in the Twig template when it is not defined (which is when it doesn't match a Craft Route) but I'd like to do it somewhere else before it reaches the template because I want to remove the logic in Twig. 

Can I add a method to be executed before last Craft's renderTemplate($template, $variables) in which I would resolve and add $entry to $variables when it's not defined? What's the way to go?

Thank you :)
Alright, if you didn't already create a custom plugin I suggest you to visit Pluginfactory.io to create the boilerplate. Let's assume your plugin handle is awesome-plugin, just for testing purposes.

You create a controller with the name RouteController that contains the function actionMyAwesomeRoute

In summary:

handle: awesome-plugin
controller: RouteController
function: actionMyAwesomeRoute

All routes in Craft are defined via plugin-handle/controller-name/function-name without the "required" parts - and in snake-case

That means your route will be awesome-plugin/route/my-awesome-route (remove "Controller" and "action")

That being said: you can register your routes in your Plugins main init function

Defining the routes

public function init(){

    Event::on(
        UrlManager::class,
        UrlManager::EVENT_REGISTER_SITE_URL_RULES,
        function(RegisterUrlRulesEvent $event) {
            // easy route for demonstration
            $event-&gt;rules[] = [
                'pattern' =&gt; '/some-nice-url',
                'route'   =&gt; 'awesome-plugin/route/my-awesome-route'
            ];
            // when you visit www.example.com/some-nice-url your function will be executed

            // more complex example if you are not interested
            // skip that and don't think about it
            $event-&gt;rules[] = [
                'pattern' =&gt; 'my-fancy-route/&lt;action:&gt;/&lt;id:\d+&gt;/&lt;siteHandle:\w+&gt;', 
                'route' =&gt; 'awesome-plugin/route/&lt;action&gt;', 
                'defaults' =&gt; [
                    'id' =&gt; null, 
                    'siteHandle' =&gt; null, 
                    'action' =&gt; 'index'
                ]
            ];
            // you can visit this route via www.example.com/my-fancy-route
            // this way, your actionIndex will be called
            // when you do www.example.com/my-fancy-route/foo
            // Craft tries to call the actionFoo in your Controller
            // www.example.com/my-fancy-route/bar -&gt; actionBar

            // when you do www.example.com/my-fancy-route/edit/5
            // your actionEdit will be called and Craft passes 5 as a parameter

            // www.example.com/my-fancy-route/save-entry/9/siteOne
            // will call actionSaveEntry(9, 'siteOne');

        }
    }
}


Your Controller

public function actionMyAwesomeRoute(){
    $variables = // define whatever you want

    return $this-&gt;renderTemplate('path/to/template', $variables);
}


More complex examples, skip that if you don't need it

// www.example.com/my-fancy-route/show-entry/9/siteOne
public function actionShowEntry($id = null, $siteHandle = null){
    // $id will be 9, $siteHandle 'siteOne' since those parameters
    // are passed via URL, otherwise they are both null
    $entry = Craft::$app-&gt;getElements()-&gt;getElementById($id, $siteHandle);

    return $this-&gt;renderTemplate('path/to/template',  ['entry' =&gt; $entry]);
}


Just a little bit more complex stuff

You could actually use the default route and inject it with another parameter as well. So When you have an existing route to an entry like news/2018/feb/awesome-news/ you can as well visit this entry with news/2018/feb/awesome-news/fooBar

$event-&gt;rules[] = [
    'pattern' =&gt; '/&lt;route:\S+&gt;/&lt;something:\S+&gt;',
    'route'   =&gt; 'awesome-plugin/route/catch-all'
];


And in your Controller

public function actionCatchAll($route, $something){
    $entry = Craft::$app-&gt;getElements()-&gt;getElementByUri($route);
    if ($entry instanceof Entry) {
        $section = $event-&gt;getSection();
        $siteSettings = $section-&gt;getSiteSettings();
        foreach ($siteSettings as $site) {
            if ((int) $site-&gt;siteId === (int) $entry-&gt;siteId) {
                $templatePath = $site-&gt;template; // the template path for the entry
                return $this-&gt;renderTemplate(
                    $templatePath,
                        [
                            'entry'     =&gt; $entry,
                            'whatever'  =&gt; $something
                        ]
                    );
            }
        }
    }

    return Craft::$app-&gt;runAction(Craft::$app-&gt;getRequest()-&gt;getFullPath());
}