Trying to get column data from pivot table laravel - php

Hi I'm trying to output a certain column from my pivot table. To show you what I have tried, I will first show you my models (my pivot tables are ordertasks and tagtasks):
Task table:
class Task extends \Eloquent {
// Add your validation rules here
public static $rules = [
// 'title' => 'required'
];
// Don't forget to fill this array
protected $fillable = ['task_name','task_description','hour','difficulty'];
public function ordertask()
{
//oneToMany
return $this->hasMany('Ordertask', 'id_task', 'id');
}
public function tagtask()
{
//oneToMany
return $this->hasMany('Tagtask', 'id_task', 'id');
}
}
Tagtask table:
<?php
class Tagtask extends \Eloquent {
protected $fillable = ['id_tag','id_task'];
public function task()
{
//manyToOne
return $this->belongsTo('Task', 'id_task', 'id');
//return $this->belongsTo('Task');
}
public function tag()
{
//manyToOne
return $this->belongsTo('Tag', 'id_tag', 'id');
}
}
Ordertask table:
<?php
class Ordertask extends \Eloquent {
// Add your validation rules here
public static $rules = [
// 'title' => 'required'
];
// Don't forget to fill this array
protected $fillable = ['id_order','id_task', 'hour', 'hourprice','id_user', 'createdBy'];
public function user()
{
//manyToOne
return $this->belongsTo('User', 'id_user', 'id');
//return $this->belongsTo('User');
}
public function task()
{
//manyToOne
return $this->belongsTo('Task', 'id_task', 'id');
//return $this->belongsTo('Task');
}
}
Here is my TaskController.php with the following piece of code:
public function index()
{
$Tasks=Task::with('tagtask','ordertask')->get();
return View::make('user.tasks.index', compact('Tasks'));
}
Okay now comes the part where I want to show $Task->ordertask['id_user'] on my browser with the following piece of code:
#if (count($Tasks))
<ul>
#foreach($Tasks as $Task)
<div class="row">
<div class="col-md-3">
<li>
{{--as a third parameter we need to pass in the id of task, because it needs to be fed to
our actual user.task.edit route. --}}
{{link_to_route('user.tasks.edit', $Task['task_name'], array($Task->id))}}
</li>
</div>
<div class="col-md-3">
<li>
{{$Task->ordertask['id_user']}}
</li>
</div>
<div class="col-md-3">
<li>
{{$Task['task_hour']}}
</li>
</div>
<div class="col-md-3">
<li>
{{Form::open(array('route'=>array('user.tasks.destroy',$Task->id),
'method'=>'delete','class'=>'destroy'))}}
{{Form::submit('Delete')}}
{{Form::close()}}
</li>
</div>
</div>
#endforeach
</ul>
#endif
Unfortunately that doesn't work because I get the following error:
Undefined index: id_user
Instead of:
{{$Task->ordertask['id_user']}}
I have also tried this just to see what output it gave me:
{{$Task->ordertask}}
Which gave me the following output:
[{"id":5,"id_order":2,"id_task":1,"hour":63,"hourprice":15,"id_user":5,"createdBy":4,"created_at":"2014-10-13 10:21:33","updated_at":"2014-10-13 10:21:33"}]
So gladly I want to output id_user from the ordertask table. Gladly I'm waiting on your answer. Anyway thanks for your response.

One Task can have many order tasks, so to display users instead of
{{$Task->ordertask['id_user']}}
You should use:
#foreach ($Task->ordertask as $ot)
{{ $ot->id_user }}
#endforeach

Related

Can't display the values from my data base with Laravel Livewire

