Inner join using eloquent in Laravel 5.1 - php

I have a doubt that I couldn't find an answer anywhere.
I'm new to eloquent and to make the basic stuff it is excelent!
Now I need to query data from different tables and I was wondering if I can do it with eloquent.
I have two models:
class Worker extends Model {
protected $table = 'workers';
public $timestamps = true;
public function area()
{
return $this->belongsTo('Area');
}
}
And this one
class Area extends Model {
protected $table = 'areas';
public $timestamps = true;
public function worker()
{
return $this->hasMany('Worker');
}
}
So basically a worker belongs to an area and an area has many workers.
Now I want to show in a table the name of the worker and the name of the area that he belongs to.
I can do it using the query builder but I wanted to know if I can do it with eloquent.
I saw a post in laracast with this code:
$workers = Worker::with('area')->get();
Now when I use that I get the following error:
Class 'Area' not found
I don't know why I get that error when the function 'area' exists in the Worker class and in the WorkerController I'm using
use App\Area;
What I want to be able to do is the following:
#foreach ($workers as $worker)
<td>{{ $worker->name }}</td>
<td>{{ $worker->lastname }}</td>
<td>{{ $worker->areas->name }}</td>
#endforeach
Like I said, I already I'm able to accompish this using laravel's query builder but I just want to know if I can make more use of the Eloquent :)
Thank you for your time.
Just in case anyone asks here is my raw query:
$workers = DB::table('workers')
->join('areas', 'areas.id', '=', 'workers.area_id')
->select('workers.*', 'areas.name as area')
->get();
That's the one I'm using and it works perfectly fine, thank you! :)

You are missing namespaces in your relations.
public function area()
{
return $this->belongsTo('App\Area');
}
and
public function worker()
{
return $this->hasMany('App\Worker');
}

You need to use function like you named in model "area" not "areas":
#foreach ($workers as $worker)
<td>{{ $worker->name }}</td>
<td>{{ $worker->lastname }}</td>
<td>{{ $worker->area->name }}</td>
#endforeach

Related

