Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
},
"require": {
"spatie/laravel-data": "^4",
"laravel/framework": "^8|^9|^10|^11",
"laravel/framework": "^8|^9|^10|^11|^12",
"phpdocumentor/reflection-docblock": "^5.4",
"spatie/invade": "^2"
},
Expand Down
3 changes: 2 additions & 1 deletion src/Data/Operation.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Illuminate\Http\Response as HttpResponse;
use Illuminate\Routing\Route;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use ReflectionClass;
use ReflectionFunction;
use ReflectionMethod;
Expand Down Expand Up @@ -36,7 +37,7 @@ public static function fromRoute(Route $route, string $method): self

if (is_string($uses)) {
$controller_class = new ReflectionClass($route->getController());
$controller_function = $controller_class->getMethod($route->getActionMethod());
$controller_function = $controller_class->getMethod(Str::parseCallback($route->action['uses'])[1]);
Copy link

Copilot AI Dec 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For single action controllers (invokable controllers), Str::parseCallback($route->action['uses']) may return [class, null] if the action doesn't contain an '@' separator. Accessing [1] could give null, causing getMethod(null) to fail.

Consider using Str::parseCallback($route->action['uses'], '__invoke')[1] to provide a default method name for invokable controllers. Alternatively, $route->getActionMethod() already handles both regular and invokable controllers correctly.

Suggested change
$controller_function = $controller_class->getMethod(Str::parseCallback($route->action['uses'])[1]);
$controller_function = $controller_class->getMethod($route->getActionMethod());

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Dec 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test helper methodFromRoute in tests/Pest.php uses $route->getActionMethod() (line 53), but the production code now uses Str::parseCallback($route->action['uses'])[1]. This inconsistency means tests may pass while production code fails for invokable controllers.

Consider updating the test helper to use the same approach as the production code, or vice versa, to ensure tests accurately reflect production behavior.

Copilot uses AI. Check for mistakes.

echo $controller_class->name, "::", $controller_function->name, "\n";
Copy link

Copilot AI Dec 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This debugging echo statement should be removed before merging to production. It will output to stdout whenever an operation is created from a route, which is not appropriate for production code.

Suggested change
echo $controller_class->name, "::", $controller_function->name, "\n";

Copilot uses AI. Check for mistakes.
} elseif ($uses instanceof Closure) {
Expand Down
5 changes: 3 additions & 2 deletions src/Data/Property.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use ReflectionProperty;
use RuntimeException;
use Spatie\LaravelData\Data;
use Spatie\LaravelData\Data as LaravelData;
use Spatie\LaravelData\Support\Types\Storage\AcceptedTypesStorage;

class Property extends Data
{
Expand All @@ -27,7 +27,8 @@ public function getName(): string
*/
public static function fromDataClass(string $class): Collection
{
if (! is_a($class, LaravelData::class, true)) {
['kind' => $kind] = AcceptedTypesStorage::getAcceptedTypesAndKind($class);
if ($kind->isNonDataRelated()) {
throw new RuntimeException('Class does not extend LaravelData');
}

Expand Down
7 changes: 5 additions & 2 deletions src/Data/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use Spatie\LaravelData\Support\Factories\DataPropertyFactory;
use Spatie\LaravelData\Support\Transformation\TransformationContext;
use Spatie\LaravelData\Support\Transformation\TransformationContextFactory;
use Spatie\LaravelData\Support\Types\Storage\AcceptedTypesStorage;
use UnitEnum;
use Xolvio\OpenApiGenerator\Attributes\CustomContentType;
use Xolvio\OpenApiGenerator\Attributes\HttpResponseStatus;
Expand Down Expand Up @@ -236,7 +237,8 @@ protected static function fromData(string $type_name, bool $nullable): self
{
$type_name = ltrim($type_name, '\\');

if (! is_a($type_name, LaravelData::class, true)) {
['kind' => $kind] = AcceptedTypesStorage::getAcceptedTypesAndKind($type_name);
if ($kind->isNonDataRelated()) {
throw new RuntimeException("Type {$type_name} is not a Data class");
}

Expand All @@ -259,7 +261,8 @@ protected static function fromDataCollection(string $type_name, bool $nullable):
{
$type_name = ltrim($type_name, '\\');

if (! is_a($type_name, LaravelData::class, true)) {
['kind' => $kind] = AcceptedTypesStorage::getAcceptedTypesAndKind($type_name);
if ($kind->isNonDataRelated()) {
throw new RuntimeException("Type {$type_name} is not a Data class");
}

Expand Down