tighten / parental

Use single table inheritance in your Laravel app
MIT License
1.36k stars 98 forks source link

Class strangeness in model events #44

Closed sburkett closed 5 years ago

sburkett commented 5 years ago

So I have a parent class Listing and a child class of EbayListing. The parent class has the HasChildren trait, and the EbayListing class has the HasParent trait.

Parent Listing class:

namespace App;

use Illuminate\Database\Eloquent\Model;

class Listing extends Model
{
  use \Tightenco\Parental\HasChildren;

  protected $childTypes = [
    'EbayListing' => \App\Marketplaces\Ebay\EbayListing::class,
    'ShopifyListing' => \App\Marketplaces\Shopify\ShopifyListing::class,
  ];
  ...
}

Child EbayListing class:

namespace App\Marketplaces\Ebay;

use Illuminate\Database\Eloquent\Model;

class EbayListing extends \App\Listing
{
  use \Tightenco\Parental\HasParent;
  ...
}

I wanted to set up a few model events to catch certain actions when they happen. Ok, cool, so I added this to the parent Listing class:

  /**
   * The event map for the model.
   *
   * @var array
   */
  protected $dispatchesEvents = [
    'saved'     => \App\Events\Models\Listing\ListingSaved::class,
    'updated'   => \App\Events\Models\Listing\ListingUpdated::class,
    'deleted'   => \App\Events\Models\Listing\ListingDeleted::class,
  ];

So I set up a test model event for 'deleted'. I made the event listener queueable as I wanted to test some things in the job queue. Now, the queuable delete job I'm queueing doesn't do anything, but I wanted to test things out to make sure I had the queue set up correctly.

So I used artisan to do find a Listing and invoke the delete() method on it:

>>> use App\Listing;
>>> $l = Listing::find(3095);
=> App\Marketplaces\Ebay\EbayListing {#3481
     id: 3095,
     type: "EbayListing",
     ....
     created_at: "2019-04-23 16:58:47",
     updated_at: "2019-04-23 16:58:47",
   }
>>> $l->delete();
=> true

So good, so far. It added the job to the jobs table, which is great, of course. However, the job failed when the artisan queue worker ran (which I thought was odd because the handle() method is empty. So I took a look at the failed_jobs table and saw that I got a good ol' ModelNotFoundException:

Illuminate\Database\Eloquent\ModelNotFoundException: No query results for model [App\Marketplaces\Ebay\EbayListing]. in /var/www/intelebase-dev/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php:452

So, I thought, perhaps the $dispatchesEvents needed to be in the child class instead of the parent, so I set that all up, but I got the same result.

Not really sure why it is complaining, though, as App\Marketplaces\Ebay\EbayListing is a valid model, though maybe it needs a backslash in front of the App in the class path. Not sure.

Any ideas?

sburkett commented 5 years ago

I'm going to try setting it up as an observer instead, just to see if it matters.

sburkett commented 5 years ago

Blah, Observers can't be queueable, so that won't work for me. Ugh.

sburkett commented 5 years ago

OMG ... never mind, I am so stupid. The deleted event occurs after the model has been deleted from the database. So obviously storing that event information serialized in a job won't work, since the id of the record is now longer there. Ok, closing this issue out, but hopefully it will help someone else one day :)