Issue using View()->Composer() in AppServiceProvider - laravel

I am trying to pass data to a view using the boot method in the AppServiceProvider, and have followed the steps outlined in one of the Laracast fundamentals videos. However, I am getting an error in my controller when trying to use this variable.
In my AppServiceProvider:
public function boot()
{
view()->composer('home', function($view){
$view->with('current', Post::orderBy('created_at', 'desc')->first());
});
}
So this should pass the data to my home view as far as I understand, so that I don't need to keep referencing it in all the methods I have in the controller for that view. I then have a homeController with the following method:
public function index()
{
//Get user
$user = Auth::user();
//OMDB API setup - Get Movie name, remove spaces, add into API request
$movie_one = str_replace(" ", "+", $current->movie_one);
$movie_two = str_replace(" ", "+", $current->movie_two);
return view('home', compact(array('user')));
}
Previously I was adding a variable called current in this method to get an entry from my Post table, but wanted to add it to the AppServiceProvider as I will have to re-declare it in other methods as well. The issue I have is that I try to use the $current object again in this method, but it isn't available to it? I get the following error:
ErrorException in homeController.php line 30:
Undefined variable: current
What can I do here? Can I pass that data from to a controller as well as the home view? Or is that not possible?

the code you written inside the boot method, will only be accessible inside home view, if you want to access the Post object inside controller too, you have to follow this, through this you can access your Post object in controller, as will as view.
app()->singleton('current',function($app){
return Post::orderBy('created_at', 'desc')->first();
});
So in your code, you can access the Post object like this,
$post_obj = App::make('current');
$post_obj->movie_two;
or directly
App::make('current')->movie_two;

Related

Laravel new controller method doesn't work

When I create a new function in the controller for some reason it does not work. When I set the code from this function(getUnitsNotIn) to another function(index), that code works.
Does anyone know why this is happening?
My UnitsController.php action
public function index(){
$items = Unit::select('parent_id')->where('parent_id','!=',NULL)->get()->toArray();
return Units::whereNotIn('id',$items)->get();
}
public function getUnitsNotIn(){
$items = Unit::select('parent_id')->where('parent_id','!=',NULL)->get()->toArray();
return Units::whereNotIn('id',$items)->get();
}
My api.php
Route::apiResource('/units', 'UnitController');
Route::get('/units/notIn', 'UnitController#getUnitsNotIn');
In short, any new controller function that I make will not work. I tried to make a new controller and the same thing happens.
How to fix this problem?
It is not working because of apiResource(). Resource route assumes /units/{id}. so when you call /units/notIn route assume notIn as id And Action call show()
You need to use a different name.
Route::get('/un/notIn', 'UnitController#getUnitsNotIn');
Verb, path , action , route name
GET /units/{id} show units.show
Change this to
Route::get('/units-notIn', 'UnitController#getUnitsNotIn');
You define a resource controller so here in units/notin,notin define a id so
it call your show function default.

The update nor the destroy methods won't work in laravel eloquent model?

