View Composer not working in my Laravel App - php

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.

Related

Laravel: Target [...] is not instantiable when building [...]

I see there are a lot of questions on Stackoverflow like this, but they all seem to have different unrelated answers, so hear me out:
I'm updating an old Laravel app's file structure to that of the newest version (8.x)
and I am getting this error when I visit the the / route:
Error + Stack trace
Illuminate\Contracts\Container\BindingResolutionException
Target [Illuminate\View\ViewFinderInterface] is not instantiable while building [App\Http\Controllers\HomeController, App\Lib\Services\Rendering\HomepageRenderer, Illuminate\View\Environment].
I'm not sure what this even means.
Here is the code for the HomeController:
<?php
namespace App\Http\Controllers;
use App\Lib\Services\Mail\Mailer;
use App\Lib\Services\Validation\ContactValidator;
use App\Lib\Services\Rendering\HomepageRenderer;
use App;
use Illuminate\View\View;
use Input;
use Redirect;
use App\Http\Controllers\Controller;
class HomeController extends Controller
{
/**
* Validator instance.
*
* #var Lib\Services\Validation\ContactValidator
*/
private $validator;
/**
* Options instance.
*
* #var Lib\Services\Options\Options
*/
private $options;
/**
* Mailer instance.
*
* #var Lib\Services\Mail\Mailer;
*/
private $mailer;
public function __construct(ContactValidator $validator, Mailer $mailer, HomepageRenderer $renderer)
{
$this->mailer = $mailer;
$this->renderer = $renderer;
$this->validator = $validator;
$this->options = App::make('options');
$this->beforeFilter('logged', array('only' => array('createreview')));
}
/**
* Show homepage.
*
* #return View
*/
public function index()
{
return $this->renderer->render('Home.Home')->withCleantitle("Newest Reviews");
}
/**
* Show contact us page.
*
* #return View
*/
public function contact()
{
return View::make('Main.Contact');
}
public function createreview()
{
return View::make('Reviews.Create')->withCleantitle("Post Your Review");
}
/**
* Sends an email message from contact us form.
*
* #return View
*/
public function submitContact()
{
$input = Input::all();
if ( ! $this->validator->with($input)->passes())
{
return Redirect::back()->withErrors($this->validator->errors())->withInput($input);
}
$this->mailer->sendContactUs($input);
return Redirect::to('/')->withSuccess( trans('main.contact succes') );
}
}
What does the error mean and what can I do to resolve it?
Thanks.
Wouldn't using view('Home.Home') be sufficient?

Laravel - Calling Service Class from Middleware - Class App\Http\Middleware\** does not exist

So i've got some middleware here:
namespace App\Http\Middleware;
use Closure;
use App\ChatLog;
use App\Http\Services;
class LogChat
{
protected $chatLogService;
public function __construct(ChatLogService $chatLogService)
{
$this->chatLogService = $chatLogService;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$chatLog = new ChatLog;
$chatLog->companyid = '5';
$chatLog->type = 'REQUEST';
$chatLog->ipaddress = '1';
$chatLog->name = 'bob';
$chatLog->message = 'testmessage';
$chatLog->action = 'click';
$chatLog->timeTaken = '1';
$chatLog->fullLog = 'all the log';
$this->chatLogService->store($chatLog);
return $next($request);
}
}
which calls this service here:
namespace App\Http\Services;
use App\ChatLog;
use Illuminate\Support\Facades\DB;
class ChatLogService
{
/**
* Display a listing of the resource.
*
*/
public function index()
{
//
}
/**
* Store a newly created resource in storage.
*
* #param \App\ChatLog $chatLog
*/
public function store(ChatLog $chatLog)
{
$chatLog->save();
}
/**
* Display the specified resource.
*
* #param \App\ChatLog $chatLog
*/
public function show(ChatLog $chatLog)
{
//
}
}
which is injected in here:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->bind(ChatLogService::class, function ($app) {
return new ChatLogService();
});
}
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
//
}
}
But this gives me the following exception: ReflectionException
Class App\Http\Middleware\ChatLogService does not exist
What i want to do is call the "store" method in a nicely abstracted way and i feel this solution is very close - however, I can't seem to get around this error. I'm not sure if it's something simple that i'm missing, or if the approach is fundamentally wrong!
I can't see what's wrong!
Ta :)

