I have a simple setup where I need to show a bit of data universally across my app, in the header of my site. To do so, I have created a ComposerServiceProvider class and a HeaderComposer class to delegate this responsibility, as seen below:
ComposerServiceProvider
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider {
public function register() {
$this->app->view->composer('templates.header', 'HeaderComposer');
}
}
HeaderComposer
class HeaderComposer {
public function compose($view) {
Event::listen('illuminate.query', function($q) {
print_r($q);
});
$view->with('nearbyMissions', array(
'past' => Mission::remember(60, 'previousMissions')->previousMissions(3)->get(),
'future' => Mission::remember(60, 'nextMissions')->nextMissions(3)->get()
));
}
}
Previously, these classes were not namespaced, but I have now decided to namespace each of them as a good practice, by prepending the files with:
namespace MyProject\Composers;
However, this has broken my application as some part of my project can no longer resolve my composer classes. None of my pages work because they all use a templated header view which uses my HeaderComposer:
Class HeaderComposer does not exist (View: H:\myproject\app\views\templates\main.blade.php)
Where am I meant to declare the use statements for my class? In my view? (Which doesn't seem right). Somewhere else?
Since you just namespaced your class, then you have to update your composer binding:
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider {
public function register() {
$this->app->view->composer('templates.header', 'MyProject\Composers\HeaderComposer');
}
}
Related
I created class named Task in the App\Entity namespace and my problem is in my another class I want to use it but it doesn't detect my class and give me error:
Attempted to load class "Task" from namespace "App\Entity".
Did you forget a "use" statement for another namespace?
this my Task.php:
namespace App\Entity;
class Task
{
protected $task;
public function getTask()
{
return $this->task;
}
public function setTask($task)
{
$this->task = $task;
}
}
This is my DefaultController that uses the Task class:
use App\Entity\Task;
class DefaultController
{
}
Depending upon your autoloader settings, if you are using composer, you can have it such that autoloading only happens from the pre-built class map - called 'authoritative classmap' (https://getcomposer.org/doc/articles/autoloader-optimization.md).
So, when you add a class to your source, it isn't recognised by the pre-built autoloader. Try running composer dump to let the autoloader load via standard PSR-0/PSR-4 rules.
If you are using the autoloader on PSR-0/PSR-4 mode, then maybe you've not put the file in the right directory.
Thanks to all in advance.
I am trying to create Facades for my custom and common functions in laravel 5.0 also I don`t want to create controller for that so I am using Facades.
I have tried almost every tutorial but it do not help me.
Please help me to create facade without using Composer in Laravel 5.0.
Thanks again.
First of all you're creating a class of facade like this:
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class SomeFacade extends Facade
{
protected static function getFacadeAccessor()
{
return 'someService';
}
}
then You create a service class that hold your functionalities:
namespace App\Services;
class SomeService { ... }
Finally you have to register it and set an alias (not required) for it:
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProivider extends ServiceProvider
{
(...)
public function register()
{
$this->app->singleton('someService', function () {
return new \App\Services\SomeService();
});
$this->app->alias('SomeServiceFacade', \App\Facades\SomeFacade::class);
}
}
Now you can call your methods from SomeService with:
SomeServiceFacade::someMethhod();
or
app('someService')->someMethhod();
I have a service provider that I want to use to bind an instance of a class to the service container:
namespace App\Providers;
use Eluceo\iCal\Component\Calendar;
use Illuminate\Support\ServiceProvider;
class IcalProvider extends ServiceProvider
{
public function register()
{
$this->app->instance('iCal', function () {
return new Calendar(config('calendar.name'));
});
}
}
As I understand the documentation on binding an instance, this allows me to bind the key iCal to the service container so that later in my controller or service class I can type hint iCal and the instance created in the service provider will be used.
So I created a controller and tried to type hint my instance:
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
class CalendarInviteController extends Controller
{
public function download(iCal $ical, $sessionId)
{
dd($ical);
}
}
But when I do I get the error:
Class App\Http\Controllers\iCal does not exist
Makes sense, as it applies it's looking for a class named iCal in the controller namespace which doesn't exist. There's not a use statement for the instance since iCal is just a text key, so I tried telling it to look at the root namespace thinking that may fix it:
public function download(\iCal $ical, $sessionId)
and I get the error:
Class iCal does not exist
When I read the section of the documentation on resolving from the service container it looks like the only thing I need to do in the controller is type hint to get the instance.
Am I misunderstanding the docs?
Update
I should also mention that I did add my service provider to my config/app.php file.
Also, when I create an interface, bind it to the service container instead, edit the vendor code to implement said interface, and inject that interface instead it works, but that requires that I edit the vendor code which I don't want.
As you see in the docs the method instance takes a key and an object instance to register in the container. So, if you want to register a specific instance in the container, the registration should be:
namespace App\Providers;
use Eluceo\iCal\Component\Calendar;
use Illuminate\Support\ServiceProvider;
class IcalProvider extends ServiceProvider
{
public function register()
{
//register a specific instance of the Calendar class in the container
$this->app->instance('iCal', new Calendar(config('calendar.name') );
}
}
This way you could get back the instance with:
$cal = \App::make('iCal');
If your purpose is to type-hint the class in the controller method, and you want to resolve the previous registered instance from the service container, you could do like this:
namespace App\Providers;
use Eluceo\iCal\Component\Calendar;
use Illuminate\Support\ServiceProvider;
class IcalProvider extends ServiceProvider
{
public function register()
{
//the key will be 'Eluceo\iCal\Component\Calendar'
$this->app->instance( Calendar::class, new Calendar(config('calendar.name') );
}
}
Now, in your controller:
namespace App\Http\Controllers;
//important: specify the Calendar namespace
use Eluceo\iCal\Component\Calendar;
class CalendarInviteController extends Controller
{
public function download(Calendar $ical, $sessionId)
{
dd($ical);
}
}
This way Laravel will see that you want a Calendar object and it will try to get it from the service container looking if exists a binding for this key: (because this is the namespace of the class you have specified in the controller)
Eluceo\iCal\Component\Calendar
and the binding exists! As you have bound this key to your service container in your service provider, so Laravel will return your registered instance.
In the code you provided, you tipe-hinted the class iCal, but the class didn't exist anywhere so Laravel wasn't able to instantiate the class
If you’re wanting to inject dependencies into your controller (which is good, so kudos!) then you need an interface name to type-hint on.
Usually you would have a generic interface, and then bind that interface to a concrete implementation. So you may have a calendar service interface, that’s bound to your iCal implementation. Something like this:
use Eluceo\iCal\Component\Calendar;
class CalendarServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('App\Services\Calendar', function ($app) {
return new Calendar(config('calendar.name'));
});
}
public function provides()
{
return ['App\Services\Calendar'];
}
}
So long as you register your service provider in your config/app.php file, you can now type-hint your calendar dependency in classes:
use App\Services\Calendar;
class InvitationController extends Controller
{
protected $calendar;
public function __construct(Calendar $calendar)
{
$this->calendar = $calendar;
}
}
I am attempting to create a facade within laravel 4.1. I have created the facade, service provider and the class, to no avail. I followed numerous "how to's" including the advanced video for custom facades on Laracasts. No matter how many times I try, I end up with the exception of Non-static method Custom\Helpers\Helper::doSomething() should not be called statically
Here is my code...
HelpersServiceProvider.php
<?php namespace Custom\Helpers;
use Illuminate\Support\ServiceProvider;
class HelpersServiceProvider extends ServiceProvider {
public function register()
{
$this->app->bind('trial','Custom\Helpers\Helper');
}
}
HelpersFacade.php
<?php namespace Custom\Facades;
use Illuminate\Support\Facades\Facade;
class Helper extends Facade {
protected static function getFacadeAccessor()
{
return 'trial';
}
}
Helpers.php
<?php namespace Custom\Helpers;
class Helper {
public function doSomething()
{
return 'Hello';
}
}
I add the service provider to my app.php file and register the facade alias
'Custom\Helpers\HelpersServiceProvider',
'Helper' => 'Custom\Facades\Helper',
Then when I try to access it via a Static call (yes, I know it's not really static) or via the service provider directly I get the exception error.
Scratching my head on this one...
It looks like you have an incorrectly named class (or file):
HelpersFacade.php
class Helper extends Facade {
Additionally, your Helper class is in Helpers.php. Those need to match, also.
I'm trying to deepen my knowlade in laravel architecture.
I have a search engine (elastic search for the sake of the example), but this search engine might change in the future. So im trying to write a container for this, so in case i'll change the engine in the future, i will have to change only the container. (I believe the termenology is factory design?)
I have created a provider app/providers/DataFromSearchEngine.php that looks like this:
use Illuminate\Support\ServiceProvider;
class DataFromSearchEngine extends ServiceProvider {
public function boot()
{
//
}
public function register()
{
$this->app->singleton('SearchEngine', function($app) {
return new elasticSearch;
});
}
}
Then i registered it in the providers array in config/app.php .
'providers' => [
// providers...
'App\Providers\DataFromSearchEngine'
],
The next step is to call SearchEngine from my controller:
namespace App\Http\Controllers;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class SearchController extends Controller {
protected $searchEngine;
public function __construct() {
$this->searchEngine = $this->app->make('SearchEngine');
}
}
But all these yields: Undefined property: App\Http\Controllers\SearchController::$app
Can someone explain what i'm missing?
Instead of using $this->app try using app().
This is because non of the inherited controller classes, i.e. App\Http\Controllers\Controller or Illuminate\Routing\Controllers\Controller have an app property on them.
As a note you can use app('SearchEngine') which is the equivalent of app()->make('SearchEngine') as a shortcut to making your object.
I had this issue when trying to create a service provider. I registered my service provider in AppServiceProvider.php but was still getting this same error. The issue was that in my ServiceProvider I needed to add extends ServiceProvider to my class. Seems simple but is often forgotten.