laravel get parent data from child relationship - laravel

Hi i have this relationship between Customers and Claims
Customers Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Customers extends Model
{
public $primaryKey = 'id';
protected $fillable = [
'contr_nom',
'contr_cog',
'benef_nom',
'benef_cog',
'email',
'polizza',
'targa',
'iban',
'int_iban',
'cliente',
];
public function claims()
{
return $this->hasMany(Claims::class);
}
public function refunds()
{
return $this->hasManyThrough(Refunds::class, Claims::class);
}
}
Claims model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Claims extends Model
{
public $primaryKey = 'id';
protected $fillable = [
'dossier',
'date_cla',
];
public function refunds()
{
return $this->hasMany(Refunds::class);
}
public function customers()
{
return $this->belongsTo(Customers::class,'customers_id');
}
}
I need to put some information from claims and from customers in a datatable
They have a parent-child relationship as first and second columns of datatables i put id and dossier from Claims table, but how i can get for example contr_nom, contr_cog, email, polizza, etc. from Customer table for each dossier?
I tried with this controller
class ComptaController extends Controller
{
public function index(Request $request){
if ($request->ajax()) {
$data = Claims::with('customers')->get();
/*Cannot access to Customers from $data but i can see in the relationship*/
dd($data->customers->contr_nom); GIVE ME ERROR
return Datatables::of($data)
->addIndexColumn()
->addColumn('action', function($row){
$btn = 'Edit Delete';
return $btn;
})
->rawColumns(['action'])
->make(true);
}
return view('pages.compta');
}
}
but i cannot access to customers data for each dossier..
Thx.

foreach($data->customers as $customer){
dd($customer->contr_nom);
}
or
Claims::with(array('customer'=>function($query){
$query->select('id','contr_nom');
}))->get();

Using datatables I guess you can add related customer details by adding columns with a closure method like
return Datatables::of($data)
->addIndexColumn()
->addColumn('contr_nom',function($row){
return $row->customers->contr_nom;
})
->addColumn('contr_cog',function($row){
return $row->customers->contr_cog;
})
->addColumn('email',function($row){
return $row->customers->email;
})
//.. and so on otehr columns
->addColumn('action', function($row){
$btn = 'Edit Delete';
return $btn;
})
->rawColumns(['action'])
->make(true);
I guess you have one customer per claim so its better if you rename customers() to customer() in claim model it makes more sense

Related

Favorite functionality for my laravel application

I'm currently trying to make a favorite functionality to my laravel application. I'm trying to access the post table with eloquent, but it says property posts(the function in the favorite model) does not exist.
Update: I updated the query. If I dump $favorite I get two items, which is correct, but now I get this error message instead:Property [posts] does not exist on the Eloquent builder instance. (View: C:\xampp\laravelprojects\Skakahand\resources\views\profile\index.blade.php)
<div class="favorite-section">
<p>Mina favoriter</p>
{{$favorite->posts->title}}
</div>
This is my controller:
public function index(User $user)
{
$favorite = Favorite::where('user_id', auth()->user()->id)
->get();
return view('profile.index',[
'user' => $user,
'favorite' => $favorite
]);
}
Favorite model:
class Favorite extends Model
{
use HasFactory;
protected $fillable = [
'user_id'
];
public function users()
{
return $this->belongsTo(User::class);
}
public function posts()
{
return $this->belongsTo(Post::class);
}
}
and post model:
class Post extends Model
{
use HasFactory;
/* use Sluggable; */
protected $fillable = [
'title',
'body',
'category',
'decision',
'number',
'place',
'image_path',
'slug',
'price',
'user_id',
];
public function user()
{
return $this->belongsTo(User::class);
}
public function favorites(){
return $this->hasMany(Favorite::class);
}
}
First correct Model like this
class Favorite extends Model
{
use HasFactory;
protected $fillable = [
'user_id',
'post_id',
];
public function user()
{
return $this->belongsTo(User::class);
}
public function post()
{
return $this->belongsTo(Post::class);
}
}
In controller change code like this for for avoid lazy loads
public function index(User $user)
{
$favorites = Favorite::where('user_id', auth()->user()->id)
->with('post')
->get();
return view('profile.index',[
'user' => $user,
'favorites' => $favorites
]);
}
in blade use code like
<div class="favorite-section">
<p>Mina favoriter</p>
<ul>
#foreach($favorites as $favorite)
<li>{{ $favorite->post->title ?? '' }} </li>
#endforeach
</ul>
</div>
just include ->with() for relationship,
your query should look like this
$favorite = Favorite::where('user_id', auth()->user()->id)->with('post')
->get();
return view('profile.index',compact('favorite','user'));

