Home > other >  Laravel 9 Accessor not Returning Value
Laravel 9 Accessor not Returning Value

Time:05-24

I have a Reminder model that has a sound_path column. I created an accessor for that column in the model but it's returning null and I doubled checked that the database has a value in that column. What am I doing wrong?

Note: Of course I can call $this->sound_path directly in soundPathUrl mutator without creating the accessor from the first place but I'm interested to know why if I called the accessor is not returning any value.

Reminder model

namespace App\Models;

use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\URL;
use Spatie\Translatable\HasTranslations;

class Reminder extends BaseModel
{
    use HasFactory, SoftDeletes, HasTranslations;

    public $translatable = [
        'title__ml',
    ];

    protected $casts = [
        'available_days_for_reminder' => 'json',
        'is_multiple_days_allowed' => 'boolean'
    ];

    protected $appends = ['sound_path_url'];

    /**
     * Get the sound path
     * 
     * @param string  $value
     * @return \Illuminate\Database\Eloquent\Casts\Attribute
     */
    protected function soundPath(): Attribute
    {
        return Attribute::make(
            get: fn ($value) => $value
        );
    }

    /**
     * Get sound path download URL
     *
     * @return \Illuminate\Database\Eloquent\Casts\Attribute
     */
    protected function soundPathUrl(): Attribute
    {
        return new Attribute(
            get: fn () => asset('storage/' . $this->soundPath),
        );
    }
}

Reminder controller

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Resources\Reminder\ReminderCollection;
use App\Http\Resources\Reminder\ReminderResource;
use App\Models\Reminder;
use Exception;
use Illuminate\Http\Request;

class ReminderController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $reminders = Reminder::paginate(5);

        return ReminderCollection::collection($reminders);
    }
}

ReminderCollection API resource

namespace App\Http\Resources\Reminder;

use Illuminate\Http\Resources\Json\JsonResource;

class ReminderCollection extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'title' => $this->title__ml,
            'sound' => $this->sound_path_url
        ];
    }
}

Screenshot of Response

Response JSON

At the arrow there should be the value of sound_path.

CodePudding user response:

Your issue is that you are calling $this->soundPath instead of $this->sound_path in soundPathUrl method...

So, you should have this:

/**
 * Get sound path download URL
 *
 * @return \Illuminate\Database\Eloquent\Casts\Attribute
 */
protected function soundPathUrl(): Attribute
{
    return new Attribute(
        get: fn () => asset('storage/' . $this->sound_path),
    );
}

Check the documentation and you will see you still have to call your properties using snake_case.

CodePudding user response:

  1. It seems soundPath accessor does nothing, it returns the same value which seems empty. Where does soundPath value come from? First, make sure, soundPath itself has any value within that function.

  2. Call soundPath as a function

    protected function soundPathUrl(): Attribute
    {
        return new Attribute(
            get: fn () => asset('storage/' . $this->soundPath()),
        );
    }
}
  • Related