diff --git a/README.md b/README.md index a34199c..d3cbadf 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,15 @@ SelectTree::make('category_id') ->relationship('category', 'name', 'parent_id') ``` +## Usage without relationships + +Use the tree without relationship + +```php +SelectTree::make('category_id') + ->query(fn() => Category::query(), 'name', 'parent_id') +``` + ## Custom Query Customize the parent query diff --git a/src/SelectTree.php b/src/SelectTree.php index e7f9716..903c973 100644 --- a/src/SelectTree.php +++ b/src/SelectTree.php @@ -15,6 +15,7 @@ use Filament\Schemas\Components\Contracts\HasAffixActions; use Filament\Schemas\Schema; use Filament\Support\Facades\FilamentIcon; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Support\Arr; @@ -54,11 +55,13 @@ class SelectTree extends Field implements HasAffixActions protected bool $grouped = true; - protected string|Closure $relationship; + protected Closure|Builder|null $query = null; - protected ?Closure $modifyQueryUsing; + protected string|Closure|null $relationship = null; - protected ?Closure $modifyChildQueryUsing; + protected ?Closure $modifyQueryUsing = null; + + protected ?Closure $modifyChildQueryUsing = null; protected Closure|int $defaultOpenLevel = 0; @@ -158,8 +161,8 @@ protected function setUp(): void protected function buildTree(): Collection { // Start with two separate query builders - $nullParentQuery = $this->getRelationship()->getRelated()->query()->where($this->getParentAttribute(), $this->getParentNullValue()); - $nonNullParentQuery = $this->getRelationship()->getRelated()->query()->whereNot($this->getParentAttribute(), $this->getParentNullValue()); + $nullParentQuery = $this->getQuery()->clone()->where($this->getParentAttribute(), $this->getParentNullValue()); + $nonNullParentQuery = $this->getQuery()->clone()->whereNot($this->getParentAttribute(), $this->getParentNullValue()); // If we're not at the root level and a modification callback is provided, apply it to null query if ($this->modifyQueryUsing) { @@ -272,6 +275,17 @@ public function relationship(string $relationship, string $titleAttribute, strin return $this; } + public function query(Builder|Closure|null $query, string $titleAttribute, string $parentAttribute, ?Closure $modifyQueryUsing = null, ?Closure $modifyChildQueryUsing = null): static + { + $this->query = $query; + $this->titleAttribute = $titleAttribute; + $this->parentAttribute = $parentAttribute; + $this->modifyQueryUsing = $modifyQueryUsing; + $this->modifyChildQueryUsing = $modifyChildQueryUsing; + + return $this; + } + public function withCount(bool $withCount = true): static { $this->withCount = $withCount; @@ -333,11 +347,23 @@ public function append(Closure|array|null $append = null): static return $this; } - public function getRelationship(): BelongsToMany|BelongsTo + public function getRelationship(): BelongsToMany|BelongsTo|null { + if (is_null($this->relationship)) { + return null; + } return $this->getModelInstance()->{$this->evaluate($this->relationship)}(); } + public function getQuery(): ?Builder + { + if (! is_null($this->query)) { + return $this->evaluate($this->query); + } + + return $this->getRelationship()->getRelated()->query(); + } + public function getTitleAttribute(): string { return $this->evaluate($this->titleAttribute);