Accessing Properties from Classes inside of traits

I'm trying to write a unit test for the startedAt() method using mocks however the problem I'm facing is that I don't think I can access the builder instance from inside that startedAt() method.
To test the startedAt() method I created a fixture class called ExampleFilters and had it extend the parent class of Filters. Inside of the ExampleFilters class I import the FiltersByStartDate trait.
Does anyone have any suggestions on how I can access the builder property from the FiltersByStartDate trait?
Any ideas on this?
<?php
namespace App\Filters\Concerns;
trait FiltersByStartDate
{
/**
* Filter a query to include models of a specific date started.
*
* #param array $startedAt
* #return \Illuminate\Database\Eloquent\Builder
*/
public function startedAt($startedAt)
{
if (isset($startedAt[1])) {
$this->builder->whereHas('currentEmployment', function ($query) use ($startedAt) {
$query->whereBetween('started_at', [
$startedAt[0],
$startedAt[1]
]);
});
} else {
$this->builder->whereHas('currentEmployment', function ($query) use ($startedAt) {
$query->whereDate('started_at', $startedAt[0]);
});
}
return $this->builder;
}
}
<?php
namespace Tests\Fixtures;
use App\Filters\Concerns\FiltersByStartDate;
use App\Filters\Filters;
class ExampleFilters extends Filters
{
use FiltersByStartDate;
}
<?php
namespace App\Filters;
use Illuminate\Http\Request;
abstract class Filters
{
/**
* #var \Illuminate\Http\Request
*/
protected $request;
/**
* The Eloquent builder.
*
* #var \Illuminate\Database\Eloquent\Builder
*/
protected $builder;
/**
* Registered filters to operate upon
*
* #var array
*/
protected $filters = [];
/**
* Create a new class instance.
*
* #param \Illuminate\Http\Request $request
*/
public function __construct(Request $request)
{
$this->request = $request;
}
/**
* Apply the filters.
*
* #param \Illuminate\Database\Eloquent\Builder $builder
* #return \Illuminate\Database\Eloquent\Builder
*/
public function apply($builder)
{
$this->builder = $builder;
foreach ($this->getFilters() as $filter => $value) {
if (method_exists($this, $filter)) {
$this->$filter($value);
}
}
return $this->builder;
}
/**
* Fetch all relevant filters from the request.
*
* #return array
*/
public function getFilters()
{
return array_filter($this->request->only($this->filters));
}
}
<?php
namespace Tests\Unit\Filters\Concerns;
use Illuminate\Database\Query\Builder;
use Tests\Fixtures\ExampleFilters;
use Tests\TestCase;
/*
* #group filters
*/
class FiltersByStartDateTest extends TestCase
{
/* #var Tests\Fixtures\ExampleFilters */
protected $subject;
public function setUp(): void
{
$this->subject = app(ExampleFilters::class);
}
/** #test */
public function models_can_be_filtered_by_their_start_date()
{
// $this->markTestIncomplete();
$dateSet = ['2020-01-01 00:00:00'];
$mock = \Mockery::mock(Builder::class)
->shouldReceive('whereHas', \Mockery::any())
->shouldReceive('whereDate')
->withArgs(['started_at', $dateSet])
->once()
->andReturn(true)
->getMock();
dd($this->subject->startedAt($dateSet));
$builderMockFromDate = $this->subject->startedAt($dateSet);
$this->assertSame($builderMockFromDate, $mock);
}
}

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' ] );

Wrong instance passed in Laravel DB post request

