Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

cpowell89's avatar

No hint path defined for [notifications].

Hi Guys!

I'm quite new to Laravel so be gentle. I've been following a tutorial for building a simple CMS in Laravel: https://code.tutsplus.com/courses/build-a-cms-with-laravel/lessons/securing-the-back-end-part-2

I've come unstuck and the password reset stage of the process (I'm not sure you guys will be able to see the video there, but I'll explain anyway). The problem being this tutorial was written for Laravel 5.0 and I'm using 5.3.

Anyway! I've gotten as far as trying to get Laravel to send out the email which contains the link to reset your password and I'm running into an error. As far as I can tell my routes are ok:

//Resetting a users password
Route::get('password/email', [ 'as' => 'auth.passwords.email', 'uses' => 'Auth\ForgotPasswordController@showLinkRequestForm']);
Route::post('password/email', [ 'as' => 'auth.passwords.email', 'uses' => 'Auth\ForgotPasswordController@sendResetLinkEmail']);

Route::get('password/reset', [ 'as' => 'auth.passwords.reset', 'uses' => 'Auth\ResetPasswordController@showResetForm']);
Route::post('password/reset', [ 'as' => 'auth.passwords.reset', 'uses' => 'Auth\ResetPasswordController@reset']);

I'm using the standard password reset form that comes with the make:auth package and posting to: /password/email with the users email address.

Instantly after that I get the following error:

