phplaraveleloquent

How to write the relationship between two related models and assign a value using the relationship?


So I'm currently struggling with my AlbumController's store function, where i need to store an album in my albums table, including the indexes of the pictures selected to be included in the album, in which the pictures included are then going to be indexed with foreign key album_id in another table that stores the pictures called photos. I need all of the selected pictures to be assigned with the value of the newly created album, which is the primary key album_id on my albums table, but i still hasnt figured out how to assign the value using Eloquent relationships.

This is my store function inside my AlbumController controller:

/**
     * Store a newly created resource in storage.
     */
    public function store(Request $request)
    {
        $user_id = Auth::id();
        $data = [
            'album_name' => $request->get('album_name'),
            'album_description' => $request->get('album_description'),
            'user_id' => $user_id // I still hasnt figured out how assign the user_id value to the album using Eloquent ORM relationships either
        ];
        //album::create($data); // creates the album
        $photos = ['photos' => $request->get('photo_checkbox')]; // insert photos checklisted in the create album form
        foreach ($photos as $photo){
            $album_query =  Photo::where('photo_id',$photo); // assign the photos checklisted album_id according to the album just created
            $result = $album_query->albums()->save(); // tried to use Laravel's Eloquent ORM relationships
            /** $album = Album::where('album_name',$data['album_name']); 
             * $result = $album_query->update(['album_id' => $album->album_id]); // alternative without Eloquent ORM relationships
             */
        }
        dd($result);
        session()->now('data','album_name');
        return redirect(route('album.album'))->with('success','album "'.$data['album_name'].' '.'" has been registered.');
    }

I defined my album to be an instance of Album model, which can contain many photos inside of it:

class Album extends Model
{
    use HasFactory;
    protected $table = "albums";
    protected $primaryKey = "album_id";
    const CREATED_AT = 'data_created';
    const UPDATED_AT = 'data_modified';

    protected $fillable = [
        'album_name',
        'album_description',
        'user_id'
    ];

    public function photos() : HasMany {
        return $this->hasMany(Photo::class,'album_id','album_id');
    }
    public function users() : BelongsTo {
        return $this->belongsTo(GalleryUser::class,'user_id','gallery_user_id');
    }
}

while my photos are instances of Photo model:

class Photo extends Model
{
    /** @use HasFactory<\Database\Factories\PhotoGalleryFactory> */
    use HasFactory;
    protected $table = "photos";
    protected $primaryKey = "photo_id";
    const CREATED_AT = 'data_created';
    const UPDATED_AT = 'data_modified';

    protected $fillable = [
        'photo_title',
        'photo_description',
        'photo_location',
        'user_id',
        'album_id'
    ];
    public function comments() : HasMany {
        return $this->hasMany(PhotoComment::class,'comment_id','comment_id');
    }
    public function albums() : BelongsTo {
        return $this->belongsTo(Album::class,'album_id','album_id');
    }
    public function users() : BelongsTo {
        return $this->belongsTo(GalleryUser::class,'user_id','gallery_user_id');
    }
}

in this snippet of my store function of my AlbumController controller, i have written two different options to assign the value to foreign key album_id, one with eloquent relationships and one without:

...
foreach ($photos as $photo){
            $album_query =  Photo::where('photo_id',$photo); // assign the photos checklisted album_id according to the album just created
            $result = $album_query->albums()->save(); // tried to use Laravel's Eloquent ORM relationships
            /** $album = Album::where('album_name',$data['album_name']); 
             * $result = $album_query->update(['album_id' => $album->album_id]); // alternative without Eloquent ORM relationships
             */
        }
...

but when i tried to do $album_query->albums()->save(), i instead got Call to undefined method Illuminate\Database\Eloquent\Builder::albums(). I tried adding ->get() to $album_query, but i got Method Illuminate\Database\Eloquent\Collection::albums does not exist. instead. From this, i feel like i might have written the relationship the wrong way, and there is a way that the code can work if i can figure out the relationship between my Album model and my Photo model.

Meanwhile the alternative doesnt look very good either, even though i think its a plausible enough code, i feel like the eloquent ORM isnt being used very much, and i might as well not use it if thats the case.


Solution

  • Assuming that the $request->get('photo_checkbox') code return an array with photo IDs, probably the problem is that you're not iterating through the ids but instead of ['photos'] single item which is not an ID.

    Also try calling ->firstOrFail() on Photo::where('photo_id',$photo) inside the foreach in order to retrieve the model itself and not the query builder.