Recursive display of data with blade, laravel - laravel

My Controller:
class Comments extends Controller {
public function GenerateComments($id){
$theme = DB::table('New_Themes')
->where('id', $id)
->get();
$Comments = NewTheme_Comment::where('id_theme', $id)->get();
return view('comments', ['Themes'=>$theme, 'Comments'=>$Comments]);
}
My Table(NewTheme_Comment):
id
parent_id
id_theme
user
text
upVotes
downVotes
My view(contains the recursive display of the tree of comments like the same in reddit), ......(data) contains the bootstrap media object, and the </div>'s things are used to round up (visually) the tree of comments as it should be:
<?php
tree($Comments, 0, 0);
$var = -1;
function tree($Comments, $parent_id = 0, $level=0, $c=0) {
global $var;
foreach($Comments as $Comment) {
if($Comment['parent_id'] == $parent_id) {
If ($level > $var) $var++; else {
for ($i = $var-$level+1; $i>0; $i--) { if ($c < 0) echo '</div> </div>'; else $c--; };
$var=$level;
};
echo '........(data)';
tree($Comments, $Comment['id'], $level+1,$c);
};
};
};
?>
The problem is that .........(data) should contain this stuff:
<div class="media">
<div class="media-left">
<img class="media-object" style="height:40px; width:40px;" src="{{ URL::asset("images/upVote.svg") }}" >
<div>{{$Comment->upVotes-$Comment->downVotes}}</div>
<img class="media-object" style="height:40px; width:40px;" src="{{ URL::asset("images/downVote.svg") }}" >
</div>
<div class="media-body">
<p class="media-heading">{{ $Comment->text }}</p>
<p class="media-heading">{{ $Comment->user }} / {{ $Comment->created_at }} </p>
And I am using the blade above this line | , which I can't integrate into that echo in view, replacing the ..........(data).
I have the intuition that the function I should integrate into the controller but I am broken(I spent to much time on recursive method of displaying comments) and I don't know how to take the data and print out it as whole unit recursively.
Any help is GREATLY appreciated to find a way out of this mess, thank you very much
Edit 1:
This is an example if i am filling with bootstrap media object in ........(data):
<div class="media">
<a class="media-left" href="#">
<img class="media-object" src="..." alt="...">
</a>
<div class="media-body">
<h4 class="media-heading">Media heading</h4>
Without 2 x </div>

You are approaching the views in a wrong way, as blade templates are not meant to use functions, it's better to follow the below recommendations.
The best way for that is to place the function code inside a blade file, for example recursive.blade.php:
recursive.blade.php
#foreach($comments as $comment)
//place your code here
#endforeach
Then in your main blade you can call it several times:
main.blade.php
<div>
#include('recursive', ['comments' => $comments])
</div>

The below example works for me and is the most widely used approach. remember the default value for parent_id is -1.
Model
public function children(){
return $this->hasMany(self::class,'parent_id','id')->with('children');
}
Controller
$comments = Comments::where('parent_id','=',-1)->get();
return view('comments',['comments'=> $comments]);
Blade (comments.blade.php)
<div class="tree">
#include('comment-list-widget',['comments' => $comment])
</div>
Blade (comment-list-widget.blade.php)
<ul>
#foreach($comments as $comment)
<li>
<a>{{$comment->text}}</a>
#if(!empty($comment->children) && $comment->children->count())
#include('comment-list-widget',['comments' => $comment->children])
#endif
</li>
#endforeach
</ul>

Related

How to display default image if no filename exists in Laravel database

I want to display an image for each entry in a list of posts. The name of the images are unique file names. They are all saved in a database (MySQL) table. There is more than one image for each post. The code works right. Except, when there is a post without an image filename. This is a possible scenario but i can't get the code to work. In the event there's no existing filename for a post, i want to display a default filename.
Here's my code:
Images logic:
/**
* Get a vehicle's top or main image data from the image table
*/
public function topImage($id)
{
$image = Vehiclefulldataimage::where('vehiclefulldatas_id', $id)
->orderBy('id', 'ASC')->first();
return $image;
}
Here's the blade view, Posts:
#if (count($posts) > 0)
#foreach($posts as $post)
<?php $imageFilename = (new \App\Models\Logic\Images)->topImage($post->id); ?>
<!--Item-->
<li>
<div class="preview">
#if ($imageFilename = 0)
<img src="{{ asset('images') . '/' . 'defaultImage.jpg' }}" alt="No photo">
#else
<img src="{{ asset('images') . '/' . $imageFilename->disk_image_filename }}" alt="{{ ucfirst($imageFilename->caption) . ' | ' . $post->title }}">
#endif
</div>
<div class="desc">
<h3>{{ str_limit($post->title, 100, '...') }}</h3>
</div>
</li>
<!--/Item-->
#endforeach
#endif
This is the error message i get:
"Trying to get property of Non Object"
Try the following code:
You are using an assignment operator instead of comparison operator
//#if (count($posts) > 0)
#if (!$posts->isEmpty())
#foreach($posts as $post)
<?php $imageFilename = (new \App\Models\Logic\Images)->topImage($post->id); ?>
<!--Item-->
<li>
<div class="preview">
//#if ($imageFilename = 0) this is an assignment operator not comparison operator
#if ($imageFilename->isEmpty())
<img src="{{ asset('images') . '/' . 'defaultImage.jpg' }}" alt="No photo">
#else
<img src="{{ asset('images') . '/' . $imageFilename->disk_image_filename }}" alt="{{ ucfirst($imageFilename->caption) . ' | ' . $post->title }}">
#endif
</div>
<div class="desc">
<h3>{{ str_limit($post->title, 100, '...') }}</h3>
</div>
</li>
<!--/Item-->
#endforeach
#endif
Check your if statement....what you're doing there is an assignment and not a condition test...you can include a column..with a string pointing to the path of your default image..and set it to default...then load it...as default image
All of the answers above fix your problem. However, I recommend you to fix this problem by using Laravel features, Mutators.
https://laravel.com/docs/5.8/eloquent-mutators
Laravel mutators allow you to format or modify your Model attribute.
Just in your Vehiclefulldataimage model write the code below:
public function getImageAttribute($value)
{
//can write more logic here.
return $value ?: 'path/to/your/default/image';
}
Then you don't care more if condition blade template. If your image is empty the mutator returns the default image. So, everywhere when your retrieve Vehiclefulldataimage instance the mutator works properly
Thanks everyone.
After looking at all the answers, i did a simple alteration to my code. I altered:
#if ($imageFilename = 0)
to:
#if ($imageFilename == null)
Thus, my code now looks:
#if (count($posts) > 0)
#foreach($posts as $post)
<?php $imageFilename = (new \App\Models\Logic\Images)->topImage($post->id); ?>
<!--Item-->
<li>
<div class="preview">
#if ($imageFilename == null)
<img src="{{ asset('images') . '/' . 'defaultImage.jpg' }}" alt="No photo">
#else
<img src="{{ asset('images') . '/' . $imageFilename->disk_image_filename }}" alt="{{ ucfirst($imageFilename->caption) . ' | ' . $post->title }}">
#endif
</div>
<div class="desc">
<h3>{{ str_limit($post->title, 100, '...') }}</h3>
</div>
</li>
<!--/Item-->
#endforeach
#endif

in laravel error Invalid argument supplied for foreach() (View: i cant see $value

I am trying to make a blog foreach that see this erro
Invalid argument supplied for foreach() (View:
my site https://weadam.com/
my code is:
controller:
public function index()
{
$localetmp = Session::get('locale');
$blogs = #json_decode(file_get_contents("https://www.weadam.com/blogs/wp-json/wp/v2/posts?per_page=4&lang=" . $localetmp));
$blogsold = Blog::orderBy('id','desc')->take(100)->get();
foreach ((array)$blogs as $blog){
// $blog->elapsed = $this->time_elapsed_string('#'.$blog->date);
// $blog->date = date("d F Y",$blog->date);
}
$error = "";
return view('home-new',['blogs' => $blogs]);
}
and view is:
<div class="eng-home-blog">
<div class="col-sm-9 home-post-disp bx-shadow brd-radius bg-white">
#foreach($blogs as $blog)
#if($blog->sticky)
<img src="{{$blog->fimg_url}}" alt="" class="img-responsive brd-radius bx-shadow">
<div class="hm-post-date">{{$blog->date}}</div>
<h3>{{$blog->title->rendered}}</h3>
<p>{!!$blog->excerpt->rendered!!}</p>
<span>{{__("READ MORE")}}</span>
#endif
#endforeach
</div>
</div>
pass true as secondary param at json_decode function
$blogs = #json_decode(file_get_contents("https://www.weadam.com/blogs/wp-json/wp/v2/posts?per_page=4&lang=" . $localetmp),true);
now you have to fetch this blog data as associative data. not as an object. here's the example code for it
<div class="eng-home-blog">
<div class="col-sm-9 home-post-disp bx-shadow brd-radius bg-white">
#foreach($blogs as $blog)
#if($blog['sticky'])
<img src="{{$blog['fimg_url']}}" alt="" class="img-responsive brd-radius bx-shadow">
<div class="hm-post-date">{{$blog['date']}}</div>
#endif
#endforeach
</div>
</div>
You can simply use forelse it will take care of the empty case
#forelse($blogs as $blog)
// do what ever you want to do
#empty
<div> Nothing to show </div>
#endforelse
Hope it helps reference.
Thanks.

I have problem with my code "UNDEFINED INDEX"

There is link to my previous problem where is code,maybe it helps you
Parse error: syntax error, unexpected '__construct' (T_STRING), expecting function (T_FUNCTION) or const (T_CONST)
this is problem i get
Undefined index: item (View: C:\xampp\htdocs\laravel\resources\views\shoppingCart.blade.php)
this error is there <strong><?php echo e($product['item']['name']); ?></strong>
this is my route
Route::get('shoppingCart', 'WebController#shoppingCart')->name('get.shoppingCart');
this is in my webcontroller
public function shoppingCart(){
if(!Session::has('cart')){
return view('shoppingCart');
}
$oldCart = Session::get('cart');
$cart = new Cart($oldCart);
return view('shoppingCart',['products'=>$cart->items]);
}
this is link for cart
<li>CART <span class="badge">{{Session::has('cart') ? '!' : ''}}</span></li>
And this is my code for shoppingCart
#extends('layouts.main')
#section('content')
#if(Session::has('cart'))
<div>
<div>
<ul class="list-group">
#foreach($products as $product)
<li class="list-group-item"></li>
<strong>{{$product['item']['name']}}</strong>
<li>Odstrániť</li>
#endforeach
</ul>
</div>
</div>
#else
<div>
<h2>V košíku nemáš žiadne položky!!!</h2>
</div>
#endif
#endsection
Firstly you can check if you have data or not on $cart->items while writing dd($cart->items); on the your function . Follow my comments .
public function shoppingCart(){
if(!Session::has('cart')){
return view('shoppingCart');
}
$oldCart = Session::get('cart');
$cart = new Cart($oldCart);
//dd($cart->items) /*uncomment this and check if you have data or not if you have no then problem is */
return view('shoppingCart',['products'=>$cart->items]); /* on the other if you have data dont forget those line and look at my comment on blade.php */
}
Your blade.php
#extends('layouts.main')
#section('content')
#if(Session::has('cart'))
<div>
<div>
<ul class="list-group">
#foreach($products as $product)
<li class="list-group-item"></li>
<strong>{{$product['item']['name']}}</strong>
<!--Look at here you remembe you were add products writing `['products'=>$cart->items]` then you be care calling your datas first you be relay on your codes you are working array (it seems you are working with objects then you need to call it $products->item->name Secondly you remember on the function you were add your data `['products'=>$cart->items]` like this if there is no child items object on $cart->items then you need to call it like
foreach($products as $product))
{
echo $product->name; //if it is array then echo $product['name'];
}
-->
<li>Odstrániť</li>
#endforeach
</ul>
</div>
</div>
#else
<div>
<h2>V košíku nemáš žiadne položky!!!</h2>
</div>
#endif
#endsection

laravel 5.4 undefined variable in view

I'm kind of new to laravel and trying to pull data from a database but keep hitting an error page saying there's an undefined variable within the view.
I'm supposing there's something I'm doing wrong (or not doing) within the controller. So I have a create.blade.php that posts data from a form to the database and everything works fine, however I want it such that after posting to the database to redirect to the show.blade.php showing the uploaded data and here is where I hit a brick wall with the error messages.
This is my store function within the controller -
public function store(Request $request)
{
$data4page = new Data4page;
$data4page->h1Ttle = $request->h1Ttle;
$data4page->h4Ttle = $request->h4Ttle;
$data4page->description = $request->description;
$data4page->save();
/*redirecting to the content's show page*/
return redirect()->route('content.show', $data4page->id);
}
And this is the show function within the same controller -
public function show($id)
{
//
$data4page = Data4page::find($id);
return view('digital.show')->with(compact('data4page'));
}
The error message I'm getting is -
Undefined variable: data4page (View: /var/www/html/theproject/resources/views/content/show.blade.php)
And in the show.blade.php this is a sample of what I have -
<h1>{{ $data4page->h4Ttle }}</h1>
<p>{{ $data4page->description }}</p>
<h4>{{ $data4page->h4Ttle }}</h4>
Having said all that, I have also tried various means of returning the view within the show function of the controller but all these result in the same error message above. These variants include -
return view('content.show')->with('data4page', $data4page);
return view('content.show',['data4page'=>$data4page]);
Update: I earlier had typos but now the error I get is -
undefined variable: {"id":9,"h1Ttle":"h1 sample text","h4Ttle":"h4 sample text","description":"body text goes here"} (View: /var/www/html/theproject/resources/views/content/show.blade.‌​‌​php)
This is the show.blade.php -
#extends('main')
#section('title')
#section('content')
<div class="app-template">
<main class="wrapperMain">
<div class="">
<aside class="navSidebar">
<nav class="navProperty">
<h1 class="navProperty-title">{{ $data4page->h1Ttle }}</h1>
</nav>
<footer class="footerProperty">
<div class="upcomingSchedule">
<h4 class="upcomingSchedule-heading">{{ $data4page->h4Ttle }}</h4>
</div>
</footer>
</aside>
</div>
<div class="content content--withSidebar">
<div class="lead--Home">
<p>{{ $data4page->description }}</p>
</div>
</div>
</main>
#endsection
You have a name mismatch.
return view('content.show')->with(['name' => $data4page]);
Here you should use:
<h1>{{ $name->h4Ttle }}</h1>
As you called it name
In your other options you defined Data4page and in your view you use data4page (lower case d).
Changed this
return view('content.show')->with(['name' => $data4page]);
To:-
return view('content.show')->with(compact('data4page'));
Hope it hepls!
Why have you resorted to typing the variable name with the wrong case when the answers given below are absolutely fine? PHP variables are case sensitive. You're passing $Data4page to your view in the code you've shown and then trying to use the access $data4page. Any of the below will work.
return view('content.show', ['data4page' => $data4page]);
return view('content.show', compact('data4page'));
return view('content.show')->with('data4page', $data4page);
return view('content.show')->with(['data4page' => $data4page]);
return view('content.show')->with(compact('data4page'));
You need to loop through the collection to get the value
#section('content')
<div class="app-template">
<main class="wrapperMain">
#foreach ($data4page as $d4p)
<div class="">
<aside class="navSidebar">
<nav class="navProperty">
<h1 class="navProperty-title">{{ $d4p->h1Ttle }}</h1>
</nav>
<footer class="footerProperty">
<div class="upcomingSchedule">
<h4 class="upcomingSchedule-heading">{{ $d4p->h4Ttle }}</h4>
</div>
</footer>
</aside>
</div>
<div class="content content--withSidebar">
<div class="lead--Home">
<p>{{ $d4p->description }}</p>
</div>
</div>
#endforeach
</main>
#endsection

Laravel:Passing variable from controller to view

chatcontroller.php function returns variable to view:
public function getChat()
{
$message = chat_messages::all();
return View::make('home',compact($message));
}
this is my route:
Route::get('/getChat', array('as' => 'getChat','uses' => 'ChatController#getChat'));
this is my home.blade.php:
#extends('layouts.main')
#section('content')
<div class="container">
<h2>Welcome to Home Page!</h2>
<p> <a href="{{ URL::to('/logout') }}" > Logout </a></p>
<h1>Hello <span id="username">{{ Auth::user()->username }} </span>!</h1>
<div id="chat_window">
</div>
<input type="text" name="chat" class="typer" id="text" autofocus="true" onblur="notTyping()">
</div>
<ul>
#foreach($message as $msg)
<li>
{{ $msg['sender_username']," says: ",$msg['message'],"<br/>" }}
</li>
#endforeach
</ul>
<script src="{{ asset('js/jquery-2.1.3.min.js') }}"></script>
<script src="{{ asset('js/chat.js') }}"></script>
#stop
I am trying to send result returned by select query to view from controller.
when I do this from homecontroller.php then it works fine.
if I try to pass from controller which I have defined it gives error message as:Undefined variable.
I have used the extends \BaseController do i need to do anything else to access my controller variable from view.
please suggest some tutorial if possible for same.
Verify the route to be sure it uses the new controller:
Route::get('user/profile', array('uses' => 'MyDefinedController#showProfile'));
First of all check your routes, as Matei Mihai says.
There are two different ways to pass data into your view;
$items = Item::all();
// Option 1
return View::make('item.index', compact('items'));
// Option 2
return View::make('item.index')->with('items', $items); // same code as below
// Option 3
View::share('item.index', compact('items'));
return View::make('item.index);
You can also do this:
$this->data['items'] = Item::all();
return View::make('item.index', $this->data);

Resources