Laravel render\call controller action from view\layout - php

Maybe someone can tell me how to use something like embedded controllers in symfony2, to call\render controller action in Laravel4,5?

Found the best way for me, for L5:
CartServerProvider
use Illuminate\Support\ServiceProvider;
class CartServiceProvider extends ServiceProvider {
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
$this->app->make('view')->composer('layouts.master', 'Vendor\Cart\Http\ViewComposers\CartComposer');
}
}
The CartComposer class looks like this:
use Illuminate\Contracts\View\View;
class CartComposer {
/**
* Cart manager instance.
*
* #var \Vendor\Cart\StoreInterface
*/
protected $cart;
/**
* Create a new CartComposer instance.
*/
public function __construct()
{
$this->cart = app()->make('cart.store');
}
/**
* Compose the view.
*
* #return void
*/
public function compose(View $view)
{
$view->with('cart', $this->cart);
}
}
cart.store is a custom cart implementation I injected into the container, but the above should be enough to show you how to register a simple view composer.

Related

TYPO3 v9.5.11 Extbase: Inject ServiceObject generated by a ContainerClass into Repository

I am trying to inject an service object into my Repository. I have created different Service Classes under the directory Classes/Services. There is also one class that I created called ContainerService, which creates and instantiate one ServiceObject for each Service Class.
ContainerService Class:
namespace VendorName\MyExt\Service;
use VendorName\MyExt\Service\RestClientService;
class ContainerService {
private $restClient;
private $otherService;
/**
* #return RestClientService
*/
public function getRestClient() {
$objectManager = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
if ($this->restClient === null) {
$this->restClient = $objectManager->get(RestClientService::class);
}
return $this->restClient;
}
...
As I said, I create my ServiceObjects in the ContainerService Class.
Now I want to inject the ContainerService into my Repository and use it.
MyRepository Class:
namespace VendorName\MyExt\Domain\Repository;
use VendorName\MyExt\Service\ContainerService;
class MyRepository extends Repository
{
/**
* #var ContainerService
*/
public $containerService;
/**
* inject the ContainerService
*
* #param ContainerService $containerService
* #return void
*/
public function injectContainerService(ContainerService $containerService) {
$this->containerService = $containerService;
}
// Use Objects from The ContainerService
public function findAddress($addressId) {
$url = 'Person/getAddressbyId/'
$someData = $this->containerService->getRestClient()->sendRequest($url)
return $someData;
}
In MyController I recieve the $someData from my findAddress function and do some work with it.
But when I call my Page, I get following ErrorMessage:
(1/2) #1278450972 TYPO3\CMS\Extbase\Reflection\Exception\UnknownClassException
Class ContainerService does not exist. Reflection failed.
Already tried to reload all Caches and dumping the Autoload didn't help either.
Didn't install TYPO3 with composer.
I appreciate any advice or help! Thanks!
Actually found the Issue.
In MyRepository Class there was a Problem with the Annotations and the TypeHint:
namespace VendorName\MyExt\Domain\Repository;
use VendorName\MyExt\Service\ContainerService;
class MyRepository extends Repository
{
/**
*** #var \VendorName\MyExt\Service\ContainerService**
*/
public $containerService;
/**
* inject the ContainerService
*
* #param \VendorName\MyExt\Service\ContainerService $containerService
* #return void
*/
public function injectContainerService(\VendorName\MyExt\Service\ContainerService $containerService) {
$this->containerService = $containerService;
}
// Use Objects from The ContainerService
public function findAddress($addressId) {
$url = 'Person/getAddressbyId/'
$someData = $this->containerService->getRestClient()->sendRequest($url)
return $someData;
}
Now it works.

View Composer not working in my Laravel App

I am trying to share variables on multiple views so i tried the view composer but it is not working as its not passing variables and is there any way to debug it
ComposerServiceProvider.php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
view()->composer(
'layouts.admin.dashboard',
'App\Http\ViewComposers\StatComposer'
);
}
/**
* Register services.
*
* #return void
*/
public function register()
{
//
}
}
So now here will be the Composer File
StatComposer.php
<?php
namespace App\Http\ViewComposers;
use Analytics;
use Spatie\Analytics\Period;
use App\Libraries\GoogleAnalytics;
use Illuminate\Http\Request;
use Illuminate\View\View;
class StatComposer
{
/**
* Create a movie composer.
*
* #return void
*/
public function __construct()
{
$result = GoogleAnalytics::topCountries();
$country = $result->pluck('country');
$country_sessions = $result->pluck('sessions');
$topBrowsers = GoogleAnalytics::topBrowsers();
$browser = $topBrowsers->pluck('browser');
$browser_sessions = $topBrowsers->pluck('sessions');
$totalPageViews = GoogleAnalytics::fetchVisitorsAndPageViews();
$date = $totalPageViews->pluck('date');
$visitors = $totalPageViews->pluck('visitors');
$pageViews = $totalPageViews->pluck('pageViews');
}
/**
* Bind data to the view.
*
* #param View $view
* #return void
*/
public function compose(View $view)
{
$view->with('country', 'country_sessions', 'browser', 'browser_sessions','date','visitors','pageViews');
}
}
So I am unable to find way to debug it as the variables are not passing to the view i am trying to pass them to and the view is giving error of undefined variable.
The issue is your declaring a lot of variables without providing the values in the compose function. Also your not actually saving the data anywhere. It should be like this.
protected $country;
/**
* Create a movie composer.
*
* #return void
*/
public function __construct()
{
$result = GoogleAnalytics::topCountries();
$this->country = $result->pluck('country');
}
/**
* Bind data to the view.
*
* #param View $view
* #return void
*/
public function compose(View $view)
{
$view->with('country', $this->country);
}
Note we are declaring the classes property at the top, then saving to that property and then setting the 'country' variable in the with method with the $this->country property.

Binding the dependency of a Laravel Service Provider inside the provider itself?

I am just starting to get the hang of Service Providers and the IoC container, however one thing is confusing me. I have a SpamServiceProvider that requires two other classes to function. However one of those classes, InvalidKeywords, has a array $blacklist parameter which needs to be passed to its constructor.
If I register that class in the AppServiceProvider and pass in the $blacklist array, everything works fine. However, if I try to bind the class in the SpamServiceProvider instead it will not inject the $blacklist into InvalidKeywords constructor.
So I guess my question is why is this? And is there a way to keep bindings like this together in a single container or do I simply have to bind InvalidKeywords inside the AppServiceProvider?
This works
class SpamServiceProvider extends ServiceProvider
{
/**
* Indicates if loading of the provider is deferred.
*
* #var bool
*/
protected $defer = true;
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
//
}
/**
* Register services.
*
* #return void
*/
public function register()
{
$this->app->bind(SpamManager::class, function ($app) {
return new SpamManager(new InvalidKeywords, new RepeatedCharacters);
});
}
}
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->bind(InvalidKeywords::class, function ($app) {
return new InvalidKeywords(config('spam.blacklist'));
});
}
}
This does not work
class SpamServiceProvider extends ServiceProvider
{
/**
* Indicates if loading of the provider is deferred.
*
* #var bool
*/
protected $defer = true;
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
//
}
/**
* Register services.
*
* #return void
*/
public function register()
{
$this->app->bind(InvalidKeywords::class, function ($app) {
return new InvalidKeywords(config('spam.blacklist'));
});
$this->app->bind(SpamManager::class, function ($app) {
return new SpamManager(new InvalidKeywords, new RepeatedCharacters);
});
}
}
In the second case you're not resolving the InvalidKeywords class from the container, simply creating a new instance. Instead, try using app or resolve helpers when creating the SpamManager:
$this->app->bind(SpamManager::class, function ($app) {
return new SpamManager(resolve(InvalidKeywords::class), resolve(RepeatedCharacters::class));
});
// or
$this->app->bind(SpamManager::class, function ($app) {
return new SpamManager(app(InvalidKeywords::class), app(RepeatedCharacters::class));
});
I would create a singleton with InvalidKeywords as well:
$this->app->singleton(InvalidKeywords::class, function ($app) {
return new InvalidKeywords(config('spam.blacklist'));
});