So I am working on a page in Laravel that generates invite codes upon email submission. I have run into this issue, every time when I enter my email into the form, it is supposed to generate an invite code an input it into my DB then redirect me. Instead I get this error code:
Argument 1 passed to myapp\Repositories\Invite\EloquentInviteRepository::__construct()
must be an instance of Illuminate\Database\Eloquent\Model, instance of
Illuminate\Foundation\Application given, called in /var/www/laravel/bootstrap/compiled.php
on line 4259 and defined
This is my EloquentInviteRepository.php file, apparently line 21 is the line in error:
<?php namespace myapp\Repositories\Invite;
use myapp\Repositories\Crudable;
use Illuminate\Support\MessageBag;
use myapp\Repositories\Repository;
use Illuminate\Database\Eloquent\Model;
use myapp\Repositories\AbstractRepository;
class EloquentInviteRepository extends AbstractRepository implements Repository, Crudable, InviteRepository {
/**
* #var Illuminate\Database\Eloquent\Model
*/
protected $model;
/**
* Construct
*
* #param Illuminate\Database\Eloquent\Model $user
*/
public function __construct(Model $model)
{
parent::__construct(new MessageBag);
$this->model = $model;
}
/**
* Find a valid invite by a code
*
* #param string $code
* #return Illuminate\Database\Eloquent\Model
*/
public function getValidInviteByCode($code)
{
return $this->model->where('code', '=', $code)
->where('claimed_at', '=', null)
->first();
}
/**
* Create
*
* #param array $data
* #return Illuminate\Database\Eloquent\Model
*/
public function create(array $data)
{
$data['code'] = bin2hex(openssl_random_pseudo_bytes(16));
return $this->model->create($data);
}
/**
* Update
*
* #param array $data
* #return Illuminate\Database\Eloquent\Model
*/
public function update(array $data){}
/**
* Delete
*
* #param int $id
* #return boolean
*/
public function delete($id){}
}
In case anyone was curious; the __construct() interface from Illuminate\Database\Eloquent\Model.php:
/**
* Create a new Eloquent model instance.
*
* #param array $attributes
* #return void
*/
public function __construct(array $attributes = array())
{
$this->bootIfNotBooted();
$this->syncOriginal();
$this->fill($attributes);
}
and Illuminate\Foundation\Application.php:
/**
* Create a new Illuminate application instance.
*
* #param \Illuminate\Http\Request $request
* #return void
*/
public function __construct(Request $request = null)
{
$this->registerBaseBindings($request ?: $this->createNewRequest());
$this->registerBaseServiceProviders();
$this->registerBaseMiddlewares();
}
In case these help in debugging the issue!
As per request I have included my controller element used during the post function, this is the part that seems to activate the repository and prompt the error:
<?php
use myapp\Repositories\Invite\InviteRepository;
class InviteController extends BaseController {
/**
* InviteRepository
*
* #var myapp\Repositories\Invite\InviteRepository
*/
protected $repository;
/**
* Create a new instance of the InviteController
*
* #param myapp\Repositories\Invite\InviteRepository
*/
public function __construct(InviteRepository $repository)
{
$this->repository = $repository;
}
/**
* Create a new invite
*
* #return Response
*/
public function store()
{
$invite = $this->repository->create(Input::all());
}
}
RepositoryServiceProvider.php
<?php namespace myapp\Repositories;
use Illuminate\Support\ServiceProvider;
class RepositoryServiceProvider extends ServiceProvider {
/**
* Register
*/
public function register()
{
$this->registerInviteRepository();
}
/**
* Register the Invite Repository
*
* #return void
*/
public function registerInviteRepository()
{
$this->app->bind('myapp\Repositories\Invite\InviteRepository', function($app)
{
return new EloquentInviteRepository( new Invite );
});
}
}
Any idea's as to what I am missing?
Thanks for the help guys,
You've been a great resource so far!
In the file RepositoryServiceProvider.php, replace this
$this->app->bind('myapp\Repositories\Invite\InviteRepository', function($app)
{
return new EloquentInviteRepository( new Invite );
});
With this:
$this->app->bind('myapp\Repositories\Invite\InviteRepository',
'myapp\Repositories\Invite\EloquentInviteRepository');

Categories