diff --git a/src/HasUniqueUrls.php b/src/HasUniqueUrls.php index 44197a0..4a7b81e 100644 --- a/src/HasUniqueUrls.php +++ b/src/HasUniqueUrls.php @@ -18,6 +18,55 @@ trait HasUniqueUrls abstract public function urlHandler(): array; + /** + * Initialize the HasUniqueUrls trait for an instance. + * + * @throws Exception + */ + public function initializeHasUniqueUrls(): void + { + $this->checkForConflictingAttributes(); + } + + /** + * Check if the model has conflicting 'url' or 'urls' attributes. + * + * @throws Exception + */ + private function checkForConflictingAttributes(): void + { + $conflictingAttributes = ['url', 'urls']; + $modelClass = get_class($this); + + foreach ($conflictingAttributes as $attribute) { + // Check if attribute exists in fillable, guarded, or as a database column + if ($this->hasColumn($attribute)) { + throw new Exception( + "Model [{$modelClass}] has a conflicting column '{$attribute}'. " . + "The HasUniqueUrls trait uses 'urls' as a relationship name and provides 'relative_url' and 'absolute_url' attributes. " . + "Please rename the '{$attribute}' column in your model to avoid conflicts." + ); + } + } + } + + /** + * Check if the model has a specific column. + */ + private function hasColumn(string $column): bool + { + try { + // Check if the table exists and has the column + if ($this->getConnection()->getSchemaBuilder()->hasColumn($this->getTable(), $column)) { + return true; + } + } catch (\Exception $e) { + // If we can't check the schema (e.g., during testing without migrations), skip the check + } + + return false; + } + /** * Generate a unique URL for the model. * diff --git a/tests/HasUniqueUrlsTest.php b/tests/HasUniqueUrlsTest.php index 32f4a64..3a65f01 100644 --- a/tests/HasUniqueUrlsTest.php +++ b/tests/HasUniqueUrlsTest.php @@ -1,6 +1,8 @@ relative_url)->toEqual(app()->getLocale()."/parent/test".($i > 0 ? "_".$i : "")); } }); + +test('12. Check if exception is thrown when model has conflicting url column', function () { + // Create a table with 'url' column + Schema::create('models_with_url_column', function (Blueprint $table) { + $table->increments('id'); + $table->string('name'); + $table->string('url'); + }); + + // Create a model class that uses HasUniqueUrls trait + // The exception should be thrown during model instantiation + expect(function () { + $modelClass = new class () extends \Illuminate\Database\Eloquent\Model { + use \Vlados\LaravelUniqueUrls\HasUniqueUrls; + + protected $table = 'models_with_url_column'; + protected $guarded = []; + public $timestamps = false; + + public function urlHandler(): array + { + return [ + 'controller' => \Vlados\LaravelUniqueUrls\Tests\TestUrlHandler::class, + 'method' => 'view', + 'arguments' => [], + ]; + } + + public function urlStrategy($language, $locale): string + { + return \Illuminate\Support\Str::slug($this->name); + } + }; + + $modelClass::create(['name' => 'test', 'url' => 'test-url']); + })->toThrow(Exception::class, "has a conflicting column 'url'"); + + Schema::dropIfExists('models_with_url_column'); +}); + +test('13. Check if exception is thrown when model has conflicting urls column', function () { + // Create a table with 'urls' column + Schema::create('models_with_urls_column', function (Blueprint $table) { + $table->increments('id'); + $table->string('name'); + $table->string('urls'); + }); + + // Create a model class that uses HasUniqueUrls trait + // The exception should be thrown during model instantiation + expect(function () { + $modelClass = new class () extends \Illuminate\Database\Eloquent\Model { + use \Vlados\LaravelUniqueUrls\HasUniqueUrls; + + protected $table = 'models_with_urls_column'; + protected $guarded = []; + public $timestamps = false; + + public function urlHandler(): array + { + return [ + 'controller' => \Vlados\LaravelUniqueUrls\Tests\TestUrlHandler::class, + 'method' => 'view', + 'arguments' => [], + ]; + } + + public function urlStrategy($language, $locale): string + { + return \Illuminate\Support\Str::slug($this->name); + } + }; + + $modelClass::create(['name' => 'test', 'urls' => 'test-urls']); + })->toThrow(Exception::class, "has a conflicting column 'urls'"); + + Schema::dropIfExists('models_with_urls_column'); +});