l5-repository icon indicating copy to clipboard operation
l5-repository copied to clipboard

(Need help ) having problem including relationship with repository

Open ThinkDevStudios opened this issue 5 years ago • 1 comments

Hi! I would like to query shop_customers table that has the following shop ids and includes customers data on the query.

Shop Customer Model

class ShopCustomer extends Model implements Transformable
{
public function shop()
    {
        return $this->belongsTo(Shop::class, 'shop_id', 'id');
    }

    public function customer()
    {
        return $this->belongsTo(Customer::class, 'customer_id', 'id');
    }
}

Shop Model

class Shop extends Model implements Transformable
{
    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function shopCustomers()
    {
        return $this->hasMany(ShopCustomer::class);
    }
}

Customer Model

class Customer extends Model implements Transformable
{
    public function shopCustomers()
    {
        return $this->belongsTo(ShopCustomer::class, 'id', 'customer_id');
    }
}

Now with eloquent I was able to solve this but I am using use Balping\HashSlug\HasHashSlug; on repository.

Eloquent

$shops = Shop::where('user_id', $user->id)->pluck('id')->toArray();
$customers = ShopCustomer::with('customer')->where('shop_id', $shops)->get()->toArray();

This is the equivalent query and it works except for displaying the slug

select `customer_id` from `shop_customers` where `shop_id` in (19)
select * from `shop_customers` where `shop_id` = 19
select * from `customers` where `customers`.`id` in (24, 25, 26)

and the output is this

info
array:3 [▼
  0 => array:4 [▼
    "id" => 15
    "shop_id" => 19
    "customer_id" => 24
    "customer" => array:18 [▼
      "id" => 24
      "first_name" => "Colin 22"
      "last_name" => "Powlowski"
      "contacts" => "{"type":"mobile","number":"(866) 741-3896"}"
      "email" => "[email protected]"
      "notes" => "Vel iste possimus veniam. Ad unde cum sit. Veniam alias praesentium nesciunt rerum. Rerum repudiandae quaerat et nesciunt esse id voluptas fugit."
      "company" => "Towne Ltd"
      "referral_source" => "["website","friend"]"
      "address1" => "8442 Florida Knolls Suite 679"
      "address2" => "Suite 473"
      "city" => "ton"
      "province" => "Metro Manila"
      "zip_code" => 4551
      "tax_excempt" => 0
      "discounted" => 0
      "labor_override" => 0
      "price_matrix_override" => 0
      "deleted_at" => null
    ]
  ]
  1 => array:4 [▶]
  2 => array:4 [▶]
]

Any idea on how to implement this result using the repository? I tried the following

            $customers = $this->newrep->with(['customer'])->whereHas('customer', function($query) use ($shops) {
                $query->where('shop_id', $shops);
            })->all();

The query that it does is

select * from `shop_customers` where exists (select * from `customers` where `shop_customers`.`customer_id` = `customers`.`id` and `shop_id` = 19)
select * from `customers` where `customers`.`id` in (24, 25, 26)

and returns

info
array:1 [▼
  "data" => array:3 [▼
    0 => array:5 [▶]
    1 => array:5 [▼
      "slug" => "mQ4ZA"
      "shop_id" => 19
      "customer_id" => 25
      "created_at" => Carbon @1569392993 {#712 ▶}
      "updated_at" => Carbon @1569392993 {#713 ▶}
    ]
    2 => array:5 [▶]
  ]
]

Appreciate in advance any suggestions you can provide. Thank you!.

ThinkDevStudios avatar Sep 27 '19 07:09 ThinkDevStudios

First of all I would like to say that according to your query variable $shops is an array of ids, then you must use whereIn method. Yours:

$shops = Shop::where('user_id', $user->id)->pluck('id')->toArray();
$customers = ShopCustomer::with('customer')->where('shop_id', $shops)->get()->toArray();

Suggestion:

$shops = Shop::where('user_id', $user->id)->pluck('id')->toArray();
$customers = ShopCustomer::with('customer')->whereIn('shop_id', $shops)->get()->toArray();

Secondly you can shorten code if $shops not needed further:

$customers = $user->shops()->with('shopCustomer.customer')->get()->pluck('shopCustomer')->toArray();

shops() is a relation in User model

public function shops(){
return $this->hasMany(Shop::class); // if user has one shop then replace hasMany with hasOne and change method name to `shop()` as it would more appropriate
} 

and shopCustomer is a relation in Shop model

public function shopCustomer(){
return $this->hasMany(ShopCustomer::class);
}

or

$customers = ShopCustomer::with('customer')->where('shop_id', $user->shops()->pluck('id')->toArray())->get()->toArray();

or if $shops not an array of ids

$shop = Shop::where('user_id', $user->id)->first(); // $user->shop
$customers = ShopCustomer::with('customer')->where('shop_id', $shop->id)->get()->toArray();

Now coming to your issue, I am supposing these things:

  1. User has many shops because you have written this query: $shops = Shop::where('user_id', $user->id)->pluck('id')->toArray();
  2. $this->newrep is instanceof ShopCustomerRepository implemented in ShopCustomerEloquentRepositoy.
  3. You are using your own model in respective repository and not the Entities provided by the package.

To check this, your model ShopCustomer namespace must be correct in ShopCustomerRepositoryEloquent. It must be like App\ShopCustomers or App\SomeOtherDirectory\ShopCustomer if you models are located in a some other directory.

Your query:

$customers = $this->newrep->with('customer')->whereHas('customer', function($query) use ($shops) {
                $query->where('shop_id', $shops);
            })->all();

Solution 1 (staying as you are):

$shops = Shop::where('user_id', $user->id)->pluck('id')->toArray();
$customers = $this->newrep->with('customer')->findWhereIn('shop_id',$shops)->toArray();

or (if $shops not an array of ids)

$shop = Shop::where('user_id', $user->id)->first(); 
$customers = $this->newrep->with('customer')->findWhere('shop_id',$shop->id)->toArray();

Solution 1 End.

Solution 2 (if you are going add extra relations as I mentioned above): add a new method userShopsRelatedShopCustomers(), or name it as you like, in your ShopCustomerRepositoryEloquent

public function userShopsRelatedShopCustomers(){
$customers = $user->shops()->with('shopCustomer.customer');
return $customers;
}

and use it like:

$customers = $this->newrep->userShopsRelatedShopCustomers()->get()->pluck('shopCustomer')->toArray();

or

public function userShopsRelatedShopCustomers(){

$customers = $this->with('customer')->findWhere('user_id',$user->id);
return $customers;
}

and use it like:

$customers = $this->newrep->userShopsRelatedShopCustomers()->toArray();

Solution 2 End.

I again repeat if $shops (means array of ids) or $shop(means id), then replace the respective shop or shops function in User model and correct naming according to it...

junaid-A-khan avatar Oct 03 '19 15:10 junaid-A-khan