So I'm currently practicing with Laravel, and running into a problem where the sql query is reading everything from my second table as an array, rather than the column it should be assigned to.
I have a packages table, and a resources table to fill those packages. Package name and price work fine, but when I need to read from resources, I get this:
[{"id":2,"resource":"Vegetarian menu","package_id":2,"created_at":"2022-06-18T19:34:48.000000Z","updated_at":"2022-06-18T19:34:48.000000Z"},{"id":3,"resource":"Standard Menu","package_id":2,"created_at":"2022-06-18T19:35:31.000000Z","updated_at":"2022-06-18T19:35:31.000000Z"}]
When it really should be just "Vegetarian menu", and "Standard Menu"
What am I doing wrong?
//package model
class Package extends Model { use HasFactory;
protected $fillable = ['name'];
public function resources()
{
return $this->hasMany(Resource::class);
} }
//package controller
class PackageController extends Controller {public function index(){
// SELECT * FROM packages
$packages = Package::with('resources')->get();
return view('service', compact('packages')); } }
//resource model
class Resource extends Model {
use HasFactory;
protected $fillable = ['package_id', 'resource'];
public function package()
{
return $this->belongsTo(Package::class);
} }
// UI Page
#foreach ($packages as $package)
<div class="tile is-parent"><!-- each child tile needs it's own parent -->
<article class="tile is-child box has-text-centered">
<figure class="image is-96x96 is-inline-block">
<img class="is-rounded" src="https://bulma.io/images/placeholders/96x96.png" alt="">
</figure>
<p class="subtitle has-text-centered">{{ $package->name }}</p>
<h4 class="is-size-5 has-text-centered">£{{ number_format($package->cost) }}.00</h4>
<div class="content">
<ul>
<li>{{ $package->resources }}</li>
</ul>
</div><!-- content -->
</article>
</div><!-- parent -->
#endforeach
You are correctly getting what you are requesting. A collection of resources associated with every package.
[
{
"id":2,
"resource":"Vegetarian menu",
"package_id":2,
"created_at":"2022-06-18T19:34:48.000000Z",
"updated_at":"2022-06-18T19:34:48.000000Z"
},
{
"id":3,
"resource":"Standard Menu",
"package_id":2,
"created_at":"2022-06-18T19:35:31.000000Z",
"updated_at":"2022-06-18T19:35:31.000000Z"
}
]
If you want to limit the fields on the resource relation then you should modify your query as
class PackageController extends Controller {
public function index(){
// SELECT * FROM packages eager loads resource name and package_id
$packages = Package::with('resources:resource,package_id')->get();
return view('service', compact('packages'));
}
}
you just need to loop through the related collection
#foreach ($packages as $package)
<div class="tile is-parent"><!-- each child tile needs it's own parent -->
<article class="tile is-child box has-text-centered">
<figure class="image is-96x96 is-inline-block">
<img class="is-rounded" src="https://bulma.io/images/placeholders/96x96.png" alt="">
</figure>
<p class="subtitle has-text-centered">{{ $package->name }}</p>
<h4 class="is-size-5 has-text-centered">£{{ number_format($package->cost) }}.00</h4>
<div class="content">
<ul>
#foreach ($package->resources as $r)
<li>{{ $r->resource }}</li>
#endforeach
</ul>
</div><!-- content -->
</article>
</div><!-- parent -->
#endforeach
Related
my questions may be a bit of a beginner, but please be patient, thank you
I want to display the projects related to each category in the following code in the second foreach, but now all the projects are displayed
view
#foreach($categories as $category)
<div id="section-{{ $category->id }}" class="section">
<h3 class="fnt_gh fnt-color">{{ $category->category_project }}</h3>
<div class="bigBox">
<div class="container1">
#foreach($projects as $project)
<article class="barghabi">
<a href="#" data-cat="news" data-state="vic">
<img src="{{ $project->image_project }}" alt="">
<h6 class="fnt_gh" style="line-height: normal;">
{{ $project->title_project }}
</h6>
</a>
</article>
#endforeach
<div class="content"></div>
</div>
</div>
</div>
#endforeach
And a categories table and a project table whose models and relationships are as follows:
class Project extends Model
{
protected $fillable = [
'title_project' ,
'period_project' ,
'description_project' ,
'manager_project' ,
'phone_project' ,
'email_project' ,
'image_project'
];
public function categories()
{
return $this->belongsToMany(Category::class);
}
}
class Category extends Model
{
protected $fillable = ['category_project' , 'icon_project'];
public function projects()
{
return $this->belongsToMany(Project::class);
}
}
and pivot :
Schema::create('category_project', function (Blueprint $table) {
$table->unsignedBigInteger('category_id');
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->unsignedBigInteger('project_id');
$table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade');
$table->primary(['category_id' , 'project_id']);
$table->timestamps();
});
controller:
class ProjectController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function index()
{
$categories = Category::all();
$projects = Project::all();
return view('home.fa.pages.project.index', compact('categories' , 'projects' ));
}
}
You are calling #foreach($projects as $project) within your loop. You've defined $projects as all projects. Instead, use #foreach($category->projects as $project).
#foreach($categories as $category)
<div id="section-{{ $category->id }}" class="section">
<h3 class="fnt_gh fnt-color">{{ $category->category_project }}</h3>
<div class="bigBox">
<div class="container1">
#foreach($category->projects as $project)
<article class="barghabi">
<a href="#" data-cat="news" data-state="vic">
<img src="{{ $project->image_project }}" alt="">
<h6 class="fnt_gh" style="line-height: normal;">
{{ $project->title_project }}
</h6>
</a>
</article>
#endforeach
<div class="content"></div>
</div>
</div>
</div>
#endforeach
I'm not sure what's in $category->category_project but having a property with the same name as your pivot table is bound to create confusion. You should keep column names simple and readable, not append _project to each one!
I'm fetching data from Ajax after sending a form. There is a listener that is setting the attribute to my component.
What I'm trying to achieve is to display my results after having submitted the form.
In the component, the model has been well retrieved but when I would like to display it to my component, I get an error.
directive_manager.js:26 Uncaught (in promise) TypeError: Cannot read property 'getAttributeNames' of null
at _default.value (directive_manager.js:26)
at new _default (directive_manager.js:6)
at new DOMElement (dom_element.js:12)
at Function.value (dom.js:36)
at Component.get (index.js:56)
at Component.value (index.js:272)
at Component.value (index.js:246)
at Component.value (index.js:182)
at Component.value (index.js:158)
at Connection.value (index.js:30)
index.blade.php
<div id="results-products" class="results-products">
<livewire:charts-products>
</div>
....
<script>
...
var product= fetchData(url);
window.livewire.emit('set:product', product)
...
</script>
charts-products.blade.php
<div>
#isset($product)
#foreach ( $product->category as $category)
<div class="card">
<div class="card-header">
<h4>Product category</h4>
</div>
</div>
#endforeach
#endisset
</div>
ChartsProducts.php
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use App\Models\Product;
class ChartsProducts extends Component
{
public $products;
protected $listeners = [
'set:product' => 'setProduct'
];
public function render()
{
return view('livewire.charts-products');
}
public function setProduct($product)
{
$this->product= Product::find($product);
//I have checked and the assigned variable is ok
}
}
The products is a model and has a relationship Category.
Is there something that I missed ?
This has to do with the way the dom-differ inside Livewire behaves. Try adding a key to the loop item
<div>
#isset($product)
#foreach ($product->category as $category)
<div class="card" wire:key="{{ $loop->index }}">
<div class="card-header">
<h4>Product category</h4>
</div>
</div>
#endforeach
#endisset
</div>
See the troubleshooting in the docs https://laravel-livewire.com/docs/troubleshooting
Also, change your public property from $products to $product
I asked this question before but didnt get any answer,hope you have the solution.
As I have 2 tables, items and categories so every item has one category and one category can have many items.
my problem is when using groupby function but it shows one item for every category
item model:
class Item extends Model
{
protected $table="items";
protected $fillable=
['item_title','category_id','item_price','item_details','item_image'];
protected $primaryKey='item_id';
public $timestamps=false;
public function categories()
{
$this->hasOne('App\category','category_id','category_id');
}
}
category model
class Category extends Model
{
protected $table="categories";
protected $fillable=['category_name'];
protected $primaryKey='category_id';
public $timestamps=false;
public function items()
{
$this->hasMany('App\items','category_id','category_id');
}
}
Controller
class HomeController extends Controller
{
public function getItems()
{
$items = Item::groupBy('category_id')->get();
return view('home',compact('items'));
}
}
HTML
#foreach($items as $indexKey => $item)
<div class="MenuPage_contentArea">
<div class="Category_root" id="one">
<div class="Category_categoryHeader">
<div><h2 class="Category_name">{{$item->item_category}}</h2></div>
<div class="Category_description"></div>
</div>
<div class="Category_itemsContainer">
<div class="Category_itemContainer">
<button class="Item_root Button_root">
<div class="Item_image" style="background-image: url('{{ asset('images/' . $item->item_image) }}');"></div>
<div class="Item_itemContent">
<div class="Item_topSection">
<span class="Item_name">{{$item->item_title}}</span>
<span class="Item_price">${{$item->item_price}}</span></div>
<div class="Item_description">{{$item->item_details}}</div>
</div>
</button>
</div>
</div>
</div>
</div>
#endforeach
You are grouping at SQL level, but if you want all of the items in a category grouped in a Collection, then use groupBy method from Collection. Use all()
method to get a collection of all items, then use groupBy() method to group the items by category_id:
HOME CONTROLLER
class HomeController extends Controller
{
public function getItems()
{
$items = Item::all()->groupBy('category_id');
return view('home',compact('items'));
}
}
Access in your blade File as:
#foreach($items as $category_id => $categoryItems)
Category ID: {{ $category_id }} <br>
#foreach($categoryItems as $item)
<!-- Display Item Details Here -->
#endforeach
#endforeach
Hope it helps you. :)
I have tried asking this question to everyone but nobody can see why I am trying to do it or why its not working but I will try my best to explain it properly this time.
I have a simple government page on my website that shows 3 panels in bootstrap with Higher Government, Senior Ministers and Junior Ministers. Inside each of them panels it shows a list of accounts assigned to that government rank.
Here is my government.blade.php:
#include('frontend.header')
<div class="col-md-12" style="padding-bottom:24px;">
<ul class="nav navtab nav-tabs" id="myTab" style="border-bottom:none;border-radius:1px;">
<li style="padding-right:13px;" class="active"><a style="" data-target="#higher_government_team" data-toggle="tab"><i class="fa fa-diamond" aria-hidden="true"></i> The Monarch/PM</a></li>
<li style="padding-right:13px;"><a style="" data-target="#senior_government_team" data-toggle="tab"><i class="fa fa-university"></i> Seniors</a></li>
<li style="padding-right:13px;"><a style="" data-target="#junior_government_team" data-toggle="tab"><i class="fa fa-university"></i> Juniors</a></li>
</ul>
</div>
<div class="col-md-8">
<div class="tab-content">
<div class="tab-pane active" id="higher_government_team">
<div class="panel panel-info">
<div class="panel panel-body">
higher gov here
</div>
</div>
</div>
<div class="tab-pane" id="senior_government_team">
<div class="panel panel-info">
<div class="panel panel-body">
senior gov here
</div>
</div>
</div>
<div class="tab-pane" id="junior_government_team">
<div class="panel panel-info">
<div class="panel panel-body">
#foreach ($juniorGovernment as $governmentMember)
{{ $governmentMember->user_id }}<br>
#endforeach
</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
</div>
</div>
#include('frontend.footer')
Here is my controller for displaying the page:
<?php
namespace App\Http\Controllers\Frontend\User;
use Auth;
use Cache;
use Illuminate\Http\Request;
use App\Database\Website\User\Roleplay;
use App\Database\Website\Roleplay\GovernmentRole;
use App\Database\Website\Roleplay\Life\LifeEvents;
class GovernmentController
{
public function getView()
{
$higherGovernment = Cache::remember('government.higher_government', 1, function() {
return GovernmentRole::where('government_type', 'higher_government')->first()->stats;
});
$seniorGovernment = Cache::remember('government.senior_government', 1, function() {
return GovernmentRole::where('government_type', 'senior_ministers')->first()->stats;
});
$juniorGovernment = Cache::remember('government.junior_government', 1, function() {
return GovernmentRole::where('government_type', 'junior_ministers')->first()->stats;
});
return view('frontend.community.government', compact('juniorGovernment', 'seniorGovernment', 'higherGovernment', 'royalty'));
}
}
Now as you can see, I only select the first record where government_type matches. But the issue is I have multiple government roles with that government type and I want to get all the account stats for all records with that government type. I have looked at others suggestions and none of them work, either throwing an error or don't do what I want to do.
Now, I have modals for each Roleplay and GovernmentRoles, I have posted them both below.
GovernmentRole:
namespace App\Database\Website\Roleplay;
use Eloquent;
class GovernmentRole extends Eloquent
{
protected $primaryKey = 'id';
protected $table = 'srp_government_roles';
public $timestamps = false;
protected $fillable = [];
public function stats(){
return $this->hasMany('App\Database\Website\User\Roleplay', 'government_id');
}
}
Roleplay:
use Eloquent;
class Roleplay extends Eloquent
{
protected $primaryKey = 'id';
protected $table = 'srp_user_statistics';
public $timestamps = false;
protected $fillable = [];
public function user()
{
return $this->belongsTo('App\Database\Website\User\Player', 'user_id', 'id');
}
public function government_role()
{
return $this->belongsTo('App\Database\Website\Roleplay\GovernmentRole', 'government_id');
}
}
So what I am trying to achieve is not just grabbing all the Roleplay instances for the FIRST government role record in the database it finds but putting together ALL roleplay instances for ALL records that match government_type either higher_government, senior_ministers, or junior_ministers.
If I understand what you are asking, can you not do something like fetching the stats on your loop through in blade? For example (I removed the cache, its adding complexity to the question/answer without any benefit):
// controller
$higherGovernment = GovernmentRole::where('government_type', 'higher_government')->get();
// blade
#foreach($higherGovernment as $g)
{{ $g->id }}
{{ $g->name }}
#foreach($g->stats as $stat)
{{ $stat->id }}
{{ $stat->something }}
#endforeach
#endforeach
I'm new to laravel and trying to understand correctly how to show in my view my picture of my relations.
For example I have a table for Category, Post, User, and Image, and I need some help with this.
For my DB it's OK with Image table like tutorial polymorphic relation on laravel docs.(same like doc)
In my models image I have my polymorphic relation and it's all OK
class Image extends \Eloquent {
protected $guarded = ['id' , 'created_at'];
public function imageable(){
return $this->morphTo();;
}
}
I need to associate a image on my different category
class Category extends \Eloquent {
protected $guarded = ['id' , 'created_at'];
public function posts(){
return $this->hasMany('Post');
}
public function images(){
return $this->morphMany('Image','imageable');
}
public function parent(){
return $this->belongsTo('Category','parent_id');
}
public function children(){
return $this->hasMany('Category','parent_id');
}
public function getImportantPost(){
return $this->hasOne('Post')->latest();
}
public function latestPost(){
return $this->hasOne('Post')->latest();
}
}
After that in my homecontroller for my home page I have a request for 1 particular post to show with a specific category
//show headliner post specific category
$headliner = Category::with(['posts' => function($query){
$query->orderBy('published_at', 'DESC')->take(1)->get();
}])->where('id' , '=' , '5')->get();
In my home index view I have a foreach $headliner like this
<div class="widget-area-4">
<div class="widget kopa-article-list-widget">
<ul class="clearfix">
#foreach($headliner as $headline)
<li>
<article class="entry-item clearfix">
<div class="entry-thumb">
<img src="{{$headline}}" alt="" />
<span class="category-title">{{$headline->name}}</span>
</div>
<!-- entry-thumb -->
<div class="entry-content">
<header>
<h5 class="entry-title">{{$headline->latestPost->name}}</h5>
<span class="entry-date"><i class="fa fa-calendar"></i> {{$headline->latestPost->published_at}}</span>
<span class="entry-categories">Auteur: </span>
<span class="entry-comments">{{$headline->latestPost->counts_comments}}<span></span></span>
</header>
<p>{{str_limit($headline->latestPost->content, 600 ,' ...' )}}</p>
<a class="more-link" href="#">Voir plus</a>
</div>
<!-- entry-content -->
</article>
<!-- entry-item -->
</li>
#endforeach
</ul>
</div>
<!-- kopa-article-list-widget -->
</div>
But I don't know how to show my image in my foreach because I have my post associated to category so it's OK but when I try to
{{$headline->images->path}}
(path is my entries in my DB) I have a error.
Thanks for your help.
As you've used morphMany() to define images relation for a category, loading this relation will give you a collection of Image objects. Therefore in your view $headline->images refers to this collection, not a single image. Collection does not have a path attribute, hence the error.
You'll need to iterate through your images collection in the view and then render each image separately, e.g.:
#foreach($headline->images as $image)
<img src="{{ $image->path }}" />
#endforeach