I'm using a package with cities and countries in my Laravel project. I set up a repository pattern to use this cities data. My plan is to send the cities data to the register view or any other view I want. In the example here I want to send to the project.create page. I tested the repository and when I look through the controller, I can pass the data to the view and print it with dd(). There is no problem with this. Now I want to send this data to a view i want via viewcomposer.
First of all, I wrote a ComposerServiceProvider.php file as follows
<?php
namespace App\Providers;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
View::composer(
'project.create',
'App\View\Composers\LocationComposer'
);
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
//
}
}
Then I wrote the composer file, which is as follows:
<?php
namespace App\View\Composers;
use App\Repository\Eloquent\LocationRepository;
use Illuminate\View\View;
class LocationComposer
{
/**
* #var LocationRepository
*/
public $locationlist;
/**
* LocationComposer constructor.
* #param LocationRepository $locations
* #return void
*/
public function __construct(LocationRepository $locations)
{
$this->locationlist = $locations->getAllCities();
}
/**
* Bind data to the view.
*
* #param \Illuminate\View\View $view
* #return void
*/
public function compose(View $view)
{
$view->with('cities', $this->locationlist);
}
}
But the data does not pass to the view I want.
this is the error i got
Things I've tried and done:
-I registered the composerserviceprovider via app config.
-I ran php artisan config:clear
-I tried to send to other views Welcome, register etc.
I suspect I am not invoking the repository correctly into composer.
Thanks for your help...
Probabaly you didn't add App\Providers\ComposerServiceProvider::class into your config/app.php file. All additional service providers need to be added into providers array of config/app.php file.
Related
I am using Laravel 7.0.
I have created a new module and in the new modules RouteServiceProvider.php file changed the prefix of the API routes to cp.
I am now trying to send some query parameters but nothing is received in the controller action method.
Here you can see the Laravel Telescope also not showing any query parameters. I checked the Nginx logs and query parameters are present there.
php artisan route:list is showing the route correctly.
Here is the code of the controller.
<?php
namespace Modules\SomeModule\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
class PartnerController extends Controller
{
/**
* List all Partners
*
* #param Illuminate\Http\Request $request
* #return \Illuminate\Http\JsonResponse
*/
public function index(Request $request)
{
$page = $request->query('page'); // it is always null
$pageSize = $request->query('page_size'); // it is always null
return response()->json(['page' => $page, 'page_size' => $pageSize]);
}
}
Here is the code of RouteServiceProvider. I am using nWidart/laravel-modules package to generate modules in my app.
<?php
namespace Modules\SomeModule\Providers;
use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
class RouteServiceProvider extends ServiceProvider
{
/**
* The module namespace to assume when generating URLs to actions.
*
* #var string
*/
protected $moduleNamespace = 'Modules\SomeModule\Http\Controllers';
/**
* Called before routes are registered.
*
* Register any model bindings or pattern based filters.
*
* #return void
*/
public function boot()
{
parent::boot();
}
/**
* Define the routes for the application.
*
* #return void
*/
public function map()
{
$this->mapApiRoutes();
}
/**
* Define the "api" routes for the application.
*
* These routes are typically stateless.
*
* #return void
*/
protected function mapApiRoutes()
{
Route::middleware('api')
->prefix('cp')
->namespace($this->moduleNamespace)
->group(module_path('SomeModule', '/Routes/api.php'));
}
}
When I changed the API prefix back to api it works absolutely fine.
Can someone please guide what is going on here? Thanks!
I have a part of site that starts with specific prefix /manage.
Can I somehow like with AppServiceProvider view-composers inject a variable in all routes from that prefix?
I tried to do it by passing this variable to layout of all that routes. But then I met a problem. I use this variable in blade view of specific page, and it returns me variable not defined.
Then, I inspect laravel debugger and saw the order of loading of blade files. And it was :
1. Current page view
2. Layout view
3. Sidebars and other stuff
So, the fact that current page is loaded before layout, cause error of undefined variable.
So, how can I solve that ? Thanks.
Code from my Service provider :
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\CT;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
view()->composer(['website.implicare.ct.show', 'website.implicare.ct.petition.index', 'layouts.ct'], function($view) {
$ct = request()->ct;
$permissions = [];
foreach($ct->userPermissions(auth()->id()) as $userPermission) {
if($userPermission->pivot->ct_id == $ct->id) {
array_push($permissions, $userPermission->name);
}
}
$view->with('permissions', $permissions);
});
}
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
}
create ComposerServiceProvider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public $theme = 'mytheme';
public function boot()
{
view()->composer($this->theme.'.includes.navbar', 'App\Http\ViewComposers\MenuComposer');
view()->composer($this->theme.'.includes.header', 'App\Http\ViewComposers\MenuComposer');
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
//
}
}
I need to access some data (User details) in most views. What I have done:
I created ComposerServiceProvider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
view()->composer(
['includes.header','profile'],
'App\Http\ViewComposers\CustomerComposer'
);
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
//
}
}
Created CustomerComposer class
<?php
namespace App\Http\ViewComposers;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
use Modules\Customers\Entities\CustomerDetail;
class CustomerComposer
{
public $customer = [];
/**
* Bind data to the view.
*
* #param View $view
* #return void
*/
public function compose(View $view)
{
$user = Auth::guard('customer');
$this->customer = CustomerDetail::where('user_id',$user->id())->first();
$view->with( 'customer', $this->customer );
}
}
Everything works but when I look at Debug bar it shows me same queries excecuted per view, so for example if I define ['includes.header','profile'] Same SQL will be excecuted twice if ['includes.header','profile','something_else'] 3 times and so on...
In this case query's is
select * from `customer_details` where `user_id` = '1' limit 1
select * from `customer_details` where `user_id` = '1' limit 1
If I provide wildcard in
view()->composer(
['*'],
'App\Http\ViewComposers\CustomerComposer'
);
It will generate 23 queries! I missed something here?
Ok I think I found solution. In ComposerServiceProvider class:
/**
* Register the application services.
*
* #return void
*/
public function register()
{
$this->app->singleton(\App\Http\ViewComposers\CustomerComposer::class);
}
That it.
In Laravel Docs
Registering A Singleton
Sometimes, you may wish to bind something into the container that
should only be resolved once, and the same instance should be returned
on subsequent calls into the container:
Per the manual at https://laravel.com/docs/5.5/views#view-composers:
"View composers are callbacks or class methods that are called when a view is rendered. If you have data that you want to be bound to a view each time that view is rendered, a view composer can help you organize that logic into a single location."
(emphasis mine)
In this case:
view()->composer(
['includes.header','profile'],
'App\Http\ViewComposers\CustomerComposer'
);
you're attaching the includes.header view and the profile view, which I guess includes the includes.header view. So, since the composer is executed when the view is rendered, it'll execute twice, one when rendering of the profile view and again another when rendering the includes.header view.
You can use config here to resolve multiple times query run issue for view compose. For example show below code.
public function compose(View $view)
{
if(!Config::has('composeVars'))
{
Config::set('composeVars') = [
'users' => User::all();
];
}
$view->with('*', Config::get('composeVars'));
}
I've a view composer written like this
view()->composer('masterbox.partials.pipeline', function($view) {
// Some vars and code
});
In one of my view I do as follow
#include('masterbox.partials.pipeline', ['my_var' => 1])
When i'm trying it on my browser everything is fine, but when I run a simple test everything blows up ... After some debugging I found out the closure wasn't executed at all.
$this->visit('/connect/customer/subscribe')
->type($faker->firstName, 'first_name')
->type($faker->firstName, 'first_name')
->type($faker->lastName, 'last_name')
->type($faker->email, 'email')
->type($faker->phoneNumber, 'phone')
->type($password, 'password')
->type($password, 'password_confirmation')
->press("S'inscrire");
Note : It visits a page, fills the form and subscribe, then it redirects on the page with the #include and it returns a big error, part of it is
exception 'ErrorException' with message 'Undefined variable: my_var' in /Users/Loschcode/Google Drive/projects/my_project_lo/website/storage/framework/views/7e11f284c02bc38adc60b5f8a0545df65d7cf5ec.php:7
I'm afraid it an issue, it's a fresh Laravel 5.2 I downloaded a few days ago. Any guess ? Any method to debug this ? Thanks
Working solution
I ended up trying anything. My problem was my service provider organization.
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
foreach (glob(app_path().'/Http/ViewComposers/*.php') as $filename){
require_once($filename);
}
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
//
}
}
If you have a similar organization and problem, replace the require_once by a simple require and everything will go fine.
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
foreach (glob(app_path().'/Http/ViewComposers/*.php') as $filename){
require($filename);
}
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
//
}
}
I am quite new to Laravel and I really need some help. I need to create a simple app for my job, and I think I will not have problem with this as the tutorials here are really excellent.
The issue I have is that for that project I need to authenticate the users against an external DB using a SOAP webservice and if the user does not exist in the local DB I create it and log the user in. I am able to manage this part as I have already written a Joomla plugin that does that.
I have tried to figure out the documentation on how to create a custom driver. http://laravel.com/docs/5.1/authentication I thought that at first I would replicate the EloquentUserProvider befor modifying it, thus I created:
ErsAuthServiceProvider and ErsUserProvider respectively placed in App\Providers and App\Extensions
But it mysteriously does not work... I get the following error:
ErrorException in ErsUserProvider.php line 33: Argument 1 passed to App\Extensions\ErsUserProvider::__construct() must be an instance of Illuminate\Contracts\Hashing\Hasher, none given, called in /home/vagrant/Code/ERSTools/app/Providers/ErsAuthServiceProvider.php on line 31 and defined
Actually I do not understand much in the documentation what they are doing with the boot() method in the example. I understand that they extend The Auth class in order to add the new driver (ers in my case) but I do not get why they pass the $app['riak.connection']
<?php
namespace App\Providers;
use Auth;
use App\Extensions\ErsUserProvider;
use Illuminate\Contracts\Auth\Access\Gate as GateContract;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class ErsAuthServiceProvider extends ServiceProvider
{
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
];
/**
* Register any application authentication / authorization services.
*
* #param \Illuminate\Contracts\Auth\Access\Gate $gate
* #return void
*/
public function boot(GateContract $gate)
{
parent::registerPolicies($gate);
Auth::extend('ers', function($app) {
// Return an instance of Illuminate\Contracts\Auth\UserProvider...
return new ErsUserProvider;
});
//
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
//
}
}
and
<?php
namespace App\Extensions;
use Illuminate\Support\Str;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Hashing\Hasher as HasherContract;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;
class ErsUserProvider implements UserProvider
{
/**
* The hasher implementation.
*
* #var \Illuminate\Contracts\Hashing\Hasher
*/
protected $hasher;
/**
* The Eloquent user model.
*
* #var string
*/
protected $model;
/**
* Create a new database user provider.
*
* #param \Illuminate\Contracts\Hashing\Hasher $hasher
* #param string $model
* #return void
*/
public function __construct(HasherContract $hasher, $model)
{
$this->model = $model;
$this->hasher = $hasher;
}
... the rest is similar to the original file (EloquentUserProvider)
Finally, my plan is to keep the ErsUserprovider quite similar to the EloquentUserProvider and to implement my check with the webservice in the validateCredentials() method as in this method I shoul know if a user exists with the requested username in the local DB, I will know if the user passes validation with the SOAP webservice I can then
Login the user
Login the user and create a new user based on the date returned by the webservice
refuse the login.
Is this a good plan?
I sweated but I made the first part work. The issue was within the boot method.My custom provider is a working replica of the original laravel 5.1 I can now customize it.
Here is the Service provider that works:
<?php
namespace App\Providers;
use App\Extensions\ErsUserProvider;
use Illuminate\Support\ServiceProvider;
use Illuminate\Contracts\Auth\UserProvider;
class ErsAuthServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
$this->app['auth']->extend('ers',function($app)
{
$model = $app['config']['auth.model'];
return new ErsUserProvider($app['hash'], $model);
});
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
//
}
}