Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

lukaszj's avatar

fortify jetstream vue3

Hello Friends, in my project (stack inertia, vue, fortify), when i want to change avatar in user/profile, i have empty array. When I save without image is ok. I only added two custom fields. It's my UpdateUserProfileInformation file in action/ fortify. Please help :D

class UpdateUserProfileInformation implements UpdatesUserProfileInformation {

public function update(User $user, array $input): void
{

    Validator::make($input, [
        'first_name' => ['required', 'string', 'max:255'],
        'last_name' => ['required', 'string', 'max:255'],
        'email' => ['required', 'email', 'max:255', Rule::unique('users')->ignore($user->id)],
        'photo' => ['nullable', 'mimes:jpg,jpeg,png', 'max:1024'],
        'phone_number' => ['phone:AUTO,GB', 'nullable'],
    ])->validateWithBag('updateProfileInformation');

    if (isset($input['photo'])) {
        $user->profile->addMediaFromRequest('photo')->toMediaCollection('avatar');
    }

    if ($input['email'] !== $user->email &&
        $user instanceof MustVerifyEmail) {
        $this->updateVerifiedUser($user, $input);
    } else {
        $user->forceFill(Arr::except($input, ['phone_number', 'email']))->save();

        $user->profile->forceFill(
            ['phone_number' => $input['phone_number']]
        )->save();
    }
}

/**
 * Update the given verified user's profile information.
 *
 * @param  array<string, string>  $input
 */
protected function updateVerifiedUser(User $user, array $input): void
{
    $user->forceFill([
        'email' => $input['email'],
        'email_verified_at' => null,
    ])->save();

    $user->sendEmailVerificationNotification();
}

}

... and vue file

    <template #description>
        Update your account's profile information and email address.
    </template>

    <template #form>
        <!-- Profile Photo -->
        <div v-if="$page.props.jetstream.managesProfilePhotos" class="col-span-6 sm:col-span-4">
            <!-- Profile Photo File Input -->
            <input
                id="photo"
                ref="photoInput"
                type="file"
                class="hidden"
                @change="updatePhotoPreview"
            >

            <InputLabel for="photo" value="Photo" />

            <!-- Current Profile Photo -->
            <div v-show="! photoPreview" class="mt-2">
                <img :src="user.profile_photo_url" :alt="user.name" class="rounded-full h-20 w-20 object-cover">
            </div>

            <!-- New Profile Photo Preview -->
            <div v-show="photoPreview" class="mt-2">
                <span
                    class="block rounded-full w-20 h-20 bg-cover bg-no-repeat bg-center"
                    :style="'background-image: url(\'' + photoPreview + '\');'"
                />
            </div>

            <SecondaryButton class="mt-2 me-2" type="button" @click.prevent="selectNewPhoto">
                Select A New Photo
            </SecondaryButton>

            <SecondaryButton
                v-if="user.profile_photo_path"
                type="button"
                class="mt-2"
                @click.prevent="deletePhoto"
            >
                Remove Photo
            </SecondaryButton>

            <InputError :message="form.errors.photo" class="mt-2" />
        </div>

        <!-- Name -->
        <div class="col-span-6 sm:col-span-4">
            <InputLabel for="firstname" value="First name" />
            <TextInput
                id="firstname"
                v-model="form.first_name"
                type="text"
                class="mt-1 block w-full"
                required
                autocomplete="firstname"
            />
            <InputError :message="form.errors.first_name" class="mt-2" />
        </div>

        <div class="col-span-6 sm:col-span-4">
            <InputLabel for="lastname" value="Last name" />
            <TextInput
                id="lastname"
                v-model="form.last_name"
                type="text"
                class="mt-1 block w-full"
                autocomplete="lastname"
            />
            <InputError :message="form.errors.last_name" class="mt-2" />
        </div>

        <!-- Email -->
        <div class="col-span-6 sm:col-span-4">
            <InputLabel for="email" value="Email" />
            <TextInput
                id="email"
                v-model="form.email"
                type="email"
                class="mt-1 block w-full"
                required
                autocomplete="username"
            />
            <InputError :message="form.errors.email" class="mt-2" />

            <div v-if="$page.props.jetstream.hasEmailVerification && user.email_verified_at === null">
                <p class="text-sm mt-2">
                    Your email address is unverified.

                    <Link
                        :href="route('verification.send')"
                        method="post"
                        as="button"
                        class="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
                        @click.prevent="sendEmailVerification"
                    >
                        Click here to re-send the verification email.
                    </Link>
                </p>

                <div v-show="verificationLinkSent" class="mt-2 font-medium text-sm text-green-600">
                    A new verification link has been sent to your email address.
                </div>
            </div>
        </div>
        <div class="col-span-6 sm:col-span-4">
            <InputLabel for="phone_number" value="Phone" />
            <TextInput
                id="phone_number"
                v-model="form.phone_number"
                type="text"
                class="mt-1 block w-full"
                autocomplete="phone_number"
            />
            <InputError :message="form.errors.phone_number" class="mt-2" />
        </div>
    </template>

    <template #actions>
        <ActionMessage :on="form.recentlySuccessful" class="me-3">
            Saved.
        </ActionMessage>

        <PrimaryButton :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
            Save
        </PrimaryButton>
    </template>
</FormSection>
0 likes
0 replies

Please or to participate in this conversation.