laravel / nova-issues

556 stars 34 forks source link

ResourceId no longer accessible on custom rules validations (using Illuminate\Contracts\Validation\Rule) #5770

Closed WillyReyno closed 1 year ago

WillyReyno commented 1 year ago

Description:

Since upgrading from Nova 4.25.1 to 4.26.5 & Laravel v10.13.5 to v10.17.1, I no longer have access to the resourceId when using custom rules.

I don't know if my usage was correct but here how I was doing it

app/Nova/Post.php

Text::make('Slug')->rules(new UniqueShortLinkSlug($this->id)),

And my custom rule (using the now deprecated Rule)

<?php

namespace App\Rules;

use App\Models\Post;
use Illuminate\Contracts\Validation\Rule; 

class UniqueShortLinkSlug implements Rule
{
    private ?int $existingId;

    public function __construct(private ?int $postId)
    {
    }

    /**
     * Determine if the validation rule passes.
     *
     * @param string $attribute
     * @param mixed $value
     *
     * @return bool
     */
    public function passes($attribute, $value)
    {
        $postWithSameSlug = Post::where('id', '!=', $this->postId)
            ->where(function ($query) use ($value) {
                $query->where('slug', '=', $value)
                    ->orWhereJsonContains('alt_slugs', $value);
            })->first();

        $this->existingId = $postWithSameSlug ? $postWithSameSlug->id : null;

        return !$postWithSameSlug;
    }

    /**
     * Get the validation error message.
     */
    public function message(): string
    {
        return 'Slug is already used by another entry in database. (post id ' . $this->existingId . ')';
    }
}

Now the id is always null, so I can't use the resource id within my rules.

I also tried migrating to the new ValidationRule, but even while implementing DataAwareRules I can't retrieve the id within $this->data.

Detailed steps to reproduce the issue on a fresh Nova installation:

I don't have time to make a reproduction repository right now, but I could do it in a few days if needed.

crynobone commented 1 year ago

Please provide full reproducing repository based on fresh installation as suggested in the bug report template (or you can refer to https://github.com/nova-issues for example)

Internally we only send the $request to Rule class and fetch the value from the request.

WillyReyno commented 1 year ago

Just for those who might encounter the same issue, my solution was to refactor to the new ValidationRule and add a Hidden::make('ID', 'id') field on my resource to have the id appear in $this->data['id'] thanks to DataAwareRules.

The regular ID::make() doesn't show up in it because it's not shown on forms.

crynobone commented 1 year ago

Just to clarify, ID::make() was never shown in forms in Nova 4 and 3, so it shouldn't be related to upgrading from Nova 4.25.1 to 4.26.5