How can I add CORS middleware to routes defined in custom Laravel Nova tool? - laravel

I'm building a headless cms using laravel nova and vuejs.
I'm having an issue with trying to register the excellent CORS middleware from https://github.com/barryvdh/laravel-cors. I can get this working from the main app but I would like to add this as a dependency to my custom nova tool.
I just can't figure out how to do this.
I've tried adding the middleware in the routes function generated by the artisan nova:tool command.
/**
* Register the tool's routes.
*
* #return void
*/
protected function routes()
{
if ($this->app->routesAreCached()) {
return;
}
Route::middleware(\Barryvdh\Cors\HandleCors::class)
->prefix('api/meta-blog')
->group(__DIR__.'/../routes/api.php');
}
But I get an error Class Barryvdh\Cors\HandleCors does not exist from vendor/laravel/framework/src/Illuminate/Container/Container.php when I hit any of the api paths.
I think this is because the middleware is not registered with the main app. I'm looking to find out how to make this 3rd party nova tool dependency work with the main laravel routing system.
I have successfully used other 3rd party packages with success. But not this one. I can confirm that the package exists and has been loaded in my custom tools autoload file.
Thanks in advance.

I solved this.
In the boot function we can push a middleware to the api group.
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
...
$router = $this->app['router'];
$router->pushMiddlewareToGroup('api', Barryvdh\Cors\HandleCors::class);
}
Then in the routes function
/**
* Register the tool's routes.
*
* #return void
*/
protected function routes()
{
if ($this->app->routesAreCached()) {
return;
}
Route::prefix('api/meta-blog')
->group(__DIR__.'/../routes/api.php');
}
Hope this helps someone else.

Related

Laravel - Making Routes in file other than web.php

Making routes of various pages of a website in web.php makes it bulky and unstructured. So my question is is there any way to save it in separate files?
// Calling Registration function
Route::any('/admin-store','AdminUserController#store')->name('admin-reg');
// Redirecting to Registration page
Route::get('/admin-registration','AdminUserController#index')->name('admin-registration');
// Redirecting to login page
Route::get('/admin-login','AdminLoginController#index')->name('admin-login');
// Redirecting to Admin Profile Page
Route::get('/admin-profile','AdminProfileController#index')->name('admin-profile');
// Calling Login function
Route::post('admin-login-result','AdminLoginController#login')->name('admin-log');
// Calling Function to Update Profile
Route::post('admin-edit-profile','AdminEditController#updateProfile')
->name('admin-edit-profile');
// Redirecting to Profile Edit page
Route::get('/admin-edit-profile','AdminEditController#index')->name('admin-edit');
Short answer
Yes, you can store routes in different files.
Expanded answer
1 - Create your new Route file
Create your new route file, for this example I'll name it users.php and store there the related routes:
routes/users.php
Route::get('/my-fancy-route', 'MyCoolController#anAwesomeFunction');
// and the rest of your code.
2 - Add your route file to the RouteServiceProvider
Add here a new method, i'll call it mapUserRoutes:
app/Providers/RouteServiceProvider.php
/**
* Define the User routes of the application.
*
*
* #return void
*/
protected function mapUserRoutes()
{
Route::prefix('v1') // if you need to specify a route prefix
->middleware('auth:api') // specify here your middlewares
->namespace($this->namespace) // leave it as is
/** the name of your route goes here: */
->group(base_path('routes/users.php'));
}
3 - Add it to the map() method
In the same file(RouteServiceProvider.php), go to the top and add your new method inside the map() function:
/**
* Define the routes for the application.
*
* #return void
*/
public function map()
{
// some other mapping actions
$this->mapUserRoutes();
}
4 - Final steps
I'm not fully sure if this is neccesary but never hurts to do:
Stop your server (if runing)
do php artisan config:clear
Start your server.

Check if input is from console

I want to share a variable of my views with:
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
\Schema::defaultStringLength(191);
$customers = Customer::get();
\View::share('customers', $customers);
}
}
it works as expected, but when I want to migrate my tables via artisan it throws an error, that the table for customers was not found because it is checked BEFORE the migration starts. So I need something like
if(!artisan_request) {
//request to laravel is via web and not artisan
}
But I haven't found anything in the documentation.
You can check if you are running in the console by using
app()->runningInConsole()
Underneath that, all it does is check the interface type
return php_sapi_name() == 'cli' || php_sapi_name() == 'phpdbg'
You can find more on the PHP Docs site
To detect whether the app is running in console, you can do something like this:
use Illuminate\Support\Facades\App;
if(App::runningInConsole())
{
// app is running in console
}
See, illuminate/Foundation/Application.php:520

use config file of custom package without publishing in Laravel 5.*

