Handling User Preferences from a JSON Field in Laravel

Here I wanted to show you a little how I implemented the user preferences part so I can call them. For now it would be one that can come up with, well the first preference for example would be dark mode but later I came up with another one that is for autoplay.
The most direct reference would be to create here in the user table a column for Dark Mode another column for autoplay and so on until you come up with 10 more preferences, which doesn't quite convince me since obviously you're adding fields and fields and fields on the user entity that already has many for such simple things. It doesn't seem to me that you could add a relational table, that is, a one-to-one relationship but it seems even more complicated to me in the sense that for something as simple as a preference you would have to be managing those structures and then bringing that information from Arabic if it exists if it doesn't exist and the whole question. I wanted something simpler, what occurred to me I'll show you below.

JSON-based user preferences

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 in a constant:

<script>
   window.Laravel = {!! json_encode([
       'user' => Auth::user(),
   ]) !!}
</script>

In this way, I am sharing user data, including a user field to manage extra data such as user preference and autoplay in JSON format.

So if we do this in the migration you will see which field is simply of type String:

$table->string('extra')->nullable()->default('');

So now that it's a little clearer what the field is and how I'm printing it here to have those references in Vue, let's see how I manage it. It's really very simple. Here, the first thing I do is read those preferences from the windows object, since in the end, that object that was showing you is a variable that is built here windows laravel and I can read it perfectly from Vue, just as you can see, since it's a json, I simply parse it and here I reference its values, just as you can see, so that's the first strategy:

created() {
    this.user = window.Laravel.user;
}

Notice that I am passing one if it is true and minus one if it is false you can try with true or false sometimes zero does not arrive So I preferred to do it this way to always receive that data The important thing is that it is of type toggle true or false so I can play with any value that I consider in this case those mentioned and here I have a Global method in Laravel that allows me to define all these preferences that I called as estra then here obviously we get the authenticated user either through cookies or the session after this what we do is a cast here it is interesting since it is what I was telling you, remember that this function if you pass anything to it it will return a section what it expects to receive is an object therefore if this is null or simply an empty String it would give a section and that is why here I do a verification before casting if this is null or simply empty it would return an empty object then why would this work is because if for any reason this is malformed then simply return an empty object again if this is different from empty or null:

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)
    ]);
}

It is important to check if this is happening because of what was mentioned before because this method is global, therefore any other preference I will always manage from here and the preferences are sent individually here again. Note that I am only sending the Dark mode and it does not give autoplay, therefore, it only updates the darkmode conditional.

If we review what we have in the database, it is nothing more than a json, for example I am going to put the autoplay, I am going to reload here again here. Note that the autoplay is false but there is nothing about Dark Mode:

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)
 }
},

I'm going to set it to true for example here it would appear as true and now I go with Dark Mode and if we check here it is also there and it is attached to the data that we had before. So this is thanks to the verification that I indicated to you here again if this is what we are passing to it we simply touch this and we are working from the original object that we are obtaining from the user and we update the entire object and in this way it seems much simpler, much nicer, much more understandable than creating a bunch of additional columns to manage user preferences and we can extend it very easily.

In the end, as a moral we always have to check if it is defined, if it is not defined, if it is defined we obtain it, if it is not defined we simply leave a default value and always be aware of the castings so that it does not give a section and simply stops executing the rest of the application and also that an ugly error message appears here, so now yes, with that we are done.

- Andrés Cruz

En español

Andrés Cruz

Develop with Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz In Udemy

I agree to receive announcements of interest about this Blog.

!Courses from!

10$

On Udemy

There are 3d 03:49!


Udemy

!Courses from!

4$

In Academy

View courses

!Books from!

1$

See the books
¡Become an affiliate on Gumroad!