Laravel eloquent don't get relation model many to many relation

[][1]we can retrieve the Post model for a Comment by accessing the post "dynamic property
I have a Posts table
My Order Model
class Order extends Model
{
protected $table = 'orders';
protected $fillable = ['user_id', 'billing_phone', 'billing_address',
'payment_method', 'payment_status', 'product_id', 'order_status'];
}
public function products()
{
return $this->belongsToMany(Product::class, 'order_product', 'order_id', 'product_id');
}
}
My web route
Route::get('get-orders', function() {
$orders = \App\Models\Order::all();
foreach ($orders as $order) {
foreach ($order->products as $product) {
echo 'ID: ' . $product->name;
}
}
});
Now I want to get orders & its products, what is the problem?
When i due and dump this is the retun result
[1]: https://i.stack.imgur.com/IaqEv.png
Try this with better performance.
Order.php model:
class Order extends Model
{
protected $table = 'orders';
protected $fillable = [
'user_id',
'billing_phone',
'billing_address',
'payment_method',
'payment_status',
'product_id',
'order_status'
];
public function products()
{
return $this->belongsToMany(
Product::class,
'order_product',
'order_id',
'product_id'
);
}
}
web.php route file:
Route::get('get-orders', function() {
//use eager load here, better performance.
$orders = \App\Models\Order::with('products')->get();
foreach ($orders as $order) {
foreach ($order->products as $product) {
echo 'ID: ' . $product->name;
}
}
});

How can I add, delete and get a favorite from product with polymorphic relationship, in Laravel 5.6?

My product model like this :
<?php
...
class Product extends Model
{
...
protected $fillable = ['name','photo','description',...];
public function favorites(){
return $this->morphMany(Favorite::class, 'favoritable');
}
}
My favorite model like this :
<?php
...
class Favorite extends Model
{
...
protected $fillable = ['user_id', 'favoritable_id', 'favoritable_type'];
public function favoritable()
{
return $this->morphTo();
}
}
My eloquent query laravel to add, delete and get like this :
public function addWishlist($product_id)
{
$result = Favorite::create([
'user_id' => auth()->user()->id,
'favoritable_id' => $product_id,
'favoritable_type' => 'App\Models\Product',
'created_at' => Carbon::now()
]);
return $result;
}
public function deleteWishlist($product_id)
{
$result = Favorite::where('user_id', auth()->user()->id)
->where('favoritable_id', $product_id)
->delete();
return $result;
}
public function getWishlist($product_id)
{
$result = Favorite::where('user_id', auth()->user()->id)
->where('favoritable_id', $product_id)
->get();
return $result;
}
From the code above, I'm using parameter product_id to add, delete and get data favorite
What I want to ask here is : Whether the above is the correct way to add, delete and get data using polymorphic relationship?
Or is there a better way to do that?

Laravel 5.5 Relationships

I'm trying to implement relationships between models and i recieve "Trying to get property 'products' of non-object" and i don't understand why, because i used this before in the same way and it's worked fine.
The logic of relationship is that 1 Merchant hasMany Products
this is the code that i'm using:
Merchant Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Merchant extends Model {
protected $table = "merchants";
protected $fillable = [
'merchant_id', 'merchant_name', 'secret_key', 'merchant_address', 'merchant_phone', 'merchant_admin',
'merchant_contact', 'merchant_mail', 'merchant_description', 'enable', 'created_at', 'updated_at'];
public function users() {
//many to many
return $this->belongsToMany('App\User');
}
public function branchOffices() {
return $this->hasMany('App\BranchOffice', 'merchant_id', 'merchant_id');
}
public function products() {
return $this->hasMany('App\Products', 'merchant_id', 'merchant_id');
}
public function transactions() {
return $this->hasMany('App\Transaction', 'merchant_id', 'merchant_id');
}
public function readers() {
return $this->hasMany('App\Reader', 'merchant_id', 'merchant_id');
}
}
Product Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model {
protected $table = "products";
protected $fillable = [
'id', 'barcode', 'description', 'price', 'currency_id', 'merchant_id', 'branch_id',
'enable', 'created_at', 'updated_at'];
public function merchants() {
return $this->belongsTo('App\Merchant', 'merchant_id', 'merchant_id');
}
public function currencies() {
return $this->belongsTo('App\Currency', 'iso_4712', 'currency_id');
}
public function branch_sectors() {
return $this->belongsToMany('App\BranchSector');
}
}
And this is the method in ProductController:
public function merchantProducts() {
$products = Merchant::find('merchant_id')->products;
return $products;
}
If someone can help me i'll be very thankfull.
Thanks in advance!!
Assume merchant is not guaranteed existing in database giving merchant id, it is better off to check if merchant exists, and retrieves its products if so.
$products = collect();
$merchant = Merchant::find($merchant_id);
if($merchant) {
$products = $merchant->products;
}
return $products;
all!!
Finally i solved this problem using resources in this way:
public function merchantProducts(Request $request) {
$merchant_id = $request->merchant_id;
$products = Product::where('merchant_id', $merchant_id)->paginate(15);
return ProductResource::collection($products);
}
Thanks to all!!

