Laravel #include controller data - laravel

I'm trying to receive data on a sidebar that is included in the blade template but i'm not getting any data delivered. I've tried adding #include('admin.sidebar',['message_counter' => $message_counter]) and in the sidebar view show as {{$message_counter}}. I'm getting a Undefined variable: message_counter.
My router:
Route::get('/admin/sidebar', [
'uses' => 'MessagesController#counter',
'as' => 'admin.sidebar'
]);
My controller
use App\Message;
public function counter()
{
$message_counter = Message::where('status', 0)->get();
return view('admin.sidebar')->with('message_counter', $message_counter);
}
My View
<span class="menu-collapsed">Messages <span class="badge badge-pill badge-primary ml-2"> {{$message_counter}} </span></span>
What i ultimately intend to do is to show the amount of unread messages in the sidebar of the administrator backend, which is #includein every page.
It may be because i'm accessing two different controllers everytime I enter any page on the admin backend.
I've looked into Including Sub-Views but i'm probably missing something silly or not understanding some key concept, help is appreciated!
Thank you!

Note: I think this is inconvenient and unrecommendable. This is just to answer the question, you can scroll down to see other answers or approach.
Controller
public function counter()
{
$message_counter = Message::where('status', 0)->get();
return view('admin.sidebar');
}
View
#php
$message_counter = App\Message::where('status', 0)->get();
#endphp
Messages <span class="badge badge-pill badge-primary ml-2"> {{$message_counter}} </span></span>

