Issue with Laravel hasMany relation - laravel

I’m having an issue with relations in two of my models in a Laravel application. My models are:
class Invoice extends Eloquent {
protected $table = 'invoices';
public function line_items()
{
return $this->hasMany('LineItem');
}
}
And:
class LineItem extends Eloquent {
protected $table = 'line_items';
public function invoice()
{
return $this->belongsTo('Invoice');
}
}
In my controller, I fetch an Invoice row with the following:
$invoice = Invoice::find($id);
However, if I try and access the line_items property to fetch the LineItem rows relating to my invoice, I get the following error:
Invalid argument supplied for foreach()
Why is this? I’ve set my models up as per Laravel’s documentation: http://laravel.com/docs/eloquent#one-to-many

change
public function line_items()
for
public function lineItems()
and it will work , tested in Laravel 4.1 :)

Check your tables relations... (Schema)
Your FK must be lineitem_id... You have modified this? Laravel will configure automatically... Don't change this...
Then, try
$invoice->line_items() or $invoice->line_items in 4.1

Check for line_items before the foreach loop:
if(! $invoice->line_items->isEmpty()){
foreach($invoice->line_items as $line_item){
//do stuff
}
}
Also, it won't hurt to explicitly mention the FK, although laravel will automatically try to do it for you provided you use proper names for your table fields.
//Invoice Model
return $this->hasMany('LineItem', 'invoice_id');
//LineItem Model
return $this->belongsTo('Invoice', 'invoice_id');

Related

Laravel orm with() not works

JoinSkipReason has not id, but JoinReview's primary key is foreign key of JoinSkipReason.
Query Builder works well...
I want to use with() to join the JoinSkipReason to the JoinReview table.
Thank you.
JoinReview::with(
'join_skip_reason'
);
class JoinReview extends Model
{
public function joinSkipReason()
{
return $this->hasOne('App\Models\Service\JoinSkipReason');
}
}
class JoinSkipReason extends Model
{
protected $fillable = ['join_review_id', 'reason'];
public function joinReview()
{
return $this->belongsTo('App\Models\Service\JoinReview', 'id');
}
}
I've encountered this issue myself, the issue is that for eager loading multi-word relations you should use camelCase.
In your code:
JoinReview::with(
'joinSkipReason'
);
I've also found a (kinda old) issue saying that you should also access the eager-loaded relation as camelCase, otherwise it will ignore the cached result and query the database again.
Check do like that
public function joinSkipReason()
{
return $this->hasOne('App\Models\Service\JoinSkipReason','join_review_id','id');
}

How get users from section table ? laravel

The idea is that I have relation between two table's section and user
the section_id exist in users table it relation with id section
SO for ex : section_id = 2 > want to bring all users belongs to id section
My code here use id from url and I don't want to do this I want without id bring all users :
public function getAllUsers($id)
{
$data = User::where('section_id',$id)->get();
}
If I'm understanding you correctly, you want to get all the users for a particular Section that have the relationship to that section.
Assuming you have the relationship set up correctly on the Section model:
public function users() {
return $this->hasMany('App\User');
}
I suggest you go about this 'backward' and just pull the users from the Section model itself (eager loading allows one query):
$section = Section::with('users')->first();
$usersForThisSection = $section->users;
If you setup a One to Many relationship you can say things like: $user->section to return the section a user belongs to...and $section->users to get a collection of all the users in a section -- the getAllUsers() is redundant in this case.
Make sure your User and Section models contain these methods. Sounds like your migration was setup properly if you have a section_id column on your users table.
More info on one-to-many here: https://laravel.com/docs/5.8/eloquent-relationships#one-to-many
// app/User.php
class User extends Model
{
public function section() {
return $this->belongsTo('App\Section');
}
}
// app/Section.php
class Section extends Model
{
public function users() {
return $this->hasMany('App\User');
}
}
Test out your relationships in php artisan tinker like so...
$user = User::find(1);
$user->section
$section = Section::find(1);
$section->users
you need a unique identifier to receive section_id's users. receive it from url(get) or ajax(post) . if you worry about users access then use "auth"

Laravel Eloquent, filtering from pivot table column