I have a strange situation where eloquent model won't let me update nor destroy while index and create is working fine!
I'm using Vue.js and Laravel API Resource for form control, and while it worked with me before, it won't work here:
Here's my Vue.js Code:
updateFinish(finish) {
axios.patch(`/api/finishes/${finish.id}`, finish).then(response => {
this.fetchFinishes();
}).catch(error => {
// Get laravel validation error
this.errors = error.response.data.errors;
});
},
laravel update code (not working)
public function update(FinishType $finishType)
{
// Don't know why not working
$finishType->update($this->validateRequest());
return new FinishTypeResource($finishType);
}
the response is null:
{"id":null,"name":null}
While this code works:
public function update($id)
{
$finishType = FinishType::find($id);
$validates = $this->validateRequest();
$finishType->name = $validates['name'];
$finishType->save();
return new FinishTypeResource($finishType);
}
public function validateRequest()
{
return request()->validate([
'name' => 'required | unique:finish_types',
]);
}
Note the Model name is FinishType and database table name is finish_types, I even tried to define the table name in the model like so protected $table = 'finish_types' – still not working and I already have defined the $fillable array!!!
Your route model binding is not working correctly, for the implicit binding to work your injected variable should match the route parameter name.
Assuming that your parameter name could be finish (reading the url from your javascript) you have to write the update function using $finish as injected variable, like this:
public function update(FinishType $finish)
{
$finish->update($this->validateRequest());
return new FinishTypeResource($finish);
}
Do the same for destroy():
public function destroy(FinishType $finish)
{
// your destroy code here
}
In any case you can run php artisan route:list to find your parameter name (the part of the URI in braces) and give the same name to the injected variable.
If the two do not match, parameter and injected variable name, laravel injects a void, not loaded, FinishType model so it does not make sense doing an update or a delete on it.
I can't post comments so I'm going to post what I assume is the answer.
Laravel does route model binding automagically when the route url name corresponds to the name of the table I think... or model.
So users/{id} would auto bind the User object when you type it as a param in the controller. Example (User $user)
However, since your URL seems to be "different" from the name of your Model/Table, go to the RouteServiceProvider, and manually do the binding.
So in your case you'd do something like this in the boot function of the RouteServiceProvider class:
public function boot()
{
parent::boot();
Route::model('finishes', FinishType::class);
}
Don't forget your imports :)
You can read more about Explicit Model Binding here: https://laravel.com/docs/5.8/routing#explicit-binding

Laravel 5.7 ApiResource GET params empty

I use Laravel 5.7 for my JSON API web application.
In my routes/api.php file, I created the following route :
Route::apiResource('my_resource', 'API\Resource')->except(['delete']);
I added the corresponding controller and methods (index, show,...) and everythink work perfectly. My issue is the following : I would like to add optional GET params like this :
http://a.x.y.z/my_resource?param=hello&param2=...
And for instance being able to retrieve 'hello' in my index() method. However, when I print the value of $request->input('param'), it's empty. I just don't get anything.
Yet, if I create a route like this, with an optional parameter:
Route::get('/my_resource/{param?}', 'API\Resource');
I'm able to get the parameter value in my controller method.
Here is my index method :
class Resource extends Controller {
public function index(Request $request)
{
print($request->input('param'));
// ...
}
// ...
}
Am I missing something ? I'm still new in Laravel maybe I missed something in the documentation.
Thanking you in advance,
You can use:
$request->route("param");

Trying to get intended url in LoginController in Laravel 5.6

I'm trying to capture the intended url in my LoginController so I can execute some logic in a showLoginForm() method I added to the controller so I can send the user to a specific view based on the intended URL.
I've tried the following and I cannot get it to work:
public function showLoginForm()
{
$intededUrl Session::put('url.intended', URL::full());
// my base application url is http://www.websites.com:8080
if (starts_with($intededUrl, url('/admin'))) // i want all routes that begin with http://www.websites.com:8080/admin to go here
return view('auth.login');
return view('themes.'.env('APP_THEME', 'mango').'.auth.login'); // but it keeps taking me here
}
I'm using Laravels starts_with() method to try and match the start of the url string.
I just figured it out. I needed Session::get('url.intended');

How to share object in blade template across Zizaco/Confide routes?

I'm trying to share an object across a Laravel application. I need this because I want to create a blade template which will be included everywhere and will also perform some logic/data manipulation (a dynamic menu sort of speak).
To be able to accomplish this I've created a constructor in the Base controller and used View::share facade.
While this works across all routes in the application, it's not working for Zizaco/Confide generated routes, where I get Undefined variable error for $books.
This is the constructor in the base controller:
public function __construct()
{
$books = Book::all();
View::share('books', $books);
return View::make('adminMenu')->with('books', $books);
}
What you need are View Composers!!
You can hook a view composer to a certain view name or pattern (using * wildcard). Every time before that view gets rendered the view composer will run.
You can put this anywhere. Most elegant would be a custom app/composers.php which is then required at the bottom of app/start/global.php
View::composer('adminMenu', function($view){
$books = Book::all();
$view->with('books', $books);
}

Resources