2

I have a problem with getting all the testimonials submitted by other users to display them on the user profile of the user concerned (the user being reviewed).

There are two tables. First the users table with id, name, email, photo, phone and title. And I have an avis table which stores the testimonials with id, profile_id, user_id and the comment. (The user_id gets the id of the User submitting the form and profile_id gets the id of the User who is receiving the testimonial).

I tried doing it like the following and don't really know if its the right approach. And I am not sure if I did the relationship right. I am kind of new to Laravel. But anyway this is what I tried so far:

This is User model:

public function avis()
{
    return $this->hasMany('App\Avis', 'profile_id', 'user_id');
}

And this is my Avis model:

protected $fillable = ['comment','profile_id'];

public function user() 
{
    return $this->belongsTo('App\User');
}

This is what I did in the controller displaying the profile and list of testimonials:

public function Details($id)
{
    $detail = User::with(['area.town', 'services'])->find($id);

    $avis = User::whereHas('avis', function ($query) use ($id) {
            $query->where('profile_id', '=', $id);
        })
        ->limit(3)
        ->get();

    //dd($avis);

    return view('Users', compact('avis', 'detail'));
}

Here is my form that is used to write a testimonial:

<div id="avisForm"> 
    <p class="feedback_message">We are here to make sure you are sastified and your transactions are safe. We do appreciate and will respond quickly to any feedback from you.</p>

    {!! Form::open(['route' => 'avis.store']) !!}

    <input type="hidden" name="profile_id" value="{{ $detail>id }}">
    {!! Form::textarea('comment', null, ['placeholder' => 'Message', 'required' => 'required']) !!}
    {!! Form::submit('Envoyez', ['class' => 'formBtn','style' => 'margin-top:10px']) !!}

    {!! Form::close() !!}
</div>

And this is the controller method used to store the testimonial:

public function store(AvisCreateRequest $request)
{
    $avis = new Avis;
    $id = Auth::user()->id;

    $avis->comment = $request->comment;
    $avis->profile_id = $request->profile_id;
    $avis->user_id = $id;

    //dd($avis);

    $avis->save();

    return back()->with('success_message', 'Votre Avis a ete envoyez avec succes!');
}

Can someone please point out to me what I am doing wrong?

Namoshek
  • 6,394
  • 2
  • 19
  • 31
Labelle Doriane
  • 105
  • 1
  • 3
  • 15

2 Answers2

2
public function avis()
{
    return $this->hasMany('App\Avis', 'profile_id', 'id');
}

hey man ,it must be like this , 'profile_id' and 'user_id' are both foreign key. 'id' is your local key in the users table, if you call avis() it will going to match the id of the users table with avis table profile_id

2

You will need two different relationships on your User model if you want to be able to query both types of Avis, the ones the User has written and the ones he received.

public function receivedAvis()
{
    return $this->hasMany('App\Avis', 'profile_id', 'id');
}

public function writtenAvis()
{
    return $this->hasMany('App\Avis', 'user_id', 'id');
}

You can then query the received testimonials like this:

public function Details($id)
{
    $user = User::with(['area.town', 'services'])->find($id);

    $avis = $user->receivedAvis()
        ->limit(3)
        ->get();

    return view('Users', compact('avis', 'user'));
}

If you want, you can also use relationship loading on the User - then you don't have to pass multiple variables to your view. It would look something like this:

public function Details($id)
{
    $user = User::with(['area.town', 'services'])->find($id);

    $user ->load(['receivedAvis' => function ($query) {
        $query->limit(3);
    }]);

    return view('Users', compact('user'));
}

You can then access your testimonials in the view through your $user variable:

@if(count($user->receivedAvis) > 0)
    <div id="testimonials">
        @foreach($user->receivedAvis as $avis)
            <!-- place the code to display your testimonials here -->
        @endforeach
    </div>
@endif

Please note that I renamed your $detail variable to $user because it is better to use variable names that reflect the type of the variable.

Namoshek
  • 6,394
  • 2
  • 19
  • 31
  • Hey man Its working. Thanks so much. I have one more question. How can I prevent a user from sending 2 testimonials to a same user profile and also how can I prevent a user from sending a testimonial to himself.. – Labelle Doriane Apr 27 '18 at 15:27
  • In the controller action where you return the testimonial form view, you can perform a check like this `if (\Auth::user()->writtenAvis()->where('profile_id', $profileId)->count() > 0 || $profileId === \Auth::user()->id) { return response()->back(); // or do whatever you want }`. – Namoshek Apr 27 '18 at 15:31
  • So I should add this code in Avis Controller where I store my form data – Labelle Doriane Apr 27 '18 at 15:39
  • In my opinion, you should add it in two places: 1) in the controller action that stores a new testimonial and 2) in the controller action that displays the testimonial form, because otherwise your users might type a text that cannot be stored (which is frustrating). – Namoshek Apr 27 '18 at 15:40
  • "Method Illuminate\Routing\ResponseFactory::back does not exist." Do I need to import or install something? – Labelle Doriane Apr 27 '18 at 15:44
  • 1
    It should say `return redirect()->back()`. Sorry, made a small mistake there. It will just send the user back to the route where he came from. – Namoshek Apr 27 '18 at 15:48
  • Thanks I have solve my problem.. Ouff never thought it was this easy. Your methods are so so good to understand – Labelle Doriane Apr 27 '18 at 15:52
  • 1
    That is one of the most important lessons you have to learn about Laravel when coming from other frameworks or programming languages: when you yourself feel like something is very difficult or tedious to implement, then you are most likely doing something wrong. Because the Laravel way is normally quite short and eloquent at the same time (hence the name Eloquent for the ORM system). :) – Namoshek Apr 27 '18 at 15:55
  • Ok Can I use this same way to implement favorites? I want to help a friend with his question which we were working on it yesterday. https://stackoverflow.com/questions/50045947/how-can-i-add-a-user-of-type-jobber-to-another-user-favorite-list-using-laravel :)) – Labelle Doriane Apr 27 '18 at 16:00
  • I was trying to separete it so the user will know the exact mistake he is having. I did this if (\Auth::user()->writtenAvis()->where('profile_id', $id)->count() > 0) { return redirect()->back()->with('success_message', 'Vous avez déjà laisser un avis sur ce profil'); } if (\Auth::user()->writtenAvis()->where($id === \Auth::user()->id)) { return redirect()->back()->with('success_message', 'Cette operation est Impossible!'); } But now each time I try to write a testimonial on a new user. It says Cette operation est Impossible!' – Labelle Doriane Apr 27 '18 at 16:55
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/169965/discussion-between-labelle-doriane-and-namoshek). – Labelle Doriane Apr 27 '18 at 17:35