Hiding feature from production — Laravel

I recently started working on an environment cleanup feature. The goal was very simple: erase data from Dev and Stage databases. Usually as per customer request, a copy of their database had been made somewhere and never removed.

I can’t tell if it’s a silly childish fear or a real concern, but I was afraid that someone would end up opening two tabs (production and dev) and mistakenly use the feature in the wrong tab. Have you read the recent incident at GitLab?

Long story short: I developed a feature that will not be available on production and this is how I did it:

1- The RouteServiceProvider

Inside map of RouteServiceProvider, let’s register a new type of route if we’re not on production.

if (!$this->app->environment('production'))
$this->mapDevelopmentRoutes();

Next, define rules for this new type of route, such as filename, controllers namespace and prefix.

/**
* Define the "development" routes for the application.
*
* These routes all receive "web" middleware.
*
*
@return void
*/
protected function mapDevelopmentRoutes() {
Route::middleware(['web', 'auth'])
->namespace($this->namespace . '\Development')
->as('development.')
->prefix('development')
->group(base_path('routes/development.php'));
}

2- The routes/development.php file

Not much to say here besides showing a real-case example. This is what I registered.

<?php

use
Illuminate\Support\Facades\Route;

// These routes should only be available for development environment. RouteServiceProvider will make sure to only register these
// in case the environment is not production.

Route::get('/redactor', 'RedactorController@index')->name('redactor.index');
Route::patch('/redactor', 'RedactorController@redact')->name('redactor.redact');

3- [Optional] The ViewComposer

I have a menu.blade.php file that builds the menu items for the user. I decided to leverage Laravel View Composers to tell this component whether to show the dev-only features.

@if(isset($development) && $development)
<li>
<a href="{{route('development.redactor.index')}}">
<i class="fa fa-eraser fa-fw"></i>
{{ __('Redactor') }}
<span class="pull-right text-muted" title="{{ __('Available for Dev only') }}"><i class="fa fa-warning fa-fw"></i></span>
</a>
</li>
@endif

The DevelopmentComposer file just sets development to true

<?php

namespace
App\Http\ViewComposers;

use Illuminate\View\View;

class DevelopmentComposer extends TenantComposer {

public function compose(View $view) {
parent::compose($view);

$view->with(['development' => true]);
}
}

And the ComposerServiceProvider will only registser the DevelopmentComposer if the environment is not production as well

if (!$this->app->environment('production'))
View::composer('layouts.development.menu', 'App\Http\ViewComposers\DevelopmentComposer');

And yes, this could be set inside RouteServiceProvider together with the mapping of the routes, but I only realized this now (while writing this article) =)

Conclusion

Last week I was redacting about 20 databases and halfway through the task I had a mini heart attack thinking whether I was in production or dev. Then I remembered that I had made sure this would never be a problem. Happy ending.

Hacker Noon is how hackers start their afternoons. We’re a part of the @AMIfamily. We are now accepting submissions and happy to discuss advertising & sponsorship opportunities.
To learn more, read our about page, like/message us on Facebook, or simply, tweet/DM @HackerNoon.
If you enjoyed this story, we recommend reading our latest tech stories and trending tech stories. Until next time, don’t take the realities of the world for granted!

More by Marco Aurélio Deleu

Topics of interest

More Related Stories