I have made the below composer view
for my app. I've placed it in separate file at app/composers.php.
<?php
// namespace App\Modules\Manager\Composer;
// use Illuminate\Support\Facades\View as View ;
/*
|--------------------------------------------------------------------------
| Composers
|--------------------------------------------------------------------------
|
|
*/
View::composer('tshop.includes.header', function($view)
{
$categories = Categories::getWithChilds();
$view->withCategories( $categories);
});
My composer.php file is
"autoload": {
"classmap": [
"app/commands",
"app/controllers",
"app/models",
"app/database/migrations",
"app/database/seeds",
"app/tests/TestCase.php"
],
"files": [
"app/composers.php"
]
},
Unfortunately I get this error
Fatal error: Class 'View' not found in C:\xampp\htdocs\eshop\app\composers.php on line 15
I also tried this. I wrote inside app/start/global.php
require app_path().'/composers.php';
and
use Illuminate\Support\Facades\View as View ;
at app/composers.php, getting this error
Fatal error: Call to a member function composer() on a non-object in C:\xampp\htdocs\eshop\vendor\laravel\framework\src\Illuminate\Support\Facades\Facade.php on line 211
I don't think your app/composers.php
should be autoloaded within composer. Composer's responsibility is to resolve packages and install them for you, which has nothing to do with your application logic, let alone your application's views.
At the point of running composer, it would not have any knowledge of your Laravel app. That means your Laravel facades like View
, Input
, DB
, Auth
, etc. are not loaded yet. Thus your code throws Call to a member function composer() on a non-object
.
Approach 1:
Laravel does not strictly specify where you put your laravel view composers, so requiring it by adding:
require app_path() . '/composers.php';
at the bottom of app/start/global.php
like edi9999 said would be fine.
Don't forget to remove in this case:
"files": [
"app/composers.php"
]
Approach 2: there is a way to autoload your view composers in composer.json!
From example in Laravel docs on view composers, you can do something like...
app/viewcomposers/HeaderViewComposer.php:
class HeaderViewComposer
{
public function compose($view)
{
$categories = Categories::getWithChilds();
$view->withCategories( $categories);
}
}
composer.json:
"classmap": [
...
"app/viewcomposers"
]
app/composers.php:
View::composer('tshop.includes.header', 'HeaderViewComposer');
bottom of app/start/global.php:
require app_path() . '/composers.php';
Unfortunately you still need to add the line above to app/start/global.php
so Laravel knows what view composers are defined.
Approach 3: Do autoload class in composer.json + register a custom ServiceProvider
Learning from Using View Composers in Laravel 4 by Philip Brown, we could also add our own custom service provider and not having to edit our app/start/global.php
file.
app/viewcomposers/HeaderViewComposer.php:
<?php namespace App\Modules\Manager\Composer;
class HeaderViewComposer
{
public function compose($view)
{
$categories = Categories::getWithChilds();
$view->withCategories( $categories);
}
}
composer.json:
"classmap": [
...
"app/viewcomposers"
]
app/viewcomposers/ViewComposerServiceProvider.php:
<?php namespace App\Modules\Manager\Composer;
use Illuminate\Support\ServiceProvider;
class ViewComposerServiceProvider extends ServiceProvider {
public function register()
{
$this->app->view->composer('tshop.includes.header', 'App\Modules\Manager\Composer\HeaderViewComposer');
}
}
app/config/app.php:
'providers' => array(
...
'App\Modules\Manager\Composer\ViewComposerServiceProvider',
),
As @TheShiftExchange found out, one problem is that you used the "files" options.
As you can see in composer's code, the autoload section corresponds to this:
class ComposerAutoloaderInitf8489489s7f894ds98f47d
{
....
....
public static function getLoader()
{
....
....
$includeFiles = require __DIR__ . '/autoload_files.php';
foreach ($includeFiles as $file) {
composerRequiref4s65f4556sd4f564fsdfd($file);
}
return $loader;
}
}
function composerRequire5894s89f4sd98498489f7b37d($file)
{
require $file;
}
So the files array you specify is required during composer's autoload process, way before the View Facade is loaded.
The providers to the facades are loaded in vendor/laravel/framework/illuminate/foundation/start.php
/*
|--------------------------------------------------------------------------
| Register The Core Service Providers
|--------------------------------------------------------------------------
|
| The Illuminate core service providers register all of the core pieces
| of the Illuminate framework including session, caching, encryption
| and more. It's simply a convenient wrapper for the registration.
|
*/
$providers = $config['providers'];
$app->getProviderRepository()->load($app, $providers);
Actually, the problem with classmaps is an other one: It is that they is no class in your file, so the file will never be loaded so it doesn't do anything.
To make it work, you should add into app/start/global.php
at the end of the file:
Instead of
require app_path() . '/filters.php';
Write
require app_path() . '/composers.php';
require app_path() . '/filters.php';
That's the best way I can think of to include files at each load of your application that are not classes.
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