Repository: laravel/framework (php)

Issue:
HasAttributes->isRelation() returns wrongly TRUE when a new style Accessor is present
- Laravel Version: 9.0.2
- PHP Version: 8.0.15

### Description:
When calling `isRelation()` on a model, to test if a certain key is a relation, the function returns wrongly `true` when a Accessor-method is present.

### Steps To Reproduce:

```php
<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
 
class User extends Model
{
    protected function myname(): Attribute
    {
        return new Attribute(
            get: fn () => 'some value'
        );
    }
}
```

And than, somewhere in your application call this
```php
dd($user->isRelation('myname')); // returns TRUE
```

Since 'myname' is not a _relation_, but a _Accessor_, it is expected that `isRelation()` should return `false`.

A possible fix would be to do an extra check in the `isRelation()` method to test if a method is not a Accessor, but I'm not sure what's the best approach to do that.




Pull request:
[8.x] Fix `isRelation()` failing to check an `Attribute`
<!--
Please only send a pull request to branches that are currently supported: https://laravel.com/docs/releases#support-policy 

If you are unsure which branch your pull request should be sent to, please read: https://laravel.com/docs/contributions#which-branch

Pull requests without a descriptive title, thorough description, or tests will be closed.

In addition, please describe the benefit to end users; the reasons it does not break any existing features; how it makes building web applications easier, etc.
-->

If an Eloquent model has a attribute defined using the new Attribute class, `Model@isRelation(...)` returns true when checking for the attribute name,

This PR:

- Adds a `if` clause at `Model@isRelation(...)` to check if a attribute is defined with the same name
- Adds a test that would fail prior to the changes proposed

Note: I am sending this to 8.x as it seems to be a bugfix from the related issue's description.

Closes #40966 

Patch:
diff --git a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php
index 67e44605eb..81d21484b7 100644
--- a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php
+++ b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php
@@ -499,6 +499,10 @@ public function getRelationValue($key)
      */
     public function isRelation($key)
     {
+        if ($this->hasAttributeMutator($key)) {
+            return false;
+        }
+
         return method_exists($this, $key) ||
             (static::$relationResolvers[get_class($this)][$key] ?? null);
     }


Test patch:
diff --git a/tests/Database/DatabaseEloquentRelationTest.php b/tests/Database/DatabaseEloquentRelationTest.php
index 65df35655c..b87b32637b 100755
--- a/tests/Database/DatabaseEloquentRelationTest.php
+++ b/tests/Database/DatabaseEloquentRelationTest.php
@@ -4,6 +4,7 @@
 
 use Exception;
 use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Database\Eloquent\Casts\Attribute;
 use Illuminate\Database\Eloquent\Collection;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Eloquent\Relations\HasOne;
@@ -281,6 +282,14 @@ public function testRelationResolvers()
         $this->assertInstanceOf(EloquentResolverRelationStub::class, $model->customer());
         $this->assertSame(['key' => 'value'], $model->customer);
     }
+
+    public function testIsRelationIgnoresAttribute()
+    {
+        $model = new EloquentRelationAndAtrributeModelStub;
+
+        $this->assertTrue($model->isRelation('parent'));
+        $this->assertFalse($model->isRelation('field'));
+    }
 }
 
 class EloquentRelationResetModelStub extends Model
@@ -351,3 +360,25 @@ public function getResults()
         return ['key' => 'value'];
     }
 }
+
+class EloquentRelationAndAtrributeModelStub extends Model
+{
+    protected $table = 'one_more_table';
+
+    public function field(): Attribute
+    {
+        return new Attribute(
+            function ($value) {
+                return $value;
+            },
+            function ($value) {
+                return $value;
+            },
+        );
+    }
+
+    public function parent()
+    {
+        return $this->belongsTo(self::class);
+    }
+}