You can try like this way
In Route:
Route::get('/admin/sidebar', 'MessagesController#counter');
In Controller
use App\Message;
public function counter()
{
$message_counter = Message::where('status', 0)->get();
return view('admin.sidebar', compact('message_counter));
}
And your view is ok.. Try this and if it is not working please let me know....

With a View Composer: add this to App\Providers\AppServiceProvider#boot()
View::composer('admin.sidebar', function ($view) {
$message_counter = Message::where('status', 0)->get();
$view->with([''message_counter' => $message_counter]);
});

Related

Laravel Livewire Pagination Result Disappear After Clicking Next Page/Page Number

i've been searching for a question like the one above but i can't find one, so i'm gonna make one
My problem is, when i make a very simple pagination with Laravel Livewire, the first page appear just fine, but when i click "Next Page/Page Number", the result just disappear, even though there are still more results to show, i'm absolutely got no idea, no mattter how i try.
As you can see, the simple pagination work just fine, there is next and previous button and a very big next and previous picture below
But the moment i click next page or page number, the result just disappear, the total number of result even go to 0
Here is my Component code:
namespace App\Http\Livewire;
use Livewire\Component;
use Illuminate\Http\Request;
use DB;
use Livewire\WithPagination;
class Category extends Component
{
use WithPagination;
public function render(Request $request)
{
$id = $request->id;
$product_count = DB::table('product')->where('category_id', $id)->count();
$page = $request->page ?? 1;
$product_all = DB::table('product')->where('category_id', $id)->paginate(3);
return view('livewire.category',[
'product_all' => $product_all,
'product_count' => $product_count,
'page' => $page,
]);
}
}
Here is my view code:
<div class="row">
#foreach ($product_all as $product)
<div class="col-lg-4 col-md-6 col-12 mt-4 pt-2">
#php
product($product);
#endphp
</div>
#endforeach
<!-- PAGINATION START -->
#if ($product_all instanceof \Illuminate\Pagination\LengthAwarePaginator)
{{ $product_all->links() }}
#endif
<!-- PAGINATION END -->
</div>
And a small notice, i try pagination(just normal laravel pagination) without livewire and it work perfectly fine, that's why i am really clueless of what is happening
I have already include the livewire #livewireStyles and #livewireScripts, and i can't find an answer anywhere else cause i don't see any question that match my problem, and i'm kinda new to livewire
I think your problems is related with the request parameter on the render method of the livewire component, once livewire on rerender can't access the request value, until next browser refresh.
public function render(Request $request)
instead, use livewire properties to bind the id and page with values livewire can read on rerenders
#livewire('some-component', ['category_id' => $parent_category_id, 'page' => $parent_page_value])
Like above, livewire bind this values to self properties and read from them on rerender
public $category_id, $page;
public function render()
{
$product_count = DB::table('product')->where('category_id', $this->category_id)->count();
$product_all = DB::table('product')->where('category_id', $this->category_id)->paginate(3);
return view('livewire.category',[
'product_all' => $product_all,
'product_count' => $product_count,
'page' => $this->page,
]);
}

Laravel: Undefined variable: posts (View: cant solve

So i have a problem that has been bugging me for a few days now. I want to display my posts on my homepage that is already displaying on my other pages. I think i have found why the information is not displaying and this is due to the Routes of the page. The view is looking fine and works correctly, however my controllers are the issue:
Web.php
Route::get('/', 'PageController#index');
Route::get('/welcome', 'HomeController#index1');
Route::get('/services', 'PageController#services');
Route::get('/register', 'PageController#register');
Route::get('/Create', 'PageController#Create');
Route::get('/search', 'PageController#search');
Route::get('/payment', 'PageController#Payment');
Route::resource('posts', 'PostsController');
Route::resource('search', 'SearchController');
Route::resource('reviews', 'ReviewsController');
Route::resource('postings', 'HomeController');
HomeController.php
public function index()
{
return view('home');
}
public function index1()
{
$postings = Post::all();
return view('Pages.welcome', compact('postings'));
}
Welcome.blade.php
#if(count($postings) > 1)
#foreach($postings as $post)
<h2>{{$post->title}}</h2>
#endforeach
#else
</p>no posts found</p>
#endif
The issue is in my WEB.PHP. PageController#index directs the page to the homepage, with HomeController being the controller that holds index. I then decided to create a function within that HomeController that allows me to display posts, however i keep getting error 'undefined error'. To conclude how would i insert a function in an existing controller that already has index.
You don't have $postings variable in your view, don't access it. This does not mean you can not do what you want.
You can abuse how if statements are resolved. If you have && operator in your if statement it will not check secondary conditions if first condition fails.
Will fail
#if ($postings)
Will work
#if (false && $postings)
To check if a variable is present without accessing it, you can use isset(), that is a PHP function. This will create the preferred statement that will not access $postings if it is not there. So try with the following code.
#if(isset($postings) && count($postings) > 1)
#foreach($postings as $post)
<h2>{{$post->title}}</h2>
#endforeach
#else
</p>no posts found</p>
#endif

New to Laravel - How to pass model data to a blade view?

Ok, I am totally re-writing this question, now that I am a bit more familiar with larval.
Here is my situation: I have a guitar lessons site based on larval 5.2.36, where each lesson belongs to a category, and within a lesson are several exercises. An exercise table does not have a category id as it is linked to a lesson which has a category.
Goal What I am trying to figure out is how to pass the category of the currently displayed lesson or exercise to a menu sidebar view that displays the categories, so that the category of the lesson or exercise is highlighted. For this, I need to understand how to do such a task in laravel.
From what I gathered, this is often done via controllers. However, there is no menu controller, but rather a menu composer. It contains a function
class MenuComposer
{
public function compose(View $view)
{
$minutes = 6 * 60;
$value = Cache::remember('menu-categories', $minutes, function() {
return \App\Category::with('parent')->with('children')->get();
});
$view->with('categories', $value);
}
}
Then in the menu blade file we have
#foreach ($categories as $category)
<?php $category = $category->present(); ?>
#if ($category->parent == null)
<li>{{ $category->title }}</li>
#foreach ($category->children as $child)
<?php $child = $child->present() ?>
<li class="level1">{{ $child->title }}</li>
<?php
/*
#foreach ($child->children as $grandChild)
<?php $grandChild = $grandChild->present() ?>
<li class="level2">{{ $grandChild->title }}</li>
#endforeach
*/
?>
#endforeach
#endif
#endforeach
So this is clear. I see that I can use the menu composer to pass additional data with a $view->with() call.
The question is how do I get the current category? For exercises and lessons, the routes don't have category data. They are of form
lesson/lessonid/lessontitle
or
exercise/exid/extitle
So I know I could do some sort of query of the model. But seems that wouldn't make sense, since I know there are other places in the process flow where the current cat is being passed. For instance, on an exercise page, the view is retrieving category as
$exercise->lesson->category->title
It is being passed this in exercise controller as
public function index($id, $name = null)
{
//$this->hit($id);
$exercise = $this->apiController->get($id);
$authorized = $this->isUserAuthorized();
return view('exercise/index', [
'exercise' => $exercise->present(),
'authorized' => $authorized,
]);
}
Similarly, a lesson controller passes $lesson object to lesson view as
public function index($id, $name = null)
{
//$this->hit($id);
$lesson = $this->apiController->get($id);
$subscribed = $this->request->user() && $this->request->user()->subscribed('premium');
return view('lesson/index', [
'lesson' => $lesson->present(),
'subscribed' => $subscribed,
]);
}
Based on above, seems I could modify the return statements in the lesson and exercise controller to pass the category to the menu view, but I don't see in the documentation how to do that, and I suspect the menu view is rendered before the lesson and exercise controller are called...
Also read about using service providers. middleware, etc, here: How to pass data to all views in Laravel 5?
But all these approaches seem overkill. I don't need every view to have the data. Seems to me, I need to do this somehow in the menu composer. But I don't know what method to use from the menu composer to retrieve the current lesson or exercise category. In the menu composer after debugging in phpstorm I see that the $view object for a lesson has $view->$data->$lesson->$entity.
So what I did was edited the menu composer to pass category to view:
$d=$view->getdata();
$s=array_key_exists ('lesson' , $d );
if ($s ==1) $attr = collect($d)->get('lesson');
$cat=$attr->cat();
This works since in the LessonPresenter I added function
public function cat()
{
$cat = $this->entity->category['attributes']['title'];
return $cat;
}
This works, but I feel like it is a hack. And I will have to do this for the Exercise Presenter as well. Being new to larval I suspect there has to be a more elegant way to do this. So can someone please explain how this should be done?
thanks,
Brian
You can use Facades of Laravel directly in blade templates.
Just use {! !} syntax to try and echo it. e.g: {!! Route::current() !!}
There are also similar functions of Route facade you can use.
Then, you can check your category with #if() ... #endif blocks and add something like class name within it.
Note: Don't put lots of logic in your blade files. Do it in your controller file (even in your other service classes) and pass simplest variables (e.g $isCurrentCategory) as an array to your template files using View::make() function's 2nd parameter.
Maybe this can help you
<a href="#" class="{{ (\Request::route()->getName() == 'routename') ? 'active' : '' }}">
You can also get the route prefix for example, you can check this out here:
Laravel API Docs Routing

Passed data lost in Laravel paginator starting from page 2

I am trying to list people by their appRole. Here's the controller:
public function indexByAppRole(Request $request, $appRoleId)
{
$h1 = AppRole::where('id', $appRoleId)->first()->name;
return view('admin.people.index', [
'people' => $this->people->byAppRole($appRoleId),
'appRoles' => $this->appRoles->forAll(),
'h1' => 'Role: '. $h1,
]);
}
Paginator is used in the repository:
public function byAppRole($appRoleId)
{
return Person::where('person_app_role.app_role_id', $appRoleId)
->join('person_app_role', 'person_app_role.person_id', '=', 'people.id')
->select('people.*') // fix ID confusion but why?
->paginate(20);
}
The main view lists the returned people. In the sidebar, I have the following list as side-navigation:
<ul class="list-group nav nav-pills nav-stacked">
#foreach ($appRoles as $appRole)
<li>
{{ str_plural($appRole->name) }}
</li>
#endforeach
</ul>
The navigation list works on page 1 of search results or listings, but the list is not showing up on page 2 and subsequent pages. What did I do wrong?
I solved the problem. For AppRole, I also used a paginator, so this was fixed by using all() instead of paginate() to get all appRoles.
// Before...........
public function forAll()
{
return AppRole::paginate(20);
}
And:
// After............
public function forAll()
{
return AppRole::all();
}

NotFoundHttpException Laravel

I am very new in learning Laravel. I want to fetch data from a database and show it. I can do it. But I want to use the title (fetched from the database) as a link. but then I get a NotFoundHttpException.
Routes
Route::get('articles', 'ArticleController#index');
Route::get('articles/{id}', 'ArticleController#show');
Controller
class ArticleController extends Controller
{
public function index()
{
$articles = Article::all();
return view('articles.index', compact('articles'));
}
public function show($id){
$article = Article::find($id);
return view('articles.show', compact('article'));
}
}
View
#extends('new_welcome')
#section('content')
<h1>Articles</h1>
#foreach($articles as $article)
<article>
<h2>
{{$article->title}}
</h2>
<div class="body">{{ $article->body}}</div>
</article>
#endforeach
#stop
Can someone help me in this case?
Your problem is because of You've "eat" one curly brace (blade engine skips it):
was:
href="{url ('/articles',$article->id)}"
have to be:
href="{{url ('/articles',$article->id)}}"
as You said:
if I click on any single article title then it can not show me the
specific article. But, if I give the URL "homestead.app/articles/2";
so You can see that when You click on link Your browser's address bar becomes:
homestead.app/{url ('/articles',$article->id)}
Because You're beginner so I'll give You advice to not to set direct url in views using url() helper.
Named routes are better if You want to have app that will work properly if in future You decide to change url from: articles to artcls. In this named routes will save You from bulk changing urls in view files.
set name to Your route using 'as' directive that makes Your routing flexible for changes (when You need to change URL so You change only path and keep views unchanged):
Route::get('articles/{id}', ['as' => 'article', 'uses' => 'ArticleController#show']);
Route::get('articles', ['as' => 'articles', 'uses' => 'ArticleController#index']);
change Your view file (find route helper in href):
#extends('new_welcome')
#section('content')
<h1> Articles </h1>
#foreach($articles as $article)
<article>
<h2>
{{$article->title}}
</h2>
<div class="body">{{ $article->body}}</div>
</article>
#endforeach
#stop

Resources