I need to filter the active clients from a route using Eloquent.
I'm working with a third party database that I can't modify. In my project I have two models: Cliente(client) and Ruta(route), which have a many to many relationship, so I added the belongsToMany relationship in my models.
The only column I'm interested from the pivot table is called DESACTIV, which tells me if a Client is deactivated for a Route.
Ruta model:
class Ruta extends Model
{
protected $connection = 'mysql2';
protected $table = 'truta';
protected $primaryKey = 'CODIRUTA';
public function clientes(){
return $this->belongsToMany(Cliente::class, 'tcpcarut', 'CODIRUTA', 'CODICLIE')->withPivot('DESACTIV');
}
}
Cliente model:
class Cliente extends Model
{
protected $connection = 'mysql2';
protected $table = 'tcpca';
protected $primaryKey = 'CODICLIE';
public function rutas(){
return $this->belongsToMany(Ruta::class, 'tcpcarut', 'CODICLIE', 'CODIRUTA')->withPivot('DESACTIV');
}
}
What I need is to get the active (or non deactivated) Clients given a specific Route.
I have done it on my controller like this:
$miRuta = Ruta::where('CODIRUTA','=',$ruta)->first();
$clientes = array();
foreach ($miRuta->clientes as $cliente){
if ($cliente->DESACTIV == 0){
array_push($clientes, $cliente->NOMBCLIE);
echo end($clientes)."<br/>";
}
}
And it works fine, but I don't think it's elegant. I know this can be archieved through Eloquent, I'm just to noob at it and don't know how to do it.
Maybe I could add the filter on the clientes method on my Ruta model, so it would return only the active Clients.
Or maybe It could be best to add a method on the Cliente model, like isDeactivated
I know it sounds like I know what I'm talking about but I need someone to hold my hand on this, I'm just too noob with Eloquent :/. Examples would be much appreciated.
You can use the wherePivot method to constrain a relationship based on values in the pivot table. You just need to add the following to your Ruta model
public function desactivClientes() {
return $this->clientes()->wherePivot('DESACTIV', 0);
}
And then you just have to modify the rest of your code a bit to use the constrained relationship. I'm also adding a null check because if this function does return null, which can happen if your table doesn't have a record where CODIRUTA matches whatever is in $ruta, then it will likely throw a fatal error trying to call a method on a non-object.
$miRuta = Ruta::where('CODIRUTA','=',$ruta)->first();
$clientes = array();
if ($miRuta !== null) {
$clientes = $miRuta->desactivClientes()->pluck('NOMBCLIE');
}

Cannot access Collection::$items

I've got some troubles with an eloquent query.
Users have many feeds and feeds have many items.
I need to get all the items that belongs to the feeds of the user order by date.
I've got a pivot table:
feed_user
----------
- id
- feed_id
- user_id
and relationships are defined like this in my models:
class UsersController extends BaseController {
public function feeds() {
return $this->hasMany('feed');
}
class Feed extends \Eloquent {
protected $fillable = [];
public function users() {
return $this->belongsToMany('User');
}
public function items() {
return $this->hasMany('Item');
}
class Item extends \Eloquent {
protected $fillable = [];
public function feed() {
return $this->belongsTo('Feed');
}
But when I do this query...
Auth::user()->feeds->items->orderBy('date', 'DESC')->get();
It returns this error:
Cannot access protected property Illuminate\Database\Eloquent\Collection::$items
There are a couple issues here.
First, the relationship on User model is not correct. A hasMany relationship is one half a one-to-many relationship. This would assume that a feed belongs to one user, and that the feed table has the user_id field. A many-to-many relationship is defined by adding a belongsToMany relationship on both models. So, a user belongsToMany feeds, and a feed belongsToMany users.
class User extends \Eloquent {
public function feeds() {
return $this->belongsToMany('feed');
}
}
Next, the error you're seeing is because Auth::user()->feeds returns a Illuminate\Database\Eloquent\Collection object. You're then trying to access the items attribute on the Collection, which is protected and throws the error you're seeing.
Finally, since Laravel does not use joins for relationships, you cannot order a query by a field on a related table without manually doing the join yourself.
Try using eager loading:
Auth::user()->with('feeds.items')->orderBy('date', 'DESC')->get();

Laravel 4 - Display username based on ID

I have a posts and a users table.
In the posts table, i have a posts_author which is the ID of the user from the users table.
Is there an easy way to display the email address of the user, which is in the users table?
Cheers,
As long as you've set your relationships up it should just be a simple query.
http://laravel.com/docs/eloquent#relationships
Look at the one to many relationships.
(1 User, Multiple posts)
Remember to set the inverse of the relationship up also
If your model has the right relationships then should be as simple as $post->author->email().
You must tweak the author relationship because Eloquent assumes the key will be named author_id.
// Post
public function author() {
return $this->belongsTo('Author', 'posts_author');
}
// Author
public function posts() {
return $this->hasMany('Post');
}
Remember to use eager loading in case you are retrieving emails from more than one post object, or you will end up with n+1 queries.
Providing that you've configured the relationships properly, it should be pretty easy.
Post Model:
class Post extends Eloquent
{
protected $table = 'posts';
public function author()
{
return $this->belongsTo('User', 'posts_author');
}
}
Then User Model:
class User extends Eloquent
{
protected $table = 'users';
public function posts()
{
return $this->hasMany('Post', 'posts_author');
}
}
Then when loading the post you can do the following.
$post = Post::with('author')->find($id);
This will tell Eloquent to join on the users table and load the user data at the same time. Now you can just access all of the user information like this:
$post->author->username;
$post->author->email;
$post->author->id;
// etc etc
Obviously this is just a skeleton, but the assumption is that you have the rest setup.

Resources