I have two table User & Article the relationship between tables are
Model:
class Article extends Eloquent {
public static $table = 'article';
public function User()
{
return $this->has_one('user', 'id');
}
and
class User extends Eloquent {
public static $table = 'user';
public function Article()
{
return $this->belongs_to('article', 'id_user');
}
I want to get name value from User directly on Article view but don't works with error
Trying to get property of non-object
My Controller:
public function action_index()
{
$Article = Article::order_by('id')->paginate(10);
return View::make('article.index')->with('$articles', $Article);
}
My View:
#foreach ($articles->results as $Arti)
<tr>
<td>{{$Arti->id}}</td>
<td>{{$Arti->tag}}</td>
<td>{{$Arti->user->name }}</td> <------ ERROR
<td>{{$Arti->content}}</td>
<td>{{$Arti->date}}</td>
<td>
Have a look at the below, a few things are different to yours...
Article belongs_to User (not has_one)
User has_many Article (not belongs_to)
Your relationships should be named in lowercase, plural for has_many (i.e. articles or user)
Your relationship subjects should be class names (i.e. Article or User)
Foreign keys should be name relationship_id, i.e. user_id
Add ::with() to your query to eager load relationships
When you paginate you need to access ->results in your view
class Article extends Eloquent {
// 3: lowercase 'user'
public function user()
{
// 1: Article belongs to User
// 4: class name 'User'
// 5: Foreign key on article table is user_id
return $this->belongs_to('User');
}
}
// models/user.php
class User extends Eloquent {
// 3: lowercase plural 'articles'
public function articles()
{
// 2: User has many Articles
// 4: class name 'Article'
return $this->has_many('Article');
}
}
// controllers/articles.php
class Article_Controller extends Base_Controller {
public $restful = true;
public function get_index()
{
// 6: Eager load the user relationship, ::with('user')
$articles = Article::with('user')->order_by('id')->paginate(10);
return View::make('articles.index', compact('articles'));
}
}
// views/articles/index.blade.php
// 7: access $articles->results from the paginator
#foreach ($articles->results as $article)
<h1>{{ $article->title }}</h1>
<p>By {{ $article->user->name }}</p>
#endforeach
{{ $articles->links() }}
Related
I mix a little bit with the query in laravel.
I have a list of articles. I would like to get the datas from the author of this article.
Relation model Article
public function author()
{
return $this->belongsTo('App\Models\Author');
}
Relation model Author
public function articles()
{
return $this->hasMany('App\Models\Article');
}
I try this $author = Author::with('articles')->first();
this :
$author = Author::whereHas('articles', function ($query){
$query->where('id', '1');
});
And many others tests, but I doesn't understand all.
My method in my controller :
protected function index()
{
$articles = Article::published()->paginate(8);
return view('pages.blog', [
'articles' => $articles,
]);
}
And above all, how do I display the correct information in my view in my foreach?
Thank you !
To solve the problem you have to define the relationships in the following way.
Article class define, based on the following table structure:
articles {
id : integer [primary key],
...,
author_id : integer [foreign key]
}
class Article extends Illuminate\Database\Eloquent\Model {
protected $table = "articles";
// HERE YOUR CLASS CODE
public function author() {
return $this->belongsTo("Author", "author_id", "id");
}
}
Author class define, based on the following table structure:
authors {
id : integer [primary key],
...
}
class Author extends Illuminate\Database\Eloquent\Model {
protected $table = "authors";
// HERE YOUR CLASS CODE
public function articles() {
return $this->hasMany("Article", "author_id", "id");
}
}
When you use the method belongsTo and hasMany, it is better indicate the label of the external key and the local key.
To display information in your view you have to follow the example:
#foreach ($articles as $article)
<p>Id {{ $article->id }}</p>
...
#endforeach
For more information :
https://laravel.com/docs/5.4/eloquent-relationships
https://laravel.com/docs/5.4/blade
I am trying to grasp the concept of Eloquent ORM by creating a ticketing system at the moment. What I am trying to achieve is:
The tickets with the user who posted the ticket
The feedback belonging to the ticket and the user who entered the
feedback
This is what I have right now:
// TicketController.php
public function index()
{
$tickets = Ticket::with('feedback')->with('user')->orderBy("created_at", "desc")->get();
//dd($tickets);
return View::make('modules.helpdesk.index')->withTickets($tickets);
}
And the following models
// Ticket.php
class Ticket extends Eloquent {
protected $table = 'helpdesk_tickets';
public function feedback()
{
return $this->hasMany('Feedback');
}
public function user()
{
return $this->belongsTo('User');
}
}
// Feedback.php
class Feedback extends Eloquent {
protected $table = 'helpdesk_tickets_feedback';
public function ticket()
{
return $this->belongsTo('Ticket');
}
}
// User.php
class User extends Eloquent {
protected $table = 'users';
public function ticket()
{
return $this->belongsTo('Ticket');
}
}
What I have now is the tickets, their related feedback and user who created the ticket. What I am trying to achieve now is to also get the user who created the feedback.
You need to fix the relation:
// User model
public function tickets()
{
return $this->hasMany('Ticket'); // adjust namespace if needed
}
Next add the relation:
// Feedback model
public function user()
{
return $this->belongsTo('User'); // namespace like above
}
then use eager loading:
// it will execute 4 queries:
// 1st for tickets
// 2nd for feedback
// 3rd for feedbacks' user
// 4th for tickets' user
$tickets = Ticket::with('feedback.user', 'user')->latest()->get();
you can then access the relations in a loop, like below:
#foreach ($tickets as $ticket)
{{ $ticket->title }} by {{ $ticket->user->name }}
#foreach ($ticket->feedback as $feedback)
{{ $feedback->content }}
#endforeach
#endforeach
What you want to do is create nested relations, just like Ticket add a belgonsTo relation on feeback
When you want to use it you can chain relations using the dot notation feedback.user
The code
// Feedback.php
class Feedback extends Eloquent {
protected $table = 'helpdesk_tickets_feedback';
public function ticket()
{
return $this->belongsTo('Ticket');
}
public function user()
{
return $this->belgonsTo('User')
}
}
// TicketController.php
public function index()
{
$tickets = Ticket::with('feedback')->with('user')->with('feedback.user')->orderBy("created_at", "desc")->get();
//dd($tickets);
return View::make('modules.helpdesk.index')->withTickets($tickets);
}
EDIT:
Even though this would work, it will execute more queries than needed. See Jareks answer.
Original Answer:
First of all you need to get your relationships straightened, in User.php you should call the user relationship with HasMany.
public function ticket() {
return $this->hasMany('Ticket');
}
In modules.helpdesk.index you should now have a Ticket Collection since your attaching the $ticket variable to the view.
If you loop through this collection with a foreach loop then what you should get is a model each loop:
foreach($tickets as $ticket) {
// Prints the name property of the Ticket model
print $ticket->name;
// Since a ticket only belongs to ONE user then that means that you are trying to fetch a model
// What we're doing here is getting the User model via the relationship you made in the model Ticket.php and then getting the name.
print $ticket->user()->first()->username;
// Since a ticket can have MANY feedbacks that means were fetching a collection
// which needs to be broken down to models so we do that looping the collection.
// Here we are doing the same thing as with the User model except with a collection.
foreach($ticket->feedback()->get() as $feedback) {
$feedback->text;
}
}
You should definitely check out the Laravel API and see Collection and Model there. http://laravel.com/api/ You get alot of help from there when you get stuck, trust me :)
I hope this answered your question.
I'm trying to print all books' name in 'books' table and its category associated. But it doesn't show any content nor error messages.
Model::Book.php
class Book extends Eloquent{
protected $table ='books';
public function bookCat()
{
return $this->belongsTo('BookCategory');
}
}
Model::BookCategory.php
class BookCategory extends Eloquent{
protected $table ='book_categories';
}
Controller::route.php
Route::get('/', function()
{
$books = Book::all();
return View::make('books')
->with('books', $books);
});
View::books.blade.php
#foreach ($books as $book)
<li>{{ $book->book_name }}</li>
- <small>{{ $book->bookCat }}</small>
#endforeach
Table::books
(int)id, (string)book_name, (int)category_id
Table::book_categories
(int)id, (string)category
Add the relationship to BookCategory.
class BookCategory extends Eloquent{
protected $table ='book_categories';
public function books() {
return $this->hasMany('Book');
}
}
Your local key doesn't match the model names, either, so you would need to specify that in the relation:
class Book extends Eloquent{
protected $table ='books';
public function bookCat()
{
return $this->belongsTo('BookCategory', 'category_id');
}
}
You may also want to eager-load the categories in your controller, as your query is for the books:
$books = Book::with('bookCat')->get();
I have a list of books and a list of authors. I made the Model relations, so that my Book Model says, that books->belongTo('Author') and my Author Model says, that authors->hasMany('Book').
So normally I could access the a variable through this:
$books = Book::all();
And then in the view:
#foreach($books as $book)
<div>{{$book->id}}</div>
<div>{{$book->title}}</div>
<div>{{$book->authors->firstname}}</div>
#endforeach
But this does not work. I get the error message: Trying to get property of non-object
So here are my files:
My Models:
Book.php
class Book extends \Eloquent {
protected $guarded = [];
public function religions()
{
return $this->belongsTo('Religion');
}
public function branches()
{
return $this->belongsTo('Branch');
}
public function authors()
{
return $this->belongsTo('Author');
}
public function quotes()
{
return $this->hasMany('Quote');
}
public function chapters()
{
return $this->hasMany('Chapter');
}
}
Author.php
class Author extends \Eloquent {
protected $guarded = [];
public function books()
{
return $this->hasMany('Book');
}
public function quotes()
{
return $this->hasMany('Quote');
}
public function branches()
{
return $this->belongsTo('Branch');
}
public function religions()
{
return $this->belongsTo('Religion');
}
}
Then come my controller:
ReligionBranchBookController
class ReligionBranchBookController extends \BaseController {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index($religionId, $branchId)
{
//
// $books = Book::where('religion_id', $religionId)->where('branch_id', $branchId)->get();
$books = Book::all();
$authors = Author::all();
// dd($books->toArray());
return View::make('books.index')
->with('religionId', $religionId)
->with('branchId', $branchId)
->with('books', $books)
->with('authors', $authors);
}
}
My Views:
index.blade.php
#extends('layout.main')
#section('content')
<h1>Books List!!</h1>
<table>
<tr>
<th>ID</th>
<th>Title</th>
<th>Author</th>
</tr>
#foreach($books as $book)
<tr>
<td>{{$book->id}}</td>
<td>{{$book->title}}</td>
<td>{{$book->authors->firstname}}</td>
</tr>
#endforeach
</table>
#stop
I know that it should normally work, I rebuild it with only books and authors, and it works fine there.
So, does anyone have an idea, where I am going wrong?
Thanks,
George
In your Book model change the authors method to author like this:
public function author()
{
return $this->belongsTo('Author');
}
Because, one book belongs to one author according to your relationship and when you call authors the belongsTo->getResults() get called and runs the wrong query so authors get null and you get the error. Things to remember:
For hasOne and belongsTo relationship use singular form of relationship method, i.e, author not authors.
hasOne or belongsTo returns a single model object.
For hasMany and belongsToMany relationship use plural form of relationship method, i.e, authors not author.
hasMany and belongsToMany returns a collection of model objects.
I am using laravel, I have a main table with 'projects' and a table with 'users', an intermediate table linking the two as a many-to-many relationship.
Now I want to display a list of projects, but if they are over 'projects.max_people' then they should be hidden from this list, how do I do this in laravel?
The problem is im 'get()'ing the users in the view, after I did Project::get()... how do I add this where condition?
You should create a new object called ProjectUser or so. In this object should contain a 'project_id' and 'user_id'.
Then, your Project model would look something like this:
<?php
class Project extends \Eloquent
{
protected $table = 'projects';
public function projectUsers(){
$this->hasMany('ProjectUser', 'project_id');
}
}
The User class:
<?php
class Project extends \Eloquent
{
protected $table = 'projects';
public function projectUsers(){
$this->hasMany('ProjectUser', 'user_id');
}
}
The ProjectUser class:
class ProjectUser extends \Eloquent
{
protected $table = 'project_users';
public function project(){
$this->belongsTo('Project'`enter code here`, 'project_id');
}
public function user(){
$this->belongsTo('User', 'user_id');
}
}
Now, you can get the users of a project like so:
$projects = Project::with('projectUsers.user')->get();
When looping through these objects you can access the user like this:
#foreach($projects as $project)
#foreach($project->projectUsers as $projectUser)
{{ $projectUser->user->id }}
#endforeach
#endforeach