i want to list all the images for each project, i tried to do it like this, but it always return 1 image only.
public function home()
{
$projects = Project::all(); //result : 1
foreach($projects as $project){
$images = $project->images()->get();
// dd($images); //result : 4
foreach($images as $image){
return '<img src="'.$image->image_path.'">';
}
}
}
the code above is just for test purpose, what i want to do is to display it in a table, something like this in my controller :
<tbody>
'
$images = $project->images()->get();
foreach($images as $image){
'
<tr>
<td><img src="'.$image->image_path.'"></td>
</tr>
'
}
'
</tbody>
Since a function can only return once, you probably need to do something different on the inner foreach like concatenating the image html to an existing string.
That said, the right way to do this would generally be to return $images to be used directly in a template where you would build out the html.
I'm not sure what all is going on here, but it looks like you want to do something that is relatively simple in Laravel if you are able to use Controllers and Blade Templates.
First, you start with your controller (keep all of your application logic there):
// ProjectController.php
public function home()
{
//-- grab all the projects, with all of their images
// Using with() will allow you to eager load those images
// from the database if they are Eloquent relationships.
$projects = Project::with('images')->get();
//-- send those $projects to your view
// Using with() here will send that variable to your
// view accessible by the key.
return view('projects')->with(['projects' => $projects]);
}
Then, in your blade template, you can easily iterate over the projects and images:
// views/projects.blade.php
#foreach($projects as $project)
<table>
...
<tbody>
#foreach($project->images as $image)
<tr>
<td><img src="{{ $image->image_path }}"></td>
</tr>
#endforeach
</tbody>
...
</table>
#endforeach
</tbody>
Hope this helps. If none of this makes sense, you can always check out the docs, they are really well written!
Laravel Docs
Be sure to check out the Controllers, Blade Templates and Eloquent ORM - Relationships sections :)
Related
I cannot wrap my mind around something.
I have a table which I render in my tables.blade.php file like this:
<table>
<thead>
<tr>
<th scope="col">Country</th>
<th scope="col">Member</th>
</tr>
</thead>
<tbody>
#foreach ($members as $member)
#if ($member->continent == 'Europe')
<tr>
<td>
{{ $member->country }}
</td>
<td class="align-middle player-code copy-code">
{{ $member->name }}
</td>
</tr>
#endif
#endforeach
</tbody>
</table>
As you can see you can click on a country which will show you members from one country in a new view (code not shown here).
The route for that single country site in the web.php looks like this:
Route::get('/{country}', 'PageController#show')->name('country');
Everything worked fine until I realized that I could put anything as 'country' and still would get shown the site for the country just with an empty table.
So '/abcde' would get you the view with just a naked table.
So I changed the route like this:
Route::get('/{country}', 'PageController#show')->name('country')->where('country', ('United Kingdom|France|Belgium|South Africa);
//the list is much longer
Ok. So now I have constrained the 'country'-parameter in a pretty static way. And I have the feeling that is not the way it should be done. Because in the end I would like to have URLS that look like this '/united-kingdom', '/france', but now they're looking like this '/United%20Kingdom'.
I saw the answers to this question Laravel clean links without spaces or uppercase , but for me they're not so useful since I'm not working with Eloquent models but the Query Builder (The db tables I get are ready made, I only have to display them).
So my questions are:
How to limit a route parameter more dynamically?
How to display data one way (written like it's also in the table like this 'United Kingdom'), but have a route like this ('united-kingdom')?
I am willing to provide more code or info if you need, I'm just pretty confused and have the feeling I'm overlooking something (big).
Thank you for your time and help!
If you would like a route parameter to always be constrained by a
given regular expression, you may use the pattern method. You should
define these patterns in the boot method of your RouteServiceProvider:
use Illuminate\Support\Facades\DB;
//...
/**
* Define your route model bindings, pattern filters, etc.
*
* #return void
*/
public function boot()
{
$list_of_countries = DB::table('members')->whereNotNull('country')->pluck("country")->unique()->map(function ($name) {
return str_slug($name, '-');
})->reject(function ($name) {
return empty($name);
})->toArray();
$regex = '(' . implode('|', $list_of_countries) . ')';
Route::pattern('{country-slug}', $regex);
parent::boot();
}
routes\web.php
Route::get('/{country-slug}', 'PageController#show')->name('country');
Docs
I'm working on updating a laravel blade template to insert some database info into an html table. IN order to do this, I'm having to add new data to the controller for this blade and that's where I'm having some troubles.
I'm still trying to understand more with laravel, so I'm thinking my syntax or methods of creating this data are incorrect but I just can't put my finger on it right now.
In my function below, the $calls_allowed portion was already existing and it works on the page currently. I created the $contact_events portion of the function and that's where my problem is.
IN my view, I created a foreach loop and if statement around the html table in question. The table loads, but it's empty even though there are records in the database for the dealer.
I'm trying to say
if $dealer-> id matches contact_events.dealer_num, load all records for that dealer
contact_events is the table and dealer_num is the column I'm matching, then I'm trying to load the columns from that table (updated_at,method,notes) into the html table.
The affected code is below. The view/route/controller work, it's just this function I'm creating that isn't loading data. Any help is much appreciated.
Controller code:
public function show($id)
{
$d = Dealer::find($id);
if(!$d){
\Session::flash('warning_message', 'Sorry that resource can not be found.');
return redirect()->route('account.dealer.index');
}
$calls_allowed = DB::table('dealers.dealers')->
where('dealer_num', $id)->
pluck('calls_allowed');
$contact_events = DB::table('dealers.contact_events')->
where('dealer_num', $id)->
pluck('updated_at', 'method', 'notes');
if(!empty($calls_allowed)){
$d->calls_allowed = $calls_allowed[0];
} else {
$d->calls_allowed = null;
}
return view('Account.Dealer.show')->with('dealer', $d);
}
View code:
<thead>
<tr>
<th>Contacted Date</th>
<th>Type of Contact</th>
<th>Call Notes</th>
</tr>
</thead>
#foreach($dealer->contact_events as $events)
#if($events->dealer_num = $dealer->id)
<tbody>
<tr>
<td>{{$events->updated_at}}</td>
<td>{{$events->method}}</td>
<td>{{$events->notes}}</td>
</tr>
</tbody>
#endif
#endForeach
It looks like you are not assigning the data to the object after retrieving from database.
$contact_events = DB::table('dealers.contact_events')->
where('dealer_num', $id)->
pluck('updated_at', 'method', 'notes');
// add this
$d->contact_events = $contact_events;
This seems like a perfect time to use the power of Laravel's Eloquent ORM...
Check out the with and has in the Laravel docs
This will require some finessing based on your needs, but it will be something like this:
$d = Dealer::where('id', '=', $id)
->with('contact_events')->first();
This uses Eloquent to get all of the contact_events that belong to the dealer with the $id.
Then you can do something like this
note: this assumes that calls_allowed is a record on the dealer table. if I misunderstood that, you can still run than you can include that just as you have it.
#if(!is_null($dealer->calls_allowed)
#foreach($dealer->contact_events as $events)
<tbody>
<tr>
<td>{{$events->updated_at}}</td>
<td>{{$events->method}}</td>
<td>{{$events->notes}}</td>
</tr>
</tbody>
#endForeach
#endif
On my website, users can upload images and attach tags to those images.
I've got an images table,a tag table and an images_tag pivot table.
Images can have many tags, and tags can belong to many images.
I want to be able to generate a list of all the tags a user has used in his/her images.
$imageIDs = Images::where('created_by', Auth::user()->id)->lists('id');
So this would create a list of all the image IDs that a user has upload.
What I want is essentially "foreach $imageIDs, check the images_tag table and for every match go to the tags table and get me back the tagname value."
But I have no idea how I'd do that.
Maybe a foreach then use the merge method on all the results? Any help would be appreciated!
You need to use whereHas() to check the relationship:
$userTags = Tags::whereHas('images', function($q) {
$q->where('created_by', auth()->user()->id);
})->get();
Then just pass this data to a view:
return view('some.view', compact('userTags'));
And iterate over tags in a view:
#foreach ($userTags as $tag)
{{ $tag->name }}
#endforeach
What you could do is this.
class Tag extends Model
{
public function images()
{
return $this->belongsToMany(Image::class);
}
}
class SomeController
{
public function someMethod()
{
$tags = Tag::with(['images' => function ($image) {
return $image->where('created_by', Auth::user()->id);
}])->select('id', 'tagname')->get();
// these are your $tags
}
}
You should not use a query inside foreach(). Then it would result N+1 problem. What you instead do is eager loading using with() statement.
I have a typical model relation. I have the model QR, which hasMany Rating, and a Model Rating, which belongsTo Qr.
Now I want to output the Ratings, which belong to a single qr model, through a foreach loop like this:
<table>
<tr>
<th>ID</th>
<th>UnitID</th>
<th># of Ratings</th>
</tr>
#foreach($qrs as $qr->ratings)
<tr>
<td>{{$qr->id}}</td>
<td>{{$qr->unit_id}}</td>
<td>{{$qr->ratings->count()}}</td>
</tr>
#endforeach
</table>
This is my Controller:
public function index()
{
//
$unit = Unit::all()->first();
$qrs = Qr::all()->first();
return View::make('index')
->with('unit', $unit)
->with('qrs', $qrs);
}
Here are my two Models
Rating.php:
class Rating extends \Eloquent {
protected $guarded = [];
public function qr(){
return $this->belongsTo('Qr');
}
}
Qr.php:
class Qr extends \Eloquent {
protected $guarded = [];
public function unit(){
return $this->belongsTo('Unit');
}
public function ratings(){
return $this->hasMany('Rating');
}
}
I actually want to output the count of ratings, a Qr-Code has. I know it is possible to do it somehow like this:
{{Rating::where('qr_id', $qr->id)->count()}}
But I want to do it somehow like this in the foreach loop
{{ $Qr->rating->count() }}
If this is somehow possible.
I get the relation, if I just output the first() of Qr and then
var_dump($qrs->ratings->toArray())
But I don't know how to get the count Number of ratings in combination with the foreach loop. Any help would be dearly appreciated.
Couple of things wrong here:
// view:
#foreach($qrs as $qr->rating)
// should be:
#foreach($qrs as $qr)
// controller:
$unit = Unit::all()->first();
$qrs = Qr::all()->first();
// this way you get all Units then fetch first Unit from the collection,
// the same with Qrs, so change it to:
$unit = Unit::all(); // do you need it at all?
$qrs = Qr::with('ratings')->get();
This will solve the problem and in the foreach loop you will be able to access $qr->ratings->count() which will be Collection method.
At first you have used this:
#foreach($qrs as $qr->ratings)
You need to change it to this (as already stated in an answer):
#foreach($qrs as $qr)
Then in your index method you have used this:
public function index()
{
$unit = Unit::all()->first();
$qrs = Qr::all()->first();
return View::make('index')->with('unit', $unit)->with('qrs', $qrs);
}
In this case you need to get a collection of QR models and since Unit and Rating are related to Qr then you may use with and get() to get a collection of QR models like this:
public function index()
{
$qrs = Qr::with(array('unit', 'ratings'))->get();
return View::make('index')->with('qrs', $qrs);
}
Then you'll be able to loop the Qr models in your view like this:
#foreach($qrs as $qr)
<tr>
<td>{{ $qr->id }}</td>
<td>{{ $qr->unit_id }}</td>
<td>{{ $qr->ratings->count() }}</td>
</tr>
#endforeach
I'm attempting to load all of the items in my Lists database, while applying optional filters if they're specified. With these, I'd like to load the count of subscribers for each of the lists. I can do this via the normal $list->subscribers()->count() call within the foreach loop in the view, but can I do this through the actual pagination function?
Inside of my ListsRepo.php file:
<?php namespace Acme\Repos;
use Lists;
class DbListsRepo implements ListsRepoInterface {
public function getPaginated(array $params)
{
$list = new Lists;
// See if there are any search results that need to be accounted for
if ($params['search'] != null) $list = $list->where('name', 'LIKE', "%".$params['search']."%");
// See if we need to restrict the results to a single user
if ($params['user'] != null) $list = $list->where('userID', $params['user']);
// Check if the data should be sorted
if ($this->isSortable($params)) $list = $list->orderBy($params['sortBy'], $params['direction']);
return $list->paginate(10);
}
public function isSortable(array $params)
{
return $params['sortBy'] and $params['direction'];
}
}
Inside of my index.blade.php file:
....
#if ($lists->count())
#foreach ($lists as $list)
<tr>
<td><h4>{{ $list->name }}</h4></td>
<td><p>{{ $list->subscribers()->count() }}</p></td>
</tr>
#endforeach
#endif
...
So is there a way to properly attach the subscribers count to my getPaginated function? The current implementation results in an N+1 scenario.
You should be able to do it by including the eager-load in your getPaginated function:
public function getPaginated(array $params) {
$list = Lists::newQuery();
// See if there are any search results that need to be accounted for
if ($params['search'] != null) $list->where('name', 'LIKE', "%".$params['search']."%");
// See if we need to restrict the results to a single user
if ($params['user'] != null) $list->where('userID', $params['user']);
// Check if the data should be sorted
if ($this->isSortable($params)) $list->orderBy($params['sortBy'], $params['direction']);
$list->with('subscribers');
return $list->paginate(10);
}
And then in your blade you can simply do count($list->subscribers) because the subscribers will be preloaded into your list models.
You have to use PHP's count() on the results array, not SQL's COUNT when it comes to eager loading, as eager loading is done with a single select statement on the related table.