diff --git a/src/Taxonomies/TaxonomyRepository.php b/src/Taxonomies/TaxonomyRepository.php index cc4372c4..2791d6af 100644 --- a/src/Taxonomies/TaxonomyRepository.php +++ b/src/Taxonomies/TaxonomyRepository.php @@ -40,11 +40,18 @@ public function all(): Collection public function findByHandle($handle): ?TaxonomyContract { - $taxonomyModel = Blink::once("eloquent-taxonomies-{$handle}", function () use ($handle) { + $blinkKey = "eloquent-taxonomies-{$handle}"; + $taxonomyModel = Blink::once($blinkKey, function () use ($handle) { return app('statamic.eloquent.taxonomies.model')::whereHandle($handle)->first(); }); - return $taxonomyModel instanceof Model ? app(TaxonomyContract::class)->fromModel($taxonomyModel) : null; + if (! $taxonomyModel instanceof Model) { + Blink::forget($blinkKey); + + return null; + } + + return app(TaxonomyContract::class)->fromModel($taxonomyModel); } public function findByUri(string $uri, ?string $site = null): ?Taxonomy diff --git a/src/Taxonomies/TermQueryBuilder.php b/src/Taxonomies/TermQueryBuilder.php index ee8368d4..126e866d 100644 --- a/src/Taxonomies/TermQueryBuilder.php +++ b/src/Taxonomies/TermQueryBuilder.php @@ -174,6 +174,11 @@ public function get($columns = ['*']) { $this->applyCollectionAndTaxonomyWheres(); + // Ensure 'taxonomy' is always selected as it's required for Term::fromModel(). + if (! in_array('*', $columns) && ! in_array('taxonomy', $columns)) { + $columns[] = 'taxonomy'; + } + $items = parent::get($columns); // If a single collection has been queried, we'll supply it to the terms so @@ -212,6 +217,11 @@ public function paginate($perPage = null, $columns = [], $pageName = 'page', $pa { $this->applyCollectionAndTaxonomyWheres(); + // Ensure 'taxonomy' is always selected as it's required for Term::fromModel(). + if (! in_array('*', $columns) && ! in_array('taxonomy', $columns)) { + $columns[] = 'taxonomy'; + } + return parent::paginate($perPage, $columns, $pageName, $page); } diff --git a/tests/Terms/TermTest.php b/tests/Terms/TermTest.php index 36d99871..c1c9b9d6 100644 --- a/tests/Terms/TermTest.php +++ b/tests/Terms/TermTest.php @@ -9,8 +9,10 @@ use Statamic\Eloquent\Entries\Entry; use Statamic\Eloquent\Taxonomies\Taxonomy; use Statamic\Eloquent\Taxonomies\TermModel; +use Statamic\Facades\Blink; use Statamic\Facades\Collection; use Statamic\Facades\Stache; +use Statamic\Facades\Taxonomy as TaxonomyFacade; use Statamic\Facades\Term as TermFacade; use Statamic\Statamic; use Statamic\Testing\Concerns\PreventsSavingStacheItemsToDisk; @@ -117,4 +119,41 @@ public function it_applies_taxonomy_wheres_using_pluck_count_and_get() $this->assertSame(1, $taxonomy->queryTerms()->count()); $this->assertSame($term->slug(), $taxonomy->queryTerms()->get()->pluck('slug')->first()); } + + #[Test] + public function it_does_not_cache_null_taxonomy_lookups() + { + $taxonomy = TaxonomyFacade::findByHandle('future'); + $this->assertNull($taxonomy); + + // Create taxonomy directly in DB, bypassing TaxonomyRepository::save(). + $modelClass = app('statamic.eloquent.taxonomies.model'); + $modelClass::create([ + 'handle' => 'future', + 'title' => 'Future Taxonomy', + 'sites' => ['en'], + 'settings' => [], + ]); + + $taxonomy = TaxonomyFacade::findByHandle('future'); + + $this->assertNotNull($taxonomy); + $this->assertEquals('future', $taxonomy->handle()); + } + + #[Test] + public function it_queries_terms_with_taxonomy_available() + { + Taxonomy::make('tags')->title('Tags')->save(); + TermFacade::make('test-tag')->taxonomy('tags')->data(['title' => 'Test Tag'])->save(); + + Blink::flush(); + + $terms = TermFacade::query()->get(); + + $this->assertCount(1, $terms); + $this->assertEquals('test-tag', $terms->first()->slug()); + $this->assertNotNull($terms->first()->taxonomy()); + $this->assertEquals('tags', $terms->first()->taxonomy()->handle()); + } }