global variable in laravel - php

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;

Related

Target [Interface] is not instantiable while building [Controller]

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,
],

Custom class and ServiceProvider - Laravel 5.4

I try to make a new custom class in laravel 5.4 to check the user type.
I add this new class in a new folder app\ItSolution, code:
<?php
namespace App\ItSolution;
class DemoClass {
public function getPermission() {
switch(Auth::user()->user_type_id) {
case 1:
return 'admin';
break;
case 2:
return 'promoter';
break;
case 3:
return 'customer';
break;
default:
return false;
}
}
}
I want to use this class in all my app , so i try to make a new ServiceProvider, code :
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App;
class AuthLibServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
//
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
App::bind('democlass', function()
{
return new \App\ItSolution\DemoClass;
});
}
}
And i make a new facade for my class in the same folder app\ItSolution, code:
<?php
namespace App\ItSolution;
use Illuminate\Support\Facades\Facade;
class DemoClassFacade extends Facade {
protected static function getFacadeAccessor() { return 'democlass'; }
}
After that i add this line in app/config.php
'aliases' => [
...
'DemoClass'=> App\ItSolution\DemoClassFacade::class,
]
'providers' => [
...
App\Providers\AuthLibServiceProvider::class,
]
But i have this error when i try to use the DemoClass alias in my controller
DemoClass::getPermission():
Class 'App\Http\Controllers\DemoClass' not found
How can i fix that please, Thnaks.
In laravel 5.4 you don't need a Service Provider to register a facade, you can use automatic Facadaes, you have to define only the DemoClass.
i.e in a controller:
use Facades\ {
App\ItSolution\DemoClass
};
And call the function
DemoClass::getPermission()
Source here
You're registering this class as facade, so you'll need to add this to the beginning of the class:
use DemoClass;
Or you can just use full namespace when using the facade:
\DemoClass::

Should I use Laravel Middleware?

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
}
}

Laravel Service provider not working

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.

Laravel 5.2 What goes in facade getFacadeAccessor return

So I am trying to create my first ever Service provider and complimentary Facade in Laravel.
Service Provider:
<?php namespace Jbm\Providers;
use Illuminate\Contracts\Http\Kernel;
use Illuminate\Http\Request;
use Illuminate\Support\ServiceProvider as BaseServiceProvider;
use Jbm\Helpers\ReportGenerator;
class ReportGeneratorServiceProvider extends BaseServiceProvider
{
/**
* Indicates if loading of the provider is deferred.
*
* #var bool
*/
protected $defer = true;
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
$this->app->bind('Jbm\Helpers\Contracts\ReportGeneratorContract', function($app){
return new ReportGenerator();
});
}
/**
* Add the Cors middleware to the router.
*
* #param Kernel $kernel
*/
public function boot(Request $request, Kernel $kernel)
{
//
}
/**
* Get the services provided by the provider.
*
* #return array
*/
public function provides()
{
return array('jbm.reportGenerator');
}
}
Facade:
<?php
namespace Jbm\Facades;
use Illuminate\Support\Facades\Facade;
class ReportGenerator extends Facade
{
protected static function getFacadeAccessor()
{
return 'jbm.reportGenerator';
}
}
It seems that every package I look at handles things different ways. One thing I am confused about is what is supposed to go in the return of getFacadeAccessor() in the Facade. In my service provider I say it provides jbm.reportGenerator and then use that in the Facade but I don't know how that connects to what I've registered. Any help would be greatly appreciated.
Update:
I decided to add my service provider and my facade to my config/app.php and then tried to use it in a controller and it says "Report Generator not found". So it obviously isn't working...no idea why
Update 2:
After removing the dot in the name I am now getting Call to undefined method Jbm\Facades\ReportGenerator::parseConfig().
First, your service provider should be in the App\Providers namespace, and should extend ServiceProvider. So it will look like this:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Jbm\Helpers\ReportGenerator;
class ReportGeneratorServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('Jbm\Helpers\Contracts\ReportGeneratorContract', function($app){
return new ReportGenerator();
});
}
}
After that, the facade should be in the App\Facades namespace, and the getFacadeAccessor() method should return the class name of your service provider:
<?php
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class ReportGenerator extends Facade
{
protected static function getFacadeAccessor()
{
return App\Providers\ReportGeneratorServiceProvider::class;
}
}
Now, let's add the service provider and facade to the app:
// config/app.php
'providers' => [
App\Providers\ReportGeneratorServiceProvider::class,
]
'aliases' => [
'ReportGenerator' => App\Facades\ReportGenerator::class,
]
getFacadeAccessor should return a string that your container "knows about". That means something that is registered via a Provider.
You add your facade and an alias to app.php to be able to access something your registered statically.
So when you call YourFacadeAlias::doSomething(); laravel detects YourFacaseAlias, sees what is returned from getFacadeAccessor and uses that result to return an object associated with it from container.
Since both your facade and helper are called "ReportGenerator" the problem might be with both of them. But I think you should first check your app.php to see if you set it right. And then make sure your getFacadeAccessor and binded values match.

Categories