I have a Laravel app that requires getting some config vars that need to be used by most of my controllers.
Therefore it seems like this would be the perfect time to use middleware.
Is this the correct use of middleware? and if so, once the middleware gets the config vars, is it best practice to add these to the request object so they can be accessed by my controller?
Thanks to any responders.
J
Not, definitely!
Actually (based on you've written), the best way to go is creating an application service and registering this service on Service Container - App\Providers\AppServiceProvider (in app/Providers/AppServiceProvider.php).
Something like this:
<?php
# The Config Service:
namespace App\Services;
/**
* Config Manager
*/
class Config
{
/** #var SomeDependency */
protected $dependency;
public function __construct(SomeDependency $dependency)
{
$this->dependency = $dependency;
}
public function getVar($var)
{
// ...
}
}
In your Service Provider:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
//...
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->registerConfigManager();
}
public function registerConfigManager()
{
$this->app->singleton('config_service', function ($app) {
return new \App\Services\Config(new \SomeNamespace\SomeDependency);
});
}
//...
}
And now you can to access the service container via app(), like this:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
class MyController extends Controller
{
public function index(Request $request)
{
app('config_service')->getVar('key');
//...
}
}
IMO, middlewares are made for pre-processing requests, restrict user access, and other security related.
I would simply load the configuration in the main Controller class and use it in the extending controllers.
For example:
base controller
namespace App\Http\Controllers;
uses goes here ...;
class Controller extends BaseController
{
protected $configs = [];
public function __construct() {
$this->loadConfigs();
}
protected function loadConfigs()
{
//read configuration files or tables in database
//and put the values into '$this->configs';
}
}
user controller
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
class User extends Controller
{
public function index()
{
echo $this->configs['toolbar.color']; //just an example
}
}
Related
I'm working with Laravel 9 and I have a Controller like this:
use App\Repositories\HomeRepositoryInterface;
class HomeController extends Controller
{
private $homeRespository;
public function __construct(HomeRepositoryInterface $homeRepository)
{
$this->homeRespository = $homeRepository;
}
...
And here is the HomeRepositoryInterface:
<?php
namespace App\Repositories;
interface HomeRepositoryInterface
{
public function newest();
}
And this is the HomeRepository itself:
<?php
namespace App\Repositories;
use App\Models\Question;
class HomeRepository implements HomeRepositoryInterface
{
public function newest()
{
return $ques = Question::orderBy('created_at', 'DESC')->paginate(10);
}
}
But now I get this error:
Target [App\Repositories\HomeRepositoryInterface] is not instantiable while building [App\Http\Controllers\HomeController].
So what's going wrong here?
How can I solve this issue?
It seems that you did not introduce the service container.
For this, it is better to create a service provider as shown below and introduce the repository class to the container.
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Repositories\HomeRepositoryInterface;
use App\Repositories\HomeRepository;
class RepositoryServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* #return void
*/
public function register()
{
// Bind Interface and Repository class together
$this->app->bind(HomeRepositoryInterface::class, HomeRepository::class);
}
}
Next, you should introduce this service provider in the config/app.php file.
'providers' => [
...
...
...
App\Providers\RepositoryServiceProvider::class,
],
I'm new to Lumen, and have a fresh install (v8.2.4) and have followed the docs, trying to write my own service, but I keep getting error
"Target class [App\Prodivers\BatmanServiceProvider] does not exist."
Like I said, its a fresh install according to the Lumen docs.
in /bootstrap/app.php
$app->register(App\Providers\BatmanServiceProvider::class);
in /app/Providers/BatmanServiceProvider.php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class BatmanServiceProvider extends ServiceProvider
{
public function register()
{
return "batman!";
}
}
My controller: app/Http/Controllers/MainController.php
<?php
namespace App\Http\Controllers;
use App\Prodivers\BatmanServiceProvider;
class MainController extends Controller{
public function __construct(BatmanServiceProvider $BatmanServiceProvider){
}
public function main(){
print "hello space!";
}
}
What am I missing/doing wrong?
in /bootstrap/app.php
$app->register(App\Providers\BatmanServiceProvider::class);
in /app/Providers/BatmanServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Services\BatmanService;
class BatmanServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->bind(BatmanService::class, function(){
return new BatmanService;
});
}
}
create Services folder in your_lumen_project/app, and create php file BatmanService.php
in /app/Services/BatmanService.php
<?php
namespace App\Services;
class BatmanService
{
public function sayHello(){
return 'hi, space!';
}
}
Now, you can use anywhere!
<?php
namespace App\Http\Controllers;
use App\Services\BatmanService;
class MainController extends Controller{
protected $batmanService;
public function __construct(BatmanService $batmanService){
$this->batmanService = $batmanService;
}
public function main(){
return $this->batmanService->sayHello(); // "hi, space!"
}
}
I'm trying to share a collection of notifications to all views under the auth middleware. I thought I might be able to just call Auth::check() but it seems to always return false?
<?php
namespace App\Providers;
use Illuminate\Http\Request;
use Illuminate\Support\ServiceProvider;
use Auth;
class ViewServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
* #return void
*/
public function boot()
{
view()->composer('*', function ($view)
{
$view->with('userNotifications', Auth::user()->notifications);
});
}
}
I've bind my interface called CustomerRepository to EloquentCustomerRepository. This is my CustomerServiceProvider:
public function register()
{
$this->app->bind(CustomerRepository::class,EloquentCustomerRepository::class);
$this->app->bind(PackageRepository::class,EloquentPackageRepository::class);
}
When I try to instantiate it in my controller like this:
<?php
namespace App\Http\Controllers\api\v1;
use Lsupport\repositories\api\v1\customer\CustomerRepository;
use App\Http\Controllers\Controller;
use Lsupport\customer\Customer;
use App\Http\Requests;
class CustomerController extends Controller
{
protected $CustomerRepository;
public function __construct(CustomerRepository $CustomerRepository)
{
$this->CustomerRepository = $CustomerRepository;
}
It throws the following error:
Target [Lsupport\repositories\api\v1\Customer\CustomerRepository] is not instantiable while building [App\Http\Controllers\api\v1\CustomerController].
I also registered it in app.config:
App\Providers\CustomerServiceProvider::class,
What am I doing wrong?
CustomerServiceProvider
<?php
namespace App\Providers;
use Lsupport\repositories\api\v1\customer\EloquentCustomerRepository;
use Lsupport\repositories\api\v1\customer\EloquentPackageRepository;
use Lsupport\repositories\api\v1\customer\CustomerRepository;
use Lsupport\repositories\api\v1\customer\PackageRepository;
use Illuminate\Support\ServiceProvider;
class CustomerServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
//
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
$this->app->bind(CustomerRepository::class,EloquentCustomerRepository::class);
$this->app->bind(PackageRepository::class,EloquentPackageRepository::class);
}
}
CustomerRepository
<?php
namespace Lsupport\repositories\api\v1\Customer;
interface CustomerRepository
{
public function create($request);
}
**EloquentCustomerRepository**
<?php
namespace Lsupport\repositories\api\v1\customer;
use Lsupport\repositories\api\v1\customer\CusteromRepositoryTrait;
use Lsupport\repositories\api\v1\remain\RightTrait;
use Lsupport\repositories\api\v1\remain\JsonTrait;
use Lsupport\customer\Customer;
class EloquentCustomerRepository implements CustomerRepository
{
use JsonTrait;
use RightTrait;
use CustomerRepositoryTrait;
code.....
Ok, the first thing I notice is that you probably want the same namespaces on the interface and on the class. So, the namespace of EloquentCustomerRepository should be
namespace Lsupport\repositories\api\v1\Customer;
and not
namespace Lsupport\repositories\api\v1\customer;
(with lower customer).
Now, on your CustomerServiceProvider, you should use:
public function register()
{
$this->app->bind('Lsupport\repositories\api\v1\Customer\CustomerRepository', 'Lsupport\repositories\api\v1\Customer\EloquentCustomerRepository');
}
Make sure you run composer dumpautoload -o on the command line.
In PHP, I used to define some variables in my header.php and use them in all my pages. How can I have something like that in Laravel?
I am not talking about View::share('xx', 'xx' );
Assume I want to have a variable which holds a number in it and I need this number inside all my controllers to calculate something.
Sounds like a good candidate for a configuration file.
Create a new one, let's call it calculations.php:
Laravel ~4ish:
app
config
calculations.php
Laravel 5,6,7+:
config
calculations.php
Then put stuff in the new config file:
<?php return [ 'some_key' => 42 ];
Then retrieve the config in your code somewhere (note the file name becomes a "namespace" of sorts for the config item):
echo Config::get('calculations.some_key'); // 42 in Laravel ~4
echo config('calculations.some_key'); // 42 in Laravel ~5,6,7+
Set a property on the BaseController, which should be located in your controllers directory.
Your controllers should extend the BaseController class and thus inherit its properties.
You could use View Composers
And instead of using the boot method described in the docs you could use:
public function boot()
{
// Using class based composers...
view()->composer(
'*', 'App\Http\ViewComposers\ProfileComposer'
);
// Using Closure based composers...
view()->composer('*', function ($view) {
});
}
That would render whatever variables you declare with
$view->with('yourVariableName', 'yourVariableValue');
to all the views in your app.
Here is a full example of how I used this in one of my projects.
app/Providers/ComposerServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
view()->composer(
'*', 'App\Http\ViewComposers\UserComposer'
);
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
//
}
}
app/Http/ViewComposers/UserComposer.php
<?php
namespace App\Http\ViewComposers;
use Illuminate\Contracts\View\View;
use Illuminate\Contracts\Auth\Guard;
class UserComposer
{
protected $auth;
public function __construct(Guard $auth)
{
// Dependencies automatically resolved by service container...
$this->auth = $auth;
}
public function compose(View $view)
{
$view->with('loggedInUser', $this->auth->user());
}
}
Just remember that because you declared a new service provider it needs to be included in the 'providers' array in config/app.php
You can define them in your app\Http\Controllers\Controller.php , for example:
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
public $test = 'something';
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}
Then afterwards in all of your controllers, you can access this property by doing:
$this->test;