Repository: laravel/framework (php)

Issue:
Prepending component attributes causes an exception when said attribute is missing in calling template
- Laravel Version: 8.13
- PHP Version: 7.4
- Database Driver & Version: none

### Description:

Rendering a component with prepended attributes but without overriding that attribute in the calling template yields an error.

### Steps To Reproduce:

- `composer create-project laravel/laravel testing`
- `php artisan make:component TestComponent`
- Copy the example from the docs into the template

```blade
<div {{ $attributes->merge(['data-controller' => $attributes->prepends('profile-controller')]) }}>
    {{ $slot }}
</div>
```
- attempt to render the component without 'data-controller' specified.

Rendering this component like so: `<x-test-component data-controller="some-controller" />` works as expected.

Rendering this component like so: `<x-test-component />` yields the following error:
<img width="1209" alt="Screen Shot 2020-11-06 at 13 59 09" src="https://user-images.githubusercontent.com/6180087/98340888-41417b80-2038-11eb-852c-a6815f5f7b72.png">

I would expect to have the string `profile-controller` to be the default and only value present if no attribute named `data-controller` is specified.


Pull request description:
[8.x] Fix appendable attributes in Blade components
Currently, attempting to render a component which prepends a non-class attribute in it's template without actually overriding it in the calling template yields an Exception.

For example, given the following component called `test-component`:

```blade
<div {{ $attributes->merge(['data-controller' => $attributes->prepends('profile-controller')]) }}>
    {{ $slot }}
</div>
```

Rendering this component like so: `<x-test-component data-controller="some-controller" />` works as expected.

Rendering this component like so: `<x-test-component />` yields the following error:

<img width="1209" alt="Screen Shot 2020-11-06 at 13 59 09" src="https://user-images.githubusercontent.com/6180087/98340888-41417b80-2038-11eb-852c-a6815f5f7b72.png">

This PR fixes this behavior. `<x-test-component />` will now properly render as
```
<div data-controller="profile-controller"></div>
```

See #35128 for more details.


Patch:
diff --git a/src/Illuminate/View/AppendableAttributeValue.php b/src/Illuminate/View/AppendableAttributeValue.php
index 490ca408cd..f275801e4e 100644
--- a/src/Illuminate/View/AppendableAttributeValue.php
+++ b/src/Illuminate/View/AppendableAttributeValue.php
@@ -21,4 +21,14 @@ public function __construct($value)
     {
         $this->value = $value;
     }
+
+    /**
+     * Get the string value.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return (string) $this->value;
+    }
 }


Test patch:
diff --git a/tests/Integration/View/BladeTest.php b/tests/Integration/View/BladeTest.php
index e045be2a6d..48564b271d 100644
--- a/tests/Integration/View/BladeTest.php
+++ b/tests/Integration/View/BladeTest.php
@@ -50,11 +50,17 @@ public function test_rendering_the_same_dynamic_component_with_different_attribu
 
     public function test_appendable_attributes()
     {
-        $view = View::make('uses-appendable-panel', ['name' => 'Taylor'])->render();
+        $view = View::make('uses-appendable-panel', ['name' => 'Taylor', 'withOutside' => true])->render();
 
         $this->assertSame('<div class="mt-4 bg-gray-100" data-controller="inside-controller outside-controller" foo="bar">
     Hello Taylor
 </div>', trim($view));
+
+        $view = View::make('uses-appendable-panel', ['name' => 'Taylor', 'withOutside' => false])->render();
+
+        $this->assertSame('<div class="mt-4 bg-gray-100" data-controller="inside-controller" foo="bar">
+    Hello Taylor
+</div>', trim($view));
     }
 
     protected function getEnvironmentSetUp($app)
diff --git a/tests/Integration/View/templates/uses-appendable-panel.blade.php b/tests/Integration/View/templates/uses-appendable-panel.blade.php
index 91de44552d..df3f2698c5 100644
--- a/tests/Integration/View/templates/uses-appendable-panel.blade.php
+++ b/tests/Integration/View/templates/uses-appendable-panel.blade.php
@@ -1,3 +1,9 @@
-<x-appendable-panel class="bg-gray-100" :name="$name" data-controller="outside-controller" foo="bar">
-    Panel contents
-</x-appendable-panel>
+@if ($withOutside)
+    <x-appendable-panel class="bg-gray-100" :name="$name" data-controller="outside-controller" foo="bar">
+        Panel contents
+    </x-appendable-panel>
+@else
+    <x-appendable-panel class="bg-gray-100" :name="$name" foo="bar">
+        Panel contents
+    </x-appendable-panel>
+@endif