I have a config file for my Laravel Custom package.
Currently I am using custom package's config file by publishing it as mentioned in the docs.
I just want to clarify that, Is there a way to use custom package's config file without publishing it in Laravel 5.*
Solved it.
Here's the code that I used.
public function register()
{
if ($this->app['config']->get('custom_package') === null) {
$this->app['config']->set('custom_package', require __DIR__.'/../Config/config.php');
}
in the ServiceProvider for the custom package.
You can use mergeConfigFrom method of your package's ServiceProvider
/**
* Register bindings in the container.
*
* #return void
*/
public function register()
{
$this->mergeConfigFrom(
__DIR__.'/path/to/config/courier.php', 'courier'
);
}

How i can extend laravel translator (any other component)?

I want to implement some extra features to Illuminate\Translate\Translator.
So, i create my folder in ~/vendor directory, place there My/Traslator class, that will implement Symfony\Component\Translation\TranslatorInterface. Right?
Is it OK to extend laravel translator class (a lot of functionality will be duplicated otherwise) in my package?
If it is ok - it will be necessary to tie to current laravel version to keep code stable. But what will happen in case enduser laravel version will differ from one required in my package?
What should i do then to make laravel use my translator class in application (facades,etc)?
Make a Translator class and make it extend Illuminate\Translation\Translator
<?php
namespace App\Helpers;
use Illuminate\Translation\Translator as LaravelTranslator;
class Translator extends LaravelTranslator
{
// here you can overwrite any functions you want/need
}
Create your own TranslationServiceProvider inside app/providers (just copy the laravel translation service provider and change the line where it uses Translator with your own Translator class where you have overwritten what you needed)
<?php
namespace App\Providers;
use App\Helpers\Translator; // <= Your own class
use Illuminate\Translation\FileLoader;
use Illuminate\Support\ServiceProvider;
class TranslationServiceProvider extends ServiceProvider
{
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
$this->registerLoader();
$this->app->singleton('translator', function ($app) {
$loader = $app['translation.loader'];
// When registering the translator component, we'll need to set the default
// locale as well as the fallback locale. So, we'll grab the application
// configuration so we can easily get both of these values from there.
$locale = $app['config']['app.locale'];
$trans = new Translator($loader, $locale);
$trans->setFallback($app['config']['app.fallback_locale']);
return $trans;
});
}
/**
* Register the translation line loader.
*
* #return void
*/
protected function registerLoader()
{
$this->app->singleton('translation.loader', function ($app) {
return new FileLoader($app['files'], $app['path.lang']);
});
}
/**
* Get the services provided by the provider.
*
* #return array
*/
public function provides()
{
return ['translator', 'translation.loader'];
}
}
Comment out or delete the Laravels translator service line inside config/app.php:
//Illuminate\Translation\TranslationServiceProvider::class,
Add your own Provider in that same array
App\Providers\TranslationServiceProvider::class,
This page has more information: http://laravel.com/docs/5.0/extending#container-based-extension
So what you need to do is:
Extend the built-in class from the vendor directory
Create a new service provider that add your translation class to the service container
Replace Laravel’s translation service provider in your config/app.php file with the namespace of your translation service provider
Now when you ask for the translation service provider out of the service container—either directly (app('translator')) or with the Lang façade, it will return your translation class rather than Laravel’s.

What is the best way to setup a view plugin in Zend Framework 2?

I'm trying to setup a view plugin to expose the route matches in Zend Framework 2.
The plugin is something like this:
class GetRouteMatch extends AbstractHelper
{
/**
* Route match returned by the router.
*
* #var RouteMatch.
*/
protected $routeMatch;
/**
* Set route match returned by the router.
*
* #param RouteMatch $routeMatch
* #return self
*/
public function setRouteMatch(RouteMatch $RouteMatch)
{
$this->routeMatch = $RouteMatch;
return $this;
}
public function __invoke($param)
{
return $this->routeMatch->getParam($param, false);
}
}
What is the best way to setup the RouteMatch object?
I have to do it in the module bootstrap or in the controller?
For the moment I've resolved this way inside the controller action
$renderer = $this->getLocator()->get('Zend\View\Renderer\PhpRenderer');
$routeMatch = $renderer->plugin('routeMatch');
$routeMatch->setRouteMatch($this->getEvent()->getRouteMatch());
The RouteMatch object is injected manually.. but I'm sure there's a better way
The best is to initialize such code in your module class. You can attach an event there to inject dependencies like the routematch. However, the routematch will be available to inject soon. There is work in progress to set the routematch in a service locator. This means you can configure DI it will pull the routematch from the service locator. Then you don't need to write these things yourself anymore.

Resources