php - Laravel how to get back relationships from an array of ids

I have a table called addresses, it has a column name user_ids which is an array of the users who have that same address. When I request to /api/addresses what it returns is {id:1,name:"lorem", user_ids:[1,2]}. I want it to return the users instead of their ids

this is the addresses model


<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Address extends Model
{
    use HasFactory;

    protected $fillable = [
        'coordinates',
        'title',
        'description',
        'user_ids',
    ];



    protected $appends = ['user_ids'];

    protected $casts = [
        'user_ids' => 'array',
    ];
    
    public function users()
    {
        return $this->belongsToMany(User::class,"addresses");
    }

}

this is the create_table_addresses

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('addresses', function (Blueprint $table) {
            $table->id();
            $table->string('coordinates');
            $table->string('title');
            $table->string('description');
            $table->json("user_ids");
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('addresses');
    }
};

addresses controller

<?php

namespace App\Http\Controllers;

use App\Http\Requests\StoreAddressRequest;
use App\Http\Requests\UpdateAddressRequest;
use App\Models\Address;

class AddressController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return Address::with('users')->get();
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //

    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \App\Http\Requests\StoreAddressRequest  $request
     * @return \Illuminate\Http\Response
     */
    public function store(StoreAddressRequest $request)
    {
        $address = Address::create($request->validated());

        return response()->json($address, 201);

    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Models\Address  $address
     * @return \Illuminate\Http\Response
     */
    public function show(Address $address)
    {
        return $address;
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Models\Address  $address
     * @return \Illuminate\Http\Response
     */
    public function edit(Address $address)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \App\Http\Requests\UpdateAddressRequest  $request
     * @param  \App\Models\Address  $address
     * @return \Illuminate\Http\Response
     */
    public function update(UpdateAddressRequest $request, Address $address)
    {
        $address->update($request->validated());
        return response()->json($address, 200);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\Address  $address
     * @return \Illuminate\Http\Response
     */
    public function destroy(Address $address)
    {
        $address->delete();
        return response()->json(null, 204);
    }
}


Answer

Solution:

My suggestion would be to use the database for this (since you're already using the with('addresses')).

(Documentation for that relationship starts here)

Migration:

Schema::create('address_user', function (Blueprint $table) {
    $table->integer('user_id')->unsigned()->index();
    $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
    $table->integer('address_id')->unsigned()->index();
    $table->foreign('address_id')->references('id')->on('addresses')->onDelete('cascade');
    $table->primary(['user_id', 'address_id']);
});

User model:

use App\Models\User;

class Address extends Model {

    public function users() {
        return $this->belongsToMany(User::class);
    }

}

Address model:

use App\Models\Address;

class User extends Model {

    public function addresses() {
        return $this->belongsToMany(Address::class);
    }
}

Now you can use the relationship your application:

$address->users  // Get all the users with that address
$user->addresses // Get all the addresses for the user

Address::with('users')  // Get addresses with the users as an attribute
User::with('addresses') // Get users with the Address as an attribute

Answer

Solution:

I am assuming that the response comes from a controller so then where you build you response, you need to append the user information.

Maybe something like

User::whereIn('id', [1,2])->get() ...

If you post the controller, then I can tell you exactly where to put this or how to do it better.

Source