I'm using a Livewire component, this is my code:
Search.php :
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use App\Models\Recipe;
use App\Models\Vegetable;
use App\Models\VegetablesRecipe;
class Search extends Component
{
public $query = '';
public $vegetables;
public function mount()
{
$this->resetQuery();
}
public function resetQuery()
{
$this->vegetables = [];
}
public function render()
{
if ($this->query != null) {
return view('livewire.search', [
'vegetables' => Vegetable::where('name', 'like', '%'.$this->query.'%')->get()->toArray()
]);
} else {
return view('livewire.search', [
'vegetables' => Vegetable::all()->toArray()
]);
}
}
}
search.blade.php :
<div class="searchcomponent">
<h1>Search</h1>
<input wire:model="query" type="text" placeholder="Rechercher...">
#if(!empty($query))
<ul>
#if(!empty($vegetables))
<div class="vegetables">
#foreach($vegetables as $vegetable)
<li><span class="material-icons">lunch_dining</span>{{ $vegetable['name'] }}</li>
#endforeach
</div>
#else
<li>No result</li>
#endif
</ul>
#endif
</div>
My vegetable Model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Vegetable extends Model
{
use HasFactory;
public $timestamps = false;
protected $fillable = ['name'];
public function recipes(){
return $this->belongsToMany(Recipe::class, 'vegetables_recipes', 'vegetable_id', 'recipe_id');
}
public function getName($id) {
return $this->name;
}
}
My problem is, every time im typing something in my search bar, I just have a No result appearing on my screen even tho i seeded my data base with some vegetables already. Why doesn't it show me for example Carrot when i type it?
Or how can i fill my array vegetables with all the names of my vegetables datatable ?
Defining public $vegetables; will prevent you from passing it to the view.
Remove that. Also remove your mounting logic.
Thus you should have:
class Search extends Component
{
public $query = '';
public function render()
{
if ($this->query != null) {
return view('livewire.search', [
'vegetables' => Vegetable::where('name', 'like', '%'.$this->query.'%')->get()->toArray()
]);
} else {
return view('livewire.search', [
'vegetables' => Vegetable::all()->toArray()
]);
}
}
}
Also make sure you are calling #livewireScripts and #livewireStyles or their alternative syntaxes <livewire:styles /> <livewire:scripts /> from your main view which uses <livewire:search />.
Edit:
Alternatively, you could also use a public properly and write to it using $this->vegetables like so:
class Search extends Component
{
public $query = '';
public $vegetables;
public function render()
{
$this->vegetables = Vegetable::where('name', 'like', '%' . $this->query . '%')->get()->toArray();
return view('livewire.search');
}
}
Also, you can remove the #if(!empty($query)) and the #if(!empty($vegetables)) in place of a #forelse utilising the #empty statement rather than a #foreach. E.g.
#forelse($vegetables as $vegetable)
<li><span class="material-icons">lunch_dining</span>{{ $vegetable['name'] }}</li>
#empty
<li>No result</li>
#endforelse
That way, you will still get a list of your vegetables when the search box is empty, and if it's not empty but there's no matching results, you'll get your "No result" message.
This is because on the mount you are resetting the vegetable array to an empty array.
Refer to this fiddle for more details:
https://laravelplayground.com/#/snippets/f51e212a-dab3-4325-b6b0-4c6af4c0ab72

Problem with Laravel Livewire : Attempt to read property "recipes" on array

I'm trying to do a search input from 2 datatables of my database, one containing vegetables and the other one containing recipes made of vegetables, i first made my search input with only the elements from the vegetable table. But now im trying to include the repice table but it wont work: I'm getting the error "Attempt to read property "recipes" on array" but I do't understand where the problem comes from.
This is my code:
Search.php:
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use App\Models\Vegetable;
class Search extends Component
{
public $query = '';
public $vegetables;
public $recipes;
public function updatedQuery()
{
$this->vegetables = Vegetable::where('name', 'like', '%'.$this->query.'%')->get()->toArray();
}
public function render()
{
return view('livewire.search');
}
}
search.blade.php :
<div class="searchcomponent">
<h1>Recherche</h1>
<input wire:model="query" type="text" placeholder="Rechercher...">
#if(!empty($query))
<ul>
#if(!empty($vegetables))
<div class="vegetables">
#foreach($vegetables as $vegetable)
<li><span class="material-icons">lunch_dining</span>{{ $vegetable['name'] }}</li>
#endforeach
</div>
#else
<li>Pas de résultat</li>
#endif
<div class="recipes">
#foreach($vegetables as $vegetable)
#foreach($vegetable->recipes as $recipe)
<li><span class="material-icons">menu_book</span>{{ $recipe['name'] }}<span class="ingredient">Ingrédient: {{ $vegetable['name'] }}</span></li>
#endforeach
#endforeach
</div>
</ul>
#endif
</div>
My model Vegetable :
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Vegetable extends Model
{
use HasFactory;
public $timestamps = false;
protected $fillable = ['name'];
public function recipes(){
return $this->belongsToMany(Recipe::class, 'vegetables_recipes', 'vegetable_id', 'recipe_id');
}
public function getName($id) {
return $this->name;
}
}
My model Recipe :
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Recipe extends Model
{
use HasFactory;
public $timestamps = false;
protected $fillable = ['name'];
public function vegetables(){
return $this->hasOne(Vegetable::class, 'vegetables_recipes', 'recipe_id', 'vegetable_id');
}
public function getName($id) {
return $this->name;
}
}
The model from my pivot table VegetablesRecipe :
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class VegetablesRecipe extends Model
{
use HasFactory;
public $timestamps = false;
protected $fillable = ['vegetable_id', 'recipe_id'];
}
Thank you in advance
So I found the issue with your code; I didn't notice it yesterday as it was hidden off-screen in your Search.php's updatedQuery() function:
$this->vegetables = Vegetable::where('name', 'like', '%'.$this->query.'%')
->get()
->toArray();
When you call ->toArray(), you convert the Collection of Vegetable Model instances into an Array of Arrays. This means you cannot use Object Access to get Properties:
$vegetable->recipes; // Fails with error "Attempt to read property "recipes" on array"
Additionally, you cannot access any Model functions, as an Array is not an instance of a Model:
$vegetables['recipes']; // Undefined array key "recipes"
Since public function recipes() is a method of the Vegetable.php Model class, that won't work. It can work, if you load it first before casting to an Array:
$this->vegetables = Vegetable::where('name', 'like', '%'.$this->query.'%')
->with('recipes')
->get()
->toArray();
Now, $vegetable['recipes'] will work, but it's better to just drop the ->toArray() completely:
$this->vegetables = Vegetable::where('name', 'like', '%'.$this->query.'%')
->with('recipes')
->get();
Additionally, for performance reasons, you want to include ->with('recipes') to prevent N+1 queries being called while looping.
With those changes made, you can write your livewire/search.blade.php code as follows:
<div class="searchcomponent">
<h1>Recherche</h1>
<input wire:model="query" type="text" placeholder="Rechercher...">
#if(!empty($query))
<ul>
#if(!empty($vegetables))
<div class="vegetables">
#foreach($vegetables as $vegetable)
<li><span class="material-icons">lunch_dining</span>{{ $vegetable->name }}</li>
#endforeach
</div>
#else
<li>Pas de résultat</li>
#endif
<div class="recipes">
#foreach($vegetables as $vegetable)
#foreach($vegetable->recipes as $recipe)
<li><span class="material-icons">menu_book</span>{{ $recipe->name }}<span class="ingredient">Ingrédient: {{ $vegetable->name }}</span></li>
#endforeach
#endforeach
</div>
</ul>
#endif
</div>
Lastly, some cleanup:
Vegetable.php and Recipe.php
The methods getName($id) have no purpose; you're not doing anything with $id, and name is not a private property; you can simply do $vegetable->name or $recipe->name and it will do the same as what these methods are doing.
Recipe.php
As stated in the comments, belongsToMany() is the inverse of belongsToMany(), not hasOne():
public function vegetables(){
return $this->belongsToMany(Vegetable::class, 'vegetables_recipes');
}
Additionally, if the primary and foreign key names match the model names, you don't need them. The proper name for the pivot table would be recipes_vegetables (plural, alphabetical), so specifying that is required. You can do the same for Vegetable.php:
public function recipes(){
return $this->belongsToMany(Recipe::class, 'vegetables_recipes');
}
Lastly, your model VegetablesRecipe.php is not needed, and is currently not being used. You typically don't define a Model for a Pivot table, so you can either remove it, or keep it around should you ever need to directly modify the Pivot.

Get users name from table Laravel

I want to display user name from users table. I get article information for example {{$article->title}}
but i doesnt get users info.
Model Article
protected $fillable = ['title','slug','description_short','description','image_path','meta_title',
'meta_description','meta_keyword','published', 'created_by', 'modified_by','author_id'];
public function user(){
return $this->belongsTo(User::class);
}
Model User
protected $fillable = [
'id', 'name', 'email', 'password', 'role_id'
];
public function articles(){
return $this->hasMany('App\Article');
}
index.blade.php
#forelse ($articles as $article)
<tr>
#foreach($article as $userss)
<?php var_dump($userss) ?>
<div class="display-commentttt">
#if (isset($userss->users->name))
<?php var_dump($userss->users->name); ?>
<div class="user-login">{{ $userss->user->name }}
</div>
#elseif (isset($userss->users->id))
<?php var_dump($userss->users->name); ?>
<div class="user-login">{{ $userss->users->id }}
</div>
#endif
#endforeach
<td>{{$article->title}}</td>
<td>{{$article->published}}</td>
#endforelse
In my article Controler
public function index(){
return view('admin.articles.index',[
'articles' => Article::with(['user'])->orderBy('created_at', 'desc')->paginate(10),
]);
}
This is easily possible by Eloquent. In your Article model rename your function users() to user();
public function user(){
return $this->belongsTo(User::class);
}
then go to your controller's method and get article data using following method
public function view_articles(){
//you must have to import Article model at the top
$articles = Article::with(['user'])->get();
dd($articles); //this will show response.
return view('view_file')->with(compact('articles'));
}
//inside your view file
#foreach ($articles as $article)
<tr>
#foreach($article as $userss)
<td>{{$article->title}}</td>
<td>{{$article->published}}</td>
<td>{{$article->user->name}}</td>
#endforeach
#endforeach

Many to Many Relationship return trying to get property 'books' of non-object

I am trying to displaying the book a user has favorited, so I think many to many relationships will solve it. So I have 3 tables
Users Table
Books Table
Favorite Table
The Favorite table is the pivot table
Schema::create('favorites', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('book_id')->unsigned();
$table->integer('user_id')->unsigned();
$table->timestamps();
});
In the User Model
public function favorites(){
return $this->hasMany(Favorite::class);
}
In the Book Model
public function favorites()
{
return $this->hasMany(Favorite::class);
}
In my Favorite Model
public function book ()
{
return $this->belongsTo(Book::class);
}
I was able to save to Favorite Column like this
public function favorite($id)
{
Favorite::create([
'book_id' => $id,
'user_id' => Auth::id()
]);
Session::flash('success', "You Favorite a Book");
return redirect()->back();
}
But I am trying to show the Books Favorited
public function mylibrary(){
$user = Auth::user()->books;
// dd($user);
return view('library', compact('user'));
}
In my view, I have this
#foreach($user->books as $mybook)
...
<div class="clearfix"></div>
<p class="authorone">{{ $mybook->author->name }}</p>
<h1 class="book-title">{ $mybook -> title }}</h1>
</div>
#endforeach
You are passing Auth::user()->books to your view, not Auth::user(). You are not passing the User.
In the view you are then trying to use that value as an object:
#foreach ($user->books as $mybook)
Auth::user()->books is most likely returning null since it is not a relation method or an attribute (most likely).
You probably want to pass the User to your view:
view(..., ['user' => Auth::user()]);
Then you would want to access the correct dynamic property for the relationship you want since you aren't showing a books relationship on User.
Your model relationships could use a better setup. There is no Many to Many setup here and you don't need to define a model for the pivot, you are actually avoiding the Many to Many by doing this.
Models:
class User
{
public function books()
{
return $this->belongsToMany(Book::class, 'favorites');
}
}
class Book
{
public function users()
{
return $this->belongsToMany(User::class, 'favorites');
}
}
Controller:
public function favorite($id)
{
Auth::user()->books()->attach($id);
...
}
public function mylibrary()
{
$user = Auth::user()->load('books.author');
return view('library', compact('user'));
}
View:
#foreach($user->books as $mybook)
...
<div class="clearfix"></div>
<p class="authorone">{{ $mybook->author->name }}</p>
<h1 class="book-title">{{ $mybook->title }}</h1>
</div>
#endforeach
I was able to solve it this way
My view
#forelse ($user->favorites as $mybook)
<p class="authorone">{{ $mybook ->book->author-> name }}</p>
<h1 class="book-title">{{ $mybook ->book-> name }}</h1>
#empty
<h2>You haven't Favorited any book</h2>
<div class="text-center">
Return To
</div>
#endforelse
I added this to my user model
public function favorites(){
return $this->hasMany(Favorite::class);
}
public function books()
{
return $this->belongsToMany(Book::class);
}
My controller
public function mylibrary(){
return view('library', ['user' => Auth::user()]);
}

Laravel - Multiple Controllers within a View

I'm trying to code a simple social media page. The show view should display a post with all the comments for that particular post listed below.
I've tried a couple different approaches with no luck, this is the approach I feel like I might be closet to success with, any suggestions?
I can provide other extracts of code if you think the problem lies elsewhere but I think my problem lies within these 4 files.
web.php
Route::resource('post', 'PostController');
Route::resource('post', 'CommentController');
show.blade.php
<h1>{{$post->title}}</h1>
<p>Description: {{$post->description}}</p>
<h3>Comments</h3>
<ul>
#foreach ($comments as $comment)
<li>
User: {{$comments->user_name}} <br>
Comment: {{$comments->comment}} <br>
</li><br>
#endforeach
</ul>
PostController.php
public function show($id)
{
$post= Post::find($id);
return view('post.show')->with('post', $post);
}
CommentController.php
public function show($id)
{
$comments= Comment::find($id);
return view('post.show')->with('comments', $comments);
}
EDIT 1
Post.php
class Post extends Model
{
protected $fillable = ['title', 'description'];
function user() {
return $this->belongsTo('App\User');
}
function comment() {
return $this->hasMany('App\Comment');
}
}
firstly set the relationship between Post and Comment Model
In Post Model
class Post extends Model
{
public function comments(){
return $this->hasMany(Comment::class);
}
}
In Comment Model
class Comment extends Model
{
public function post(){
return $this->belongsTo(Post::class);
}
}
Post Controller
public function show($id)
{
$post= Post::find($id);
return view('post.show')->with('post', $post);
}
Write in the blade file
<h1>{{$post->title}}</h1>
<p>Description: {{$post->description}}</p>
<h3>Comments</h3>
<ul>
#foreach ($post->comments as $comment) //get all the comments related to this post
<li>
User: {{$comment->user_name}} <br>
Comment: {{$comment->comment}} <br>
</li><br>
#endforeach
</ul>
You can get both data by make relations between your models
I think in your two models the relation would be like that,
Post Model
namespace App\Post;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function comments(){
return $this->hasMany(Comment::class);
}
}
Comment Model:
namespace App\Comment;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
public function post(){
return $this->belongsTo(Post::class);
}
}
so if you want to return the data to view then,
PostController.php
public function show($id)
{
$post= Post::with('comments')->find($id);
$data = [
'post' => $post,
'comments' => $post->comments,
];
return view('post.show', $data);
}
CommentController.php
public function show($id)
{
$comments= Comment::with('post')->find($id);
$data = [
'post' => $comments->post,
'comments' => $comments,
];
return view('post.show' , $data);
}
For more details: https://laravel.com/docs/5.7/eloquent

Categories