Handling User Preferences from a JSON Field in Laravel
Content Index
In this section, I want to show you how I implemented the user preferences part. For now, we can consider two preferences:
- Dark Mode (darkmode)
- Autoplay (autoplay)
The initial idea might be to add columns to the users table for each preference, but this isn't scalable if we think of 10 more preferences later on, nor am I keen on adding too many fields to the user entity. Another option would be to create a one-to-one relational table, but it seemed too complicated for something so simple.
That's why I opted for a simpler solution using JSON.
Let's remember that we left off on how we can use the domain and subdomain system in Laravel.
User Preferences Based on JSON
So, the first thing I want to show you is that, from Laravel, which is where I have all the information, I print the user entity into a constant:
<script>
window.Laravel = {!! json_encode([
'user' => Auth::user(),
]) !!}
</script>This way, I am sharing user data, including a user field to handle extra data like user preference and autoplay in JSON format.
So, if we check the migration here, you'll see that the field is simply of type String:
$table->string('extra')->nullable()->default('');Reading Preferences in Vue
To access these preferences from Vue, we simply parse the JSON from the `window.Laravel` object:
created() {
this.user = window.Laravel.user;
}The value of each preference is handled as a toggle (true or false), for example, `true` for enabled and `false` for disabled.
Updating Preferences in Laravel
A global method is created in Laravel to handle all preferences, called `setExtra()`. This method:
- Gets the authenticated user (`Auth::user()` or `auth('sanctum')->user()`).
- Decodes the `extra` field into JSON, returning an empty object if it doesn't exist or is malformed.
- Updates only the preferences sent in the request.
function setExtra()
{
$user = Auth::user() ?? auth('sanctum')->user();
// si $user->extra tiene algun valor invalido, restablece a un objeto limpio
$extra = json_decode($user->extra ?? "{}") ?? json_decode("{}");
if (request("autoplay")) {
$extra->autoplay = request("autoplay") == 1 ? true : false;
}
if (request("darkmode")) {
$extra->darkmode = request("darkmode") == 1 ? true : false;
}
$user->update([
'extra' => json_encode($extra)
]);
}Reading Preferences in Vue (Dynamic Update)
From Vue, we can read and update the preferences this way:
setExtraUser() {
try {
const extra = JSON.parse(window.Laravel.user.extra)
this.isDarkMode = extra.darkmode;
this.autoplay = extra.autoplay ? true : false;
if (!this.isDarkMode)
document.querySelector("html").classList.remove("dark");
} catch (error) {
// console.error(error)
}
},If a new preference, like darkmode or autoplay, is activated, the complete object is updated, preserving the previous values. This allows for easy extension of preferences without adding new columns to the database.
Advantages of this Implementation
- Simplicity: No need to create multiple columns in the users table.
- Scalability: We can add new preferences without modifying the database.
- Security: We always check if the preference exists and perform safe casting to avoid errors.
- Vue Compatibility: We can dynamically update and read preferences in the interface.
In summary, this strategy of using a JSON field for user preferences is simpler, more flexible, and more extensible than creating multiple columns or additional relationships in the database.
The next step is to learn how you can use Vue 3 with Laravel.
I agree to receive announcements of interest about this Blog.
I'm going to show you a scheme to manage user preferences such as autoplay, language or darkmode in Laravel through a field.