type casting in laravel json response in relationships eager loading

This is my post model.
class Post extends Model
{
use SoftDeletes;
protected $table = 'posts';
protected $fillable = ['title','featuring_image', 'brief', 'body', 'seen_count'];
public function user(){
return $this->belongsTo(User::class);
}
public function comments()
{
return $this->hasMany(Comment::class);
}
public function someComments()
{
return $this->comments()->limit(Constants::COMMENTS_COUNT_LIMIT);
}
public function commentsCount()
{
return $this->comments()
->selectRaw('post_id, count(*) as count')
->groupBy('post_id');
}
public function likes()
{
return $this->hasMany(Like::class);
}
public function isLiked()
{
return $this->likes()->where('user_id', auth()->check() ? auth()->user()->id : 0);
}
public function likesCount()
{
return $this->likes()
->selectRaw('post_id, count(*) as count')
->groupBy('post_id');
}
}
I executed this query on this model.
$post = Post::with(['categories', 'user', 'commentsCount', 'likesCount', 'isLiked'])->find($post->id);
Because of the relation between this table and like and comment table, The output of this query for 'commentsCount', 'likesCount', 'isLiked' is an array. But I need to receive numbers for 'commentsCount' and 'likesCount', and a boolean for 'isliked' as an output, in laravel josn response.
You might find it easier to use the withCount() the comes with Eloquent instead.
Then for is_liked you could use a scope to get the value and the cast it to a boolean:
public function scopeIsLiked($query)
{
if (is_null($query->getQuery()->columns)) {
$query->select([$query->getQuery()->from . '.*']);
}
$relation = Relation::noConstraints(function () {
return $this->likes();
});
$q = $this->likes()->getRelationExistenceCountQuery(
$relation->getRelated()->where('user_id', auth()->check() ? auth()->user()->id : 0)->newQuery(), $query
);
$query->selectSub($q->toBase(), 'is_liked');
}
Please note you will need to add the use statement for Relation to the top of the class:
use Illuminate\Database\Eloquent\Relations\Relation;
You model could then look like:
class Post extends Model
{
use SoftDeletes;
protected $table = 'posts';
protected $fillable = ['title', 'featuring_image', 'brief', 'body', 'seen_count'];
public function user()
{
return $this->belongsTo(User::class);
}
public function comments()
{
return $this->hasMany(Comment::class);
}
public function someComments()
{
return $this->comments()->limit(Constants::COMMENTS_COUNT_LIMIT);
}
public function likes()
{
return $this->hasMany(Like::class);
}
/**
* Scope to add the "is_liked" flag.
*
* #param $query
*/
public function scopeIsLiked($query)
{
if (is_null($query->getQuery()->columns)) {
$query->select([$query->getQuery()->from . '.*']);
}
$relation = Relation::noConstraints(function () {
return $this->likes();
});
$q = $this->likes()->getRelationExistenceCountQuery(
$relation->getRelated()->where('user_id', auth()->check() ? auth()->user()->id : 0)->newQuery(), $query
);
$query->selectSub($q->toBase(), 'is_liked');
}
}
And your query would look something like:
$post = Post::with('categories', 'user')
->withCount('likes', 'comments')
->isLiked()
->find($post->id);
Hope this helps!
You can use Laravel casts:
Inside the each model you can add the following to cast a value, per example:
protected $casts = [
'isLiked' => 'boolean',
];
Rwd's answer gives a nice solution using scopes, but for laravel 5.4+ you could get away with aliasing the withCount() result and then casting it to boolean with a $cast variable on the model or an accessor (with accessor, you can only get snake case is_liked). This way we don't need to write complex scopes.
The model would be
class Post extends Model
{
// rest of model
protected $casts = ['isLiked'=>'boolean'];
public function likes()
{
return $this->hasMany(Like::class);
}
}
Then in your controller
$post = Post::with('categories', 'user')
->withCount(
[
'likes as likesCount', 'comments as commentsCount',
'likes as isLiked' =>function($query){
$query->where('user_id', auth()->check() ? auth()->user()->id : 0);
}
]
)
->find($post->id);
And now you get likesCount (int), commentsCount (int) and isLiked (boolean)

Resources