3

I am trying to do this in laravel 5.2 view.php (edit base_path to use a config variable in the string):

<?php

use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Request;

return [

/*
|--------------------------------------------------------------------------
| View Storage Paths
|--------------------------------------------------------------------------
|
| Most templating systems load templates from disk. Here you may specify
| an array of paths that should be checked for your views. Of course
| the usual Laravel view path has already been registered for you.
|
*/

'paths' => [
    realpath(base_path('resources/views/layouts/' . Config::get('api.' . Request::get('domain') . '.layout'))),
],

But now I receive this error:

Fatal error: Uncaught exception 'ReflectionException' with message 'Class log does not exist' in /Applications/AMPPS/www/loan/vendor/laravel/framework/src/Illuminate/Container/Container.php:734 Stack trace: #0 /Applications/AMPPS/www/loan/vendor/laravel/framework/src/Illuminate/Container/Container.php(734): ReflectionClass->__construct('log') #1 /Applications/AMPPS/www/loan/vendor/laravel/framework/src/Illuminate/Container/Container.php(629): Illuminate\Container\Container->build('log', Array) #2 /Applications/AMPPS/www/loan/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(697): Illuminate\Container\Container->make('log', Array) #3 /Applications/AMPPS/www/loan/vendor/laravel/framework/src/Illuminate/Container/Container.php(849): Illuminate\Foundation\Application->make('Psr\Log\LoggerI...') #4 /Applications/AMPPS/www/loan/vendor/laravel/framework/src/Illuminate/Container/Container.php(804): Illuminate\Container\Container->resolveClass(Object(ReflectionParameter)) #5 /Applications/AMPPS/www/loan/vendor/l in /Applications/AMPPS/www/loan/vendor/laravel/framework/src/Illuminate/Container/Container.php on line 734

How do I fix this? Because everything I try doesn't work. Thanks ahead of time!

Bryce
  • 988
  • 9
  • 16
  • Are you trying to serve different views for different Tenants in a SaaS model? I ask because I've been down this route many times, and I can tell you that this file is not where you want to be stuffing logic in. – Ohgodwhy Aug 03 '16 at 17:02

3 Answers3

2

Short answer: yes. Add this to the top of the file:

use Illuminate\Support\Facades\Config;
aynber
  • 22,380
  • 8
  • 50
  • 63
  • Thanks for the comment, I added this, but now I have a much larger error. Still stuck, unfortunately. Any ideas? – Bryce Aug 03 '16 at 17:04
  • That's more like another question, but you should be able to use `use Log;` at the top of the file. If that doesn't work, try `use \Illuminate\Support\Facades\Log;` – aynber Aug 03 '16 at 17:06
  • `use Log;` should work, per the documentation. Make sure you're using the right case. Can you provide the code where you're using the logger? – aynber Aug 03 '16 at 17:10
  • Please don't try to perform business logic in config files, that's what ServiceProviders are for. – Ohgodwhy Aug 03 '16 at 17:12
2

You need to move this logic out to your ViewServiceProvider instead of trying to do this directly in the config file, that's a big no no.

So what we're going to do is

php artisan make:provider MyViewServiceProvider

Which is going to result in a file existing at:

App\Providers\MyViewServiceProvider

Now we're going to open config/app.php. Find the existing ViewServiceProvider::class in this file and replace it with the namespaced path above. It should look something like this:

//the old Illuminate\View\ViewServiceProvider::class
App\Providers\MyViewServiceProvider::class,

Now inside of the registerViewFinder() function, we can overload our view paths.

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Config;

public function registerViewFinder()
{
    $this->app->bind('view.finder', function ($app) {
        $custom_path = base_path('resources/views/layouts/' . Config::get('api.' . $this->app->request()->get('domain') . '.layout')
        $paths = array_merge(
            [$custom_path],
            $app['config']['view.paths']
        );

        return new FileViewFinder($app['files'], $paths);
    });
}

Going this route will ensure that your path is observed first. If the view is not found in that path, then you can fallback to Laravel's default view path.

Edit

It's important to note that your class needs to extend the default ViewServiceProvider, and that there are 2 other functions you must declare, the whole file should look like below:

<?php

namespace App\Providers;

use Illuminate\View\ViewServiceProvider;
use Illuminate\Support\Facades\Config;

class MyViewServiceProvider extends ViewServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        parent::register();
    }

    /**
     * Register the view finder implementation.
     *
     * @return void
     */
    public function registerViewFinder()
    {
        $this->app->bind('view.finder', function ($app) {
            $custom_path = base_path('resources/views/layouts/' . Config::get('api.' . $this->app->request->get('domain') . '.layout')
            $paths = array_merge(
                [$custom_path],
                $app['config']['view.paths']
            );

            return new FileViewFinder($app['files'], $paths);
        });
    }
}
Ohgodwhy
  • 49,779
  • 11
  • 80
  • 110
  • Thank you so much! I will try this now. – Bryce Aug 03 '16 at 17:21
  • @Bryce I've made some updates to make the implementation a bit more clear for you. – Ohgodwhy Aug 03 '16 at 17:30
  • Thank you for being so helpful... I have an error now stating this: "Call to undefined method Illuminate\Foundation\Application::request()" – Bryce Aug 03 '16 at 17:33
  • @Bryce I'm sorry, I made a typo when writing it. You shouldn't call the `->request()` as a function as an accessor. Try removing the `()` so it's just `$this->app->request->get('domain')` – Ohgodwhy Aug 03 '16 at 17:39
  • 1
    Well, that solved that issue. We must be getting close! Thank you once again, really, I don't know how I ever would have figured this out otherwise... last error (hopefully): "Class 'App\Providers\FileViewFinder' not found" ... im looking into it, but perhaps you might know off hand. – Bryce Aug 03 '16 at 17:44
  • Thank you so much! I got it figured out! This is exactly what I needed! – Bryce Aug 03 '16 at 17:53
  • @Bryce Glad you got that sorted out. Take care. – Ohgodwhy Aug 03 '16 at 17:56
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/119039/discussion-between-bryce-and-ohgodwhy). – Bryce Aug 03 '16 at 18:08
1

You can use the config- and request-helpers in your app's config files.

'paths' => [
    realpath(base_path(
        'resources/views/layouts/' . config('api.' . request('domain') . '.layout')
    )),
],
Jari Pekkala
  • 847
  • 7
  • 8