How to get Title, Description and Price stored in

2019-08-29 00:35发布

问题:

I want to get the title, description, and price which are stored in a pivot table between users and services called userservices. I want to be able to display this information I'll get from the userservices table, inside the user profile view page.

I have 4 tables for that which include,

A User table with id, name, surname, email, phone, area_id.

A Service table with id, name, description, and category_id.

A category table with id, name, description

and I have pivot table btw users and services called service_user which stores the service_id, user_id, title, description and price

I wish to know how can I get the title, description and price for a service that belongs to a particular user, provided the information exists in the userservice table in the database using Laravel.

In my user Controller, I did something like this

 public function jobberDetails($id) {
    $profiledetail = User::with('area.town.region.country')
                            ->with('userservice')
                            ->find($id);

    DB::update("UPDATE users SET visit = visit + 1 WHERE id = '$id'");

   // dd($jobdetail);
    return view('Users.profileDetail', compact('profiledetail'));
}

in my web file

// Route qui permet d'afficher,le profil d'un Jobbeur
Route::get('/jobber/profiledetails/{id}', 'UserController@jobberDetails')->where(array('id' => '[0-9]+'))->name('profileDetails'); 

In my model I did something like this

public function area(): BelongsTo
{
    return $this->belongsTo(Area::class);
}

public function getTownAttribute(): Town
{
    return $this->area->town;
}

public function getRegionAttribute(): Region
{
    return $this->area->town->region;
}

public function getCountryAttribute(): Country
{
    return $this->area->town->region->country;
}

public function userservice(): BelongsTo
{
    return $this->belongsTo(UserServices::class);
}

and in my profile detail blade I did this

<div class="row">
        <div class="col-lg-8">
            <div class="job-single-head3">
    <div class="job-single-info3">
        <h3>{{ $profiledetail->name }} {{ $profiledetail->surname }}</h3>
<span><i class="la la-map-marker"></i>{{ $profiledetail->town->name}}, {{ $profiledetail->region->name}}</span>
 <span class="job-is ft"  id="more" onclick="$('.details').slideToggle(function(){$('#more').html($('.details').is(':visible')?'Cacher le numero':'Voir le numero');});">Voir le numero</span>
            </div>
        </div><!-- Job Head -->
        </div>

    </div>
</div>
<div class="job-wide-devider">
<div class="row">
    <div class="col-lg-8 column">
        <div class="extra-job-info details" style="display:none">
            <p style="text-align: center; padding: 10px; font-size: 45px;"><i class="la la-phone"></i> {{ $profiledetail->phone }}</p>
        </div>      
        <div class="job-details">
            <h3>Description</h3>
            <p> {{ $profiledetail->userservices->description }}.</p>

            <h3>Conditions et tarifs</h3>
            <ul>
                <li>{{ $profiledetail->userservices->price }}</li>
            </ul>

            <h3>Title</h3>
            <ul>
                <li>{{ $profiledetail->userservices->title }}</li>
            </ul>
        </div>

回答1:

Here's how you can do it using pivot as suggested by @DigitalDrifter

Start by adding services relationship method to the User model

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class User extends Authenticatable
{
    use Notifiable;

    //...

    public function services(): BelongsToMany
    {
        return $this->belongsToMany(Service::class)->withPivot('title', 'description', 'price');
    }
}

Add reverse relationship to the User from within Services model

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class Service extends Model
{
    protected $fillable = ['category_id', 'name', 'description'];

    public function country(): BelongsTo
    {
        return $this->belongsTo(Category::class);
    }

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

    public function category(): BelongsTo
    {
        return $this->belongsTo(Category::class);
    }
}

Now you can use it like so

$profileDetail = User::with(['area.town.region.country', 'services'])->find($id);

foreach($profileDetail->services as $service) {

    {{ $service->pivot->title }}
    {{ $service->pivot->description }}
    {{ $service->pivot->price }}
    {{ $service->category->name }}

}

Here's the test (containing all previous code example as well)

<?php

namespace Tests\Unit;

use App\Area;
use App\Town;
use App\User;
use App\Region;
use App\Service;
use App\Country;
use App\Category;
use Tests\TestCase;

use Illuminate\Foundation\Testing\RefreshDatabase;

class UserTest extends TestCase
{
    use RefreshDatabase;

    /**
     * @test
     */
    public function pulls_area_town_region_and_country()
    {
        $country = Country::create([
            'name' => 'United Kingdom',
            'description' => 'United Kingdom'
        ]);

        $region = Region::create([
            'country_id' => $country->id,
            'name' => 'Somerset',
            'description' => 'Somerset'
        ]);

        $town = Town::create([
            'region_id' => $region->id,
            'name' => 'Bristol',
            'description' => 'Bristol'
        ]);

        $area = Area::create([
            'town_id' => $town->id,
            'name' => 'South',
            'description' => 'South'
        ]);

        $category = Category::create([
            'name' => 'Animals',
            'description' => 'Animals'
        ]);

        $service = Service::create([
            'category_id' => $category->id,
            'name' => 'Service',
            'description' => 'Service'
        ]);


        $user = factory(User::class)->create([
            'area_id' => $area->id
        ]);

        $user->services()->attach($service->id, [
            'title' => 'Attached service',
            'description' => 'Attached service description',
            'price' => 12575
        ]);

        $user = User::with('area.town.region.country')->first();

        $recentJobbers = User::with(['area.town.region.country', 'services.category'])
            ->limit(5)
            ->whereType('jobber')
            ->orderBy('updated_at', 'desc')
            ->get();

        $this->assertEquals('United Kingdom', $user->area->town->region->country->name);
        $this->assertEquals('Somerset', $user->area->town->region->name);
        $this->assertEquals('Bristol', $user->area->town->name);
        $this->assertEquals('South', $user->area->name);

        $this->assertEquals('United Kingdom', $user->country->name);
        $this->assertEquals('Somerset', $user->region->name);
        $this->assertEquals('Bristol', $user->town->name);
        $this->assertEquals('South', $user->area->name);

        $this->assertEquals('Attached service', $user->services->get(0)->pivot->title);
        $this->assertEquals('Attached service description', $user->services->get(0)->pivot->description);
        $this->assertEquals(12575, $user->services->get(0)->pivot->price);
        $this->assertEquals('Animals', $user->services->get(0)->category->name);
    }
}


回答2:

Use the withPivot method to access data from the pivot table.

See the section Retrieving Intermediate Table Columns under Many-To-Many Relationships.

Your User model would define the relationship to Service as:

public function services()
{
    return $this->belongsToMany(Service::class)
                ->withPivot(['description', 'price', 'title']);
}