Laravel JSON fields and set and get attribute

Created At: 2023-06-13 01:21:32 Updated At: 2023-06-13 01:24:58

JSON fields are gaining more popularity since they became officially supported in MySQL 5.7.8. Even the popular Spatie Laravel Medialibrary package use them, so why shouldn't we? This tutorial will show you an example.

In our application, we have stored JSON data in the JSON field, so we need to know how to save data in the field and get data back from the field.

Here's our Lesson model

<?php

namespace App\Models;

use Encore\Admin\Traits\DefaultDatetimeFormat;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Lesson extends Model
{
    use HasFactory;
    use DefaultDatetimeFormat;

    protected $casts = [
        'video'=>'json',
    ];


    public function setVideoAttribute($value){

        $newVideo = [];
        foreach($value as $k=>$v){
            $valueVideo = [];
            if(!empty($v['old_url'])){
                $valueVideo['url'] = $v['old_url'];
            }else{
                $valueVideo['url']=$v['url'];
            }

            if (!empty($v["old_thumbnail"])) {
                $valueVideo["thumbnail"] = $v["old_thumbnail"];
            } else {
                $valueVideo["thumbnail"] = $v["thumbnail"];
            }
            $valueVideo['name']=$v['name'];
            array_push($newVideo,$valueVideo);
        }

        //json_encode makes it json for the database
        //array_values get the values of the php associative array
        $this->attributes['video'] = json_encode(array_values($newVideo));
    }

    public function getVideoAttribute($value){
        //conver to associative array
        /*
            "key"=>"value",
        */
        $result = json_decode($value, true);
        if(!empty($result)){
            foreach($result as $key => $value){
                $result[$key]['url'] = env('APP_URL')."uploads/".$value['url'];
                $result[$key]['thumbnail'] = env('APP_URL') . "uploads/" . $value['thumbnail'];
            }


        }
        return $result;
    }

    public function getThumbnailAttribute($value){
        return env('APP_URL')."uploads/".$value;
    }

}

Here's the controller that get data from the front end form and data process. It happens in the form() method.

    protected function form()
    {
        $form = new Form(new Lesson());

        //$form->display('id', __('ID'));
        $result = Course::pluck('name', 'id');
        $form->text('name', __('Name'));
        $form->select('course_id', __('Courses'))->options($result);
        $form->image('thumbnail', __('Thumbnail'))->uniqueName();
        $form->textarea('description', __('Description'));

        if($form->isEditing()){

            //access this during form eddting
            // dump($form->video);

                $form->table('video', function ($form) {
                $form->text('name');
                $form->hidden('old_url');
                $form->hidden('old_thumbnail');
                $form->image('thumbnail')->uniqueName();

                //any kind of media
                $form->file('url');
                });

        }else{

                //normal form submission or form creating

                $form->table('video', function ($form) {
                $form->text('name')->rules('required');
                $form->image('thumbnail')->uniqueName()->rules('required');
                //any kind of media
                $form->file('url')->rules('required');
            });
        }
        //saving call back gets called before submitting to the datbase
        //but after clicking the submit button
        // a good place to process grabbed data or form data
        $form->saving(function (Form $form){
           if($form->isEditing()){
                //here is the place to process data and
                //the below one gets the editted data
                $video = $form->video;
                // the below gets data from the database
                $res = $form->model()->video;
                //for each of the key, get the value
                $path = env('APP_URL') . "uploads/";

                $newVideo = [];
                foreach ($video as $k => $v) {
                    $oldVdieo = [];
                    //user did not type anything
                    if (empty($v['url'])) {
                        $oldVdieo["old_url"] = empty($res[$k]['url']) ? ""
                            //replacing the domian path from the value
                            : str_replace($path, "", $res[$k]['url']);
                    } else {
                        //this is a new editted value
                        $oldVdieo["url"] = $v['url'];
                    }

                    if (empty($v['thumbnail'])) {
                        $oldVdieo["old_thumbnail"] = empty($res[$k]['thumbnail']) ? ""
                            //replacing the domian path from the value
                            : str_replace($path, "", $res[$k]['thumbnail']);
                    } else {
                        //this is a new editted value
                        $oldVdieo["thumbnail"] = $v['thumbnail'];
                    }

                    if (empty($v['name'])) {
                        $oldVdieo["name"] = empty($res[$k]['name']) ? ""

                            :  $res[$k]['name'];
                    } else {
                        //this is a new editted value
                        $oldVdieo["name"] = $v['name'];
                    }


                    $oldVdieo['_remove_']=$v['_remove_'];
                    array_push($newVideo, $oldVdieo);
                   // dump($newVideo);
                }
                $form->video = $newVideo;
           }


        });

        return $form;
    }

Comment

Add Reviews