How to use method injection with App::call in Laravel

I am using Laravel 5.2 and wrote my own Service Provider. I want to inject a Request object into the register method.
The base problem is that I want to call different service container depending on a special request param - all the service container implementing the same interface/contract of course.
The error message I am getting is:
ReflectionException in Container.php line 559:
Function registerService() does not exist
My service provider looks like that:
<?php
namespace App\Providers;
use Illuminate\Http\Request;
use Illuminate\Support\ServiceProvider;
use App\Contracts\Extractor;
class ExtractorServiceProvider extends ServiceProvider
{
/**
* Indicates if loading of the provider is deferred.
*
* #var bool
*/
protected $defer = true;
/**
* Available services for channels
*
* #var array
*/
protected $availableServices = ['AExtractor', 'ZExtractor'];
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
//
}
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->call('registerService');
}
/**
* #param Request $request
* #return void
*/
protected function registerService(Request $request)
{
$tag = DB::table('channels')->where('id', $request->channel)->value('tag')->first()->tag;
$selectedExtractor = $tag . 'Extractor';
$extractor = 'AExtractor';
if(in_array($selectedExtractor, $this->availableServices)) {
$extractor = $selectedExtractor;
}
$this->app->bind('App\Contracts\Extractor', "App\\Helpers\\{$extractor}");
}
/**
* Get the services provided by the provider.
*
* #return array
*/
public function provides()
{
return [Extractor::class];
}
}
How can I use $this->app->call('registerService'); to call my registerService function and inject the Request object?
The problem is you're calling App:call in a wrong way: you have to specify the object on which you want to call the method and the method, like this :
$this->app->call( [ $this, 'registerService' ] );

Laravel, where to place the logic for the app.blade.php file?

I'm using Laravel 5 for my new project and I want to follow best practices. I have my layout wrapper as resources/views/app.blade.php and it 'yields' every view. I need to show some dynamically generated data in app.blade.php, where should I place the logic to generate the data? For any other view I would do it in the corresponding controller, but for the whole app?
Thanks
<?php namespace App\Http\Composers;
use Illuminate\Contracts\View\View;
use Illuminate\Users\Repository as UserRepository;
class ProfileComposer {
/**
* The user repository implementation.
*
* #var UserRepository
*/
protected $users;
/**
* Create a new profile composer.
*
* #param UserRepository $users
* #return void
*/
public function __construct(UserRepository $users)
{
// Dependencies automatically resolved by service container...
$this->users = $users;
}
/**
* Bind data to the view.
*
* #param View $view
* #return void
*/
public function compose(View $view)
{
$view->with('count', $this->users->count());
}
}
And bind to view!
View::composer(['profile', 'dashboard'], 'App\Http\ViewComposers\MyViewComposer');

Categories