InvalidArgumentException in FileViewFinder.php line 112: No hint path defined for [notifications]. in FileViewFinder.php line 112 at FileViewFinder->getNamespaceSegments('notifications::email') in FileViewFinder.php line 90 at FileViewFinder->findNamedPathView('notifications::email') in FileViewFinder.php line 76 at FileViewFinder->find('notifications::email') in Factory.php line 174 at Factory->make('notifications::email', array('level' => 'info', 'subject' => null, 'greeting' => null, 'introLines' => array('You are receiving this email because we received a password reset request for your account.'), 'outroLines' => array('If you did not request a password reset, no further action is required.'), 'actionText' => 'Reset Password', 'actionUrl' => 'http://laravel.dev/password/reset/59a5ea6cb598b7ae5d7c8f4ae80dffc3e70c1be802d0ae0053d96ce4c46b92da', 'message' => object(Message))) in Mailer.php line 430 at Mailer->getView('notifications::email', array('level' => 'info', 'subject' => null, 'greeting' => null, 'introLines' => array('You are receiving this email because we received a password reset request for your account.'), 'outroLines' => array('If you did not request a password reset, no further action is required.'), 'actionText' => 'Reset Password', 'actionUrl' => 'http://laravel.dev/password/reset/59a5ea6cb598b7ae5d7c8f4ae80dffc3e70c1be802d0ae0053d96ce4c46b92da', 'message' => object(Message))) in Mailer.php line 310 at Mailer->addContent(object(Message), 'notifications::email', 'notifications::email-plain', null, array('level' => 'info', 'subject' => null, 'greeting' => null, 'introLines' => array('You are receiving this email because we received a password reset request for your account.'), 'outroLines' => array('If you did not request a password reset, no further action is required.'), 'actionText' => 'Reset Password', 'actionUrl' => 'http://laravel.dev/password/reset/59a5ea6cb598b7ae5d7c8f4ae80dffc3e70c1be802d0ae0053d96ce4c46b92da', 'message' => object(Message))) in Mailer.php line 186 at Mailer->send('notifications::email', array('level' => 'info', 'subject' => null, 'greeting' => null, 'introLines' => array('You are receiving this email because we received a password reset request for your account.'), 'outroLines' => array('If you did not request a password reset, no further action is required.'), 'actionText' => 'Reset Password', 'actionUrl' => 'http://laravel.dev/password/reset/59a5ea6cb598b7ae5d7c8f4ae80dffc3e70c1be802d0ae0053d96ce4c46b92da', 'message' => object(Message)), object(Closure)) in MailChannel.php line 85 at MailChannel->send(object(User), object(ResetPassword)) in ChannelManager.php line 79 at ChannelManager->sendNow(object(Collection), object(ResetPassword)) in ChannelManager.php line 43 at ChannelManager->send(object(Collection), object(ResetPassword)) in RoutesNotifications.php line 18 at User->notify(object(ResetPassword)) in User.php line 34 at User->sendPasswordResetNotification('59a5ea6cb598b7ae5d7c8f4ae80dffc3e70c1be802d0ae0053d96ce4c46b92da') in PasswordBroker.php line 70 at PasswordBroker->sendResetLink(array('email' => '[email protected]')) in SendsPasswordResetEmails.php line 35 at ForgotPasswordController->sendResetLinkEmail(object(Request)) at call_user_func_array(array(object(ForgotPasswordController), 'sendResetLinkEmail'), array(object(Request))) in Controller.php line 55 at Controller->callAction('sendResetLinkEmail', array(object(Request))) in ControllerDispatcher.php line 44 at ControllerDispatcher->dispatch(object(Route), object(ForgotPasswordController), 'sendResetLinkEmail') in Route.php line 189 at Route->runController() in Route.php line 144 at Route->run(object(Request)) in Router.php line 642 at Router->Illuminate\Routing{closure}(object(Request)) in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request)) in RedirectIfAuthenticated.php line 24 at RedirectIfAuthenticated->handle(object(Request), object(Closure)) in Pipeline.php line 137 at Pipeline->Illuminate\Pipeline{closure}(object(Request)) in Pipeline.php line 33 at Pipeline->Illuminate\Routing{closure}(object(Request)) in SubstituteBindings.php line 41 at SubstituteBindings->handle(object(Request), object(Closure)) in Pipeline.php line 137 at Pipeline->Illuminate\Pipeline{closure}(object(Request)) in Pipeline.php line 33 at Pipeline->Illuminate\Routing{closure}(object(Request)) in VerifyCsrfToken.php line 65 at VerifyCsrfToken->handle(object(Request), object(Closure)) in Pipeline.php line 137 at Pipeline->Illuminate\Pipeline{closure}(object(Request)) in Pipeline.php line 33 at Pipeline->Illuminate\Routing{closure}(object(Request)) in ShareErrorsFromSession.php line 49 at ShareErrorsFromSession->handle(object(Request), object(Closure)) in Pipeline.php line 137 at Pipeline->Illuminate\Pipeline{closure}(object(Request)) in Pipeline.php line 33 at Pipeline->Illuminate\Routing{closure}(object(Request)) in StartSession.php line 64 at StartSession->handle(object(Request), object(Closure)) in Pipeline.php line 137 at Pipeline->Illuminate\Pipeline{closure}(object(Request)) in Pipeline.php line 33 at Pipeline->Illuminate\Routing{closure}(object(Request)) in AddQueuedCookiesToResponse.php line 37 at AddQueuedCookiesToResponse->handle(object(Request), object(Closure)) in Pipeline.php line 137 at Pipeline->Illuminate\Pipeline{closure}(object(Request)) in Pipeline.php line 33 at Pipeline->Illuminate\Routing{closure}(object(Request)) in EncryptCookies.php line 59 at EncryptCookies->handle(object(Request), object(Closure)) in Pipeline.php line 137 at Pipeline->Illuminate\Pipeline{closure}(object(Request)) in Pipeline.php line 33 at Pipeline->Illuminate\Routing{closure}(object(Request)) in Pipeline.php line 104 at Pipeline->then(object(Closure)) in Router.php line 644 at Router->runRouteWithinStack(object(Route), object(Request)) in Router.php line 618 at Router->dispatchToRoute(object(Request)) in Router.php line 596 at Router->dispatch(object(Request)) in Kernel.php line 268 at Kernel->Illuminate\Foundation\Http{closure}(object(Request)) in Pipeline.php line 53 at Pipeline->Illuminate\Routing{closure}(object(Request)) in CheckForMaintenanceMode.php line 46 at CheckForMaintenanceMode->handle(object(Request), object(Closure)) in Pipeline.php line 137 at Pipeline->Illuminate\Pipeline{closure}(object(Request)) in Pipeline.php line 33 at Pipeline->Illuminate\Routing{closure}(object(Request)) in Pipeline.php line 104 at Pipeline->then(object(Closure)) in Kernel.php line 150 at Kernel->sendRequestThroughRouter(object(Request)) in Kernel.php line 117 at Kernel->handle(object(Request)) in index.php line 53

I've tried loads of things, one of my idea was that the view templates were just missing so I found and ran php artisan vendor:publish --tag=laravel-notifications

This seems to create the templates in the correct place : \resources\views\vendor\notifications

I then ran: php artisan config:cache which cleared and rebuilt the cache successfully. Still the same error.

I feel as though it's some fundamental knowledge I'm missing that somebody will probably know the answer to quite quickly? What am I doing wrong?

I'm using the unedited ForgotPasswordController.php and ResetPasswordController.php that come with Laravel.

This has been driving me nuts for hours! Any suggestions would be awesome :)

Thank you in advance.

0 likes
4 replies
bencarter78@hotmail.com's avatar

If you add Route::auth() to your routes/web.php file then this should sort your routes out instead of manually declaring them.

2 likes
cpowell89's avatar

Ah that's a cool little function, right I'm using that now, but unfortunately I still have the same error as above when submitting the /password/reset form :(. Is there anything else you think it might be?

cpowell89's avatar

Right I've established what's causing the issue, I just need a little guidance...

Basically this tutorial explains how to create a basic theming system for Laravel and it requires you to add the following class to app/View/ThemeViewFinder.php

<?php 
namespace App\View;

use Illuminate\View\FileViewFinder;


class ThemeViewFinder extends FileViewFinder 
{

    protected $activeTheme;

    protected $basePath;

    public function setBasePath($path) {

        $this->basePath = $path;

    }

    public function setActiveTheme($theme) {

        $this->activeTheme = $theme;

        array_unshift($this->paths, $this->basePath.'/'.$theme.'/views');

    }
}

And then register it in the app/Providers/AppServiceProvider.php like so:


<?php

namespace App\Providers;

use App\View\ThemeViewFinder;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        $this->app['view']->setFinder($this->app['theme.finder']);
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton('theme.finder',function($app) {
            $finder = new ThemeViewFinder($app['files'],$app['config']['view.paths']);
            $config = $app['config']['cms.theme'];

            $finder->setBasePath($app['path.public'].'/'.$config['folder']);
            $finder->setActiveTheme($config['active']);

            return $finder;
        });
    }
}

As the error ends with a problem with FileViewFinder not being able to location the view templates for the email notifications I'm assuming this is the root of the issue. Is anyone able to help point out how these additions may be causing this problem?

  • EDIT -

One more thing! The tutorial also tells you to create "themes" folder in the /public directory and populate it with /assets /views/layouts etc etc. Is this kind of approach still valid for Laravel 5.3? As I said the tutorial was written for 5.0.

Thanks again in advance! Apologies if I seem to be asking silly questions!

cpowell89's avatar

I think I may have solved it!

It seemed to be that my hint paths were going missing when extending the FileViewFinder

So essentially what I'm doing now is getting the original instance of "FileViewFinder" grabbing the hints from it, and setting them on the new "ThemeViewFinder".

So in AppService Provider:


<?php

namespace App\Providers;

use App\View\ThemeViewFinder;
use Illuminate\Support\ServiceProvider;



class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {   

        $this->app['view']->setFinder($this->app['theme.finder']);


    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton('theme.finder',function($app) {


            $finder = new ThemeViewFinder($app['files'],$app['config']['view.paths']);
            $config = $app['config']['cms.theme'];

            $original_finder = $this->app['view']->getFinder();

            //We need to get our hints from the base level
            $finder->setHints($original_finder->getHints());

            $finder->setBasePath($app['path.base'].'/resources/'.$config['folder']);
            $finder->setActiveTheme($config['active']);


            return $finder;
        });
    }
}

And the ThemeViewFinder class :

<?php 
namespace App\View;

use Illuminate\View\FileViewFinder;
use Illuminate\Filesystem\Filesystem;

class ThemeViewFinder extends FileViewFinder 
{


    protected $activeTheme;

    protected $basePath;



    public function setBasePath($path) {

        $this->basePath = $path;

    }


    public function setActiveTheme($theme) {

        $this->activeTheme = $theme;

        array_unshift($this->paths, $this->basePath.'/'.$theme.'/views');
    

    }


    public function setHints($hints) {
        $this->hints = $hints;
    }
}

Does that seem like a sensible way of doing it or can anyone thing of a nicer way I should be doing it?

Thanks again Chris

2 likes

Please or to participate in this conversation.