I made a package which is counting the visitors on a webpage. Currently I have a single route, controller and view which don't do very much other than display a simple string. I have a separate Laravel application where this package is specifically build for. In this separate application I have a layout file called backend.
layouts/layouts/backend.blade.php
.
My package view is extending this template like so: (backend.blade.php does not exists in the package but in the separate laravel application of-course)
@extends('layouts.layouts.backend')
@section('content')
<div class="container-fluid pt-5 ">
<div class="row">
<div class="col-md-6">
<h3>{{ __('Visitors') }}</h3>
</div>
</div>
</div>
@endsection
The package successfully extends this layout but it can't find functions such as Auth::user()->token
and it will say
Trying to get property 'token' of non-object (View: /Users/rainierlaan/Sites/rainierlaan/resources/views/layouts/layouts/backend.blade.php)
Why does this happen?
This is my packages service provider
public function register()
{
// Controllers
$this->app->make('Rainieren\Visitors\Http\Controllers\VisitorController');
// Views
$this->loadViewsFrom(__DIR__.'/resources/views', 'visitors');
$this->publishes([
__DIR__.'/resources/views' => resource_path('views/visitors'),
]);
// Migrations
$this->loadMigrationsFrom(__DIR__.'/database/migrations');
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
include __DIR__ . '/routes/routes.php';
}
When I do vendor:publish
the view successfully publishes to the right folder but somehow can't recognise functions such as Auth::user()->token
or Auth::user()->unreadNotifications->count())
This is my package route:
<?php
Route::get('dashboard/visitors', '\Rainieren\Visitors\Http\Controllers\VisitorController@index')->name('visitors');
And this is the controller
public function index()
{
return view('visitors::index');
}
Laravel includes built-in authentication and session services which are typically accessed via the Auth and Session facades. These features provide cookie-based authentication for requests that are initiated from web browsers. They provide methods that allow you to verify a user's credentials and authenticate the user.
By default, the auth.basic middleware will assume the email column on your users database table is the user's "username". If you are using PHP FastCGI and Apache to serve your Laravel application, HTTP Basic authentication may not work correctly.
These packages are Laravel Breeze, Laravel Jetstream, and Laravel Fortify. Laravel Breeze is a simple, minimal implementation of all of Laravel's authentication features, including login, registration, password reset, email verification, and password confirmation.
In general, Sanctum should be preferred when possible since it is a simple, complete solution for API authentication, SPA authentication, and mobile authentication, including support for "scopes" or "abilities". If you are building a single-page application (SPA) that will be powered by a Laravel backend, you should use Laravel Sanctum.
I would need a little bit more debugging information but my first assumption is the missing AuthenticateSession
or Authenticate
middleware.
Laravel defines a default middleware group web
for your routes inside routes/web.php
and this group uses the AuthenticateSession
middleware. This is how a new installation looks like:
Route::group([
'middleware' => 'web', <<< this is the magic part
'namespace' => $this->namespace,
], function ($router) {
require base_path('routes/web.php');
});
Here we see that the middleware group web
is used.
In your custom module / service provider this is not the case. Your Route::get()
definition is added to the Router
but not inside this group. Therefore all necessary internals to authenticate the user are not performed.
In this scenario I would try to use ->middleware('auth')
or ->middleware('web')
which will use the main-projects group middleware.
Route::get('dashboard/visitors', '\Rainieren\Visitors\Http\Controllers\VisitorController@index')
->name('visitors')
->middleware('web');
Here is a different idea:
If you say you're always authenticated. Then you could try to move all web
middlewares into the global middlewares within your Kernel
(protected $middleware = []
).
I did not tested this but I can imagine that this could work as well.
I have seen in all of my active packages that they don't use Auth class at all in the views.
Their workaround is using this in the controller and pass it to the view:
$user = auth()->user();
return view('folder.view' ,['user'=>$user]);
And then in the view:
{{$user->token}} <!-- OR --!> {{$user->unreadNotifications->count()}}
Obviously as @N69S has stated only if a user is authenticated this is going to work.
Hope this works!!
EDIT:(Sorry didn't understand well the first time)
The error is in your service provider class yo have to do all the logic on the boot function, not in the register, because if you do in the register function, you load all before the laravel framework (To say something) https://laravel.com/docs/5.7/providers#the-register-method
Your serviceprovider should end like this:
public function register()
{
//Nothing
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
// Controllers
$this->app->make('Rainieren\Visitors\Http\Controllers\VisitorController');
// Views
$this->loadViewsFrom(__DIR__.'/resources/views', 'visitors');
$this->publishes([
__DIR__.'/resources/views' => resource_path('views/visitors'),
]);
// Migrations
$this->loadMigrationsFrom(__DIR__.'/database/migrations');
include __DIR__ . '/routes/routes.php';
}
Hope this finally works!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With