staudenmeir / eloquent-has-many-deep

Laravel Eloquent HasManyThrough relationships with unlimited levels
MIT License
2.67k stars 157 forks source link

BelongsTo via hasOneThrough #167

Closed mirzazeyrek closed 2 years ago

mirzazeyrek commented 2 years ago

Thanks for the awesome work on this package.

I check the readme but couldn't exactly found an example for my case:

What I'm trying to do is building a ->supplier relationship in Offer model:

class Offer extends Model implements
{
    use HasRelationships;

    /*
    public function supplier(): ?HasOneDeep
    {
        return $this->hasOneDeep(Supplier::class, [SupplierBranch::class, SupplierUser::class])->withTrashed();
    } */

    public function supplierBranch(): HasOneThrough
    {
        return $this->hasOneThrough(SupplierBranch::class, SupplierUser::class)->withTrashed();
    }
}

CREATE TABLE `offers` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  `deleted_at` timestamp NULL DEFAULT NULL,
  `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,
  `price` double NOT NULL DEFAULT '0',
  `accepted_at` timestamp NULL DEFAULT NULL,
  `declined_at` timestamp NULL DEFAULT NULL,
  `is_net` tinyint(1) NOT NULL DEFAULT '1',
  `shipping_costs` decimal(8,2) DEFAULT '0.00',
  `shipping_costs_tax` decimal(8,2) DEFAULT NULL,
  `valid_until` datetime DEFAULT NULL,
  `delivery_at` datetime DEFAULT NULL,
  `terms_accepted` json DEFAULT NULL,
  `token` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `requisition_id` bigint unsigned DEFAULT NULL,
  `supplier_invite_id` bigint unsigned DEFAULT NULL,
  `supplier_user_id` bigint unsigned DEFAULT NULL,
  `supplier_offer_no` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `import_metadata` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `tax_rate` int DEFAULT NULL,
  `delivery_time_estimate` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `delivery_time_estimate_comment` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `changes_requested_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `offers_requisition_id_foreign` (`requisition_id`),
  KEY `offers_supplier_invite_id_foreign` (`supplier_invite_id`),
  KEY `offers_supplier_user_id_foreign` (`supplier_user_id`),
  CONSTRAINT `offers_requisition_id_foreign` FOREIGN KEY (`requisition_id`) REFERENCES `requisitions` (`id`) ON DELETE CASCADE,
  CONSTRAINT `offers_supplier_invite_id_foreign` FOREIGN KEY (`supplier_invite_id`) REFERENCES `supplier_invites` (`id`) ON DELETE CASCADE,
  CONSTRAINT `offers_supplier_user_id_foreign` FOREIGN KEY (`supplier_user_id`) REFERENCES `supplier_users` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=120 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
<?php

class SupplierBranch extends Model
{
    use HasFactory;

    protected $touches = ['supplier'];

    public function supplier(): BelongsTo
    {
        return $this->belongsTo(Supplier::class)->withTrashed();
    }
}

CREATE TABLE `supplier_branches` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `phone_number` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `source` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `supplier_id` bigint unsigned NOT NULL,
  `address_id` int unsigned DEFAULT NULL,
  `deleted_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `supplier_branches_supplier_id_foreign` (`supplier_id`),
  CONSTRAINT `supplier_branches_supplier_id_foreign` FOREIGN KEY (`supplier_id`) REFERENCES `suppliers` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=126 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
staudenmeir commented 2 years ago

You can reuse the existing relationships:

    public function supplier(): ?HasOneDeep
    {
        return $this->hasOneDeepFromRelations($this->supplierBranch(), (new SupplierBranch)->supplier())
                    ->withTrashed('supplier_branches.deleted_at')
                    ->withTrashed();
    }