ErrorException Attempt to read property "name" on null (View:

I have 2 relationships that point to the same User model: operador() and profesional().
class Cita extends Model
{
public function paciente(){
return $this->belongsTo('\App\Models\Paciente');
}
public function profesional(){
return $this->belongsTo('\App\Models\User');
}
public function operador(){
return $this->belongsTo('\App\Models\User');
}
}
In the view I call them like this:
#foreach ($comisiones as $comision)
<tr>
<td>{{ $comision->paciente->name }}</td>
<td>{{ $comision->profesional->name }}</td>
<td>{{ $comision->operador->name }}</td>
<td>{{ number_format($comision->total, 0, '.', '.') }}</td>
<td>{{ $comision->estado }}</td>
</tr>
#endforeach
The program crashes on me when it tries to call $commision->operador->name. If I leave it as a comment it works without problems. But it gives me an error when I have the 2 relations at the same time.
Can I have 2 relationships pointing to the same model? And if not, what alternative do I have? Thanks
For the fact that you are using belongTo relationship, that means User is the parent model and Professional and Operador are the child model.
Hence, it is expected that the table for Professional has a column called user_id, thesame thing for the Operador table, it should have user_id column.
With this the relationship will work just fine.
Yes, you can have 2 relationships pointing to the same model.
When you write :
public function operador(){
return $this->belongsTo('\App\Models\User');
}
Laravel expects that The Migration (The table citas) has a column named operador_id. So Yes you can have multiple relationships to the same model.

Displaying fields with many to many relationship laravel 5.4

I'm the beginner of laravel 5.4. I just want to ask. I want to display in Assignments table the Collectors but it doesn't show.
Screenshot of the Assignments Index
Code in my Assignment index.blade.php
<td>{{ $assignment->collector['firstname'] }} {{ $assignment->collector['lastname'] }}</td>
Assignment.php model
public function collectors()
{
return $this->belongsToMany(Collector::class);
}
Collector.php model
public function assignments()
{
return $this->belongsToMany(Assignment::class);
}
AssignmentsController
public function index()
{
$assignments = Assignment::all();
return view('assignments.index', compact('assignments'));
}
I search to how to display the collectors with both many to many relationship. I read the doc about using pivot but I had still errors about that. Can you help me resolving this? Thanks
$collector is an object, not an array. Use -> syntax to access properties on individual collector models:
$collector->firstname
Since the relationship is many to many you need two loops:
#foreach($assignments as $assignment)
#foreach($assignment->collectors as $collector)
<td>{{ $collector->firstname }} {{ $collector->lastname }}</td>
#endforeach
#endforeach
If you find you often need two fields together, like first and last names, you can create an accessor on the Collector model to easily join them:
public function getFullNameAttribute()
{
return $this->getAttribute('firstname') . ' ' . $this->getAttribute('lastname');
}
Allowing you to then do:
#foreach($assignments as $assignment)
#foreach($assignment->collectors as $collector)
<td>{{ $collector->fullname }}</td>
#endforeach
#endforeach

Repositories and Better Array Usage with Querying DB

I have a Laravel User's Repository that I am utilizing but to prevent the always nagging N+1 problem I'm trying to get all my users to be returned with their role and status in the user's array.
As you can see right now with how its running I have 200+ times its running because of how any records in my db I have. So I"m trying to cut that down.
How would I go about doing this?
<?php namespace Backstage\Repositories\Users;
use User;
use Backstage\Repositories\DbRepository;
class DbUserRepository extends DbRepository implements UserRepositoryInterface {
protected $model;
function __construct(User $model)
{
$this->model = $model;
}
}
views/users/partials/table.blade.php
<td>{{ $user->id }}</td>
<td>{{ $user->full_name }}</td>
<td>{{ $user->email_address }}</td>
<td>{{ $user->role->name }}</td>
<td>{{ $user->status->name }}</td>
You can use eager loading to get rid of the N+1 problem, see the docs
You didn't include your models so not 100% sure about naming, but i think you need this:
function __construct(User $model)
{
$this->model = $model;
$this->model->load('roles');
}
However this always eager loads the roles for the DbUserRepository.
You can also call ->load('roles') in the right method only.

Why do i need first() in blade view with one to many relationship?

I have two tables
One QUESTIONS_TITLES entry has many QUESTIONS entries. The titles contain a group of questions.
QUESTIONS
id | question | ... | question_titles_id
QUESTIONS_TITLES
id | title
MODEL QUESTION
class Question extends \Eloquent {
public function questionTitle() {
return $this->belongsTo('QuestionsTitle', 'question_titles_id');
}
}
MODEL QUESTION
class QuestionsTitle extends \Eloquent {
protected $fillable = ['title', 'question_cat_id', 'type'];
protected $table = 'questions_titles';
public function question() {
return $this->hasMany('Question');
}
}
in my question controller i do:
$questions = Question::all();
$this->layout->content = View::make('questions.index', compact('questions'));
in my view i want a group of questions with the corresponding parent title
#foreach ($questions as $question)
<tr>
<td>{{ $question->questionTitle()->first()->title }}</td>
<td>{{ $question->id }}</td>
<td>{{ $question->question }}</td>
</tr>
#endforeach
this works. but why do i need first()? it doesn't look clean
when i drop it i get
Undefined property: Illuminate\Database\Eloquent\Relations\BelongsTo::$title (View: /vagrant/app/views/questions/index.blade.php)
$question->questionTitle() returns a BelongsTo object, not the QuestionTitle object. When you call $question->questionTitle()->first() you're executing the first() method on the relationship. This through laravel magic is getting you the correct answer. Though what you should really be doing is: $question->questionTitle->title. When you access the questionTitle attribute Laravel automatically resolves the relationship for you.

Laravel eloquent - One to many relationships (Trying to get property of non-object)

I have "posts" table that has many-to-one relationship with "categories" table. The goal is to show all of posts and their categories.
Tables:
Posts: id, content, category_id, etc
Categories: id,name
Here's my code
Models:
class Posts extends Eloquent
{
public static $table = 'posts';
public function categories()
{
return $this->belongs_to('Categories');
}
}
class Categories extends Eloquent
{
public static $table = 'categories';
public function posts()
{
return $this->has_many('posts');
}
}
My controller
public function get_posts()
{
$posts = Posts::with('categories')->all();
return View::make('admin.posts')
->with('title', 'Posts')
->with('posts', $posts);
}
My view
#foreach($posts as $post)
<tr>
<td>{{ $post->title }}</td>
<td>{{ $post->categories->name }}</td>
<td><small> {{$post->updated_at}} </small></td>
<td>
<button>
{{HTML::link_to_route('edit_post','Edit',array($post->id))}}
</button>
{{Form::open('admin/delete','Delete')}}
{{Form::hidden('id', $post->id)}}
<input type="submit" name="edit_post" value="Delete"/>
{{Form::close()}}
</td>
</tr>
#endforeach
ERROR:
Error rendering view: [admin.posts]
Trying to get property of non-object
I am a newbie, please help me solve this issues
{{ $post->categories->name }} before test is categories exists
Example:
#if( ! empty($post->categories))
<td>{{ $post->categories->name }}</td>
#else
#end if
Aesis.
Just use ::all() instead of ::with(..)->all()
categories is an array as you are using a has_many relationship. There are many categories, hence an array is returned, so to access it you have to index it like an array
the correct solution would be
$post->categories[0]->name
Are you using Laravel 4? First the syntax for declaring relationship is hasMany and belongsTo, in camel case. Check it out in Laravel documentation
In view, check if categories are empty collection, ie., whether post has its category:
#if($post->categories->count())
<td>{{ $post->categories->name }}</td>
...
#endif
By the way, I would use singular form as model class name, like Post and Category instead of plural forms. And in Post class I would define inverse one-to-many relationship with singular form, to show there's only one entry in category table for this given Post.
public function category()
{
return $this->belongsTo('Category');
}

Categories