0

I have many to many relationship between UserProfile model and UserTv model. Here are the tables.

user_profiles

id    user_id    username
 1       1       AuthUser

tv

id    name
 1    Action
 2    Drama
 3    Comedy
 4    manually added some genre from input from authenticated user

user_tv

id    user_id    tv_id
 1      1          2
 1      1          4

For example, these first three ids in tv table (Action, Drama, Comedy) are inserted through seeders and this fourth id is inserted manually through input text from form by that user who is authenticated. And there lies the my problem. I want that those values that are manually added through input in form to only be able to see that user that inserted those values, and all other users can't. But also I want all users to remain to see those first three values that are generated through seeder. Currently everything works so that all users can see everything. Any help is appreciated. Here is my code.

UserProfile.php

<?php

namespace App;

use App\User;
use Illuminate\Support\Facades\App;
use Illuminate\Database\Eloquent\Model;

class UserProfile extends Model
{
    protected $fillable = [
        'user_id',
        'username',
    ];

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function tvs()
    {
        return $this->belongsToMany(UserTv::class, 'user_tv', 'user_id', 'tv_id');
    }
}

UserTv.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class UserTv extends Model
{
    protected $table = 'tv';

    protected $fillable = [
        'name'
    ];

    public function userProfiles()
    {
        return $this->belongsToMany(UserProfile::class, 'user_tv', 'tv_id', 'user_id');
    }
}

web.php

Route::get('profile/{profile}', 'UserProfileController@showProfile')->name('profile.show');
Route::patch('profile/update-tv-options', 'TvController@updateTvOptions')->name('profile.update.tv.options');
Route::post('profile/insert-tv-options', 'TvController@insertTvOptions')->name('profile.insert.tv.options');

TvController.php

<?php

namespace App\Http\Controllers;

use App\UserTv;
use App\UserProfile;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use App\Http\Requests\InsertTvOptionsRequest;
use App\Http\Requests\UpdateTvOptionsRequest;

class TvController extends Controller
{
    public function updateTvOptions(UpdateTvOptionsRequest $request)
    {
        $user = Auth::user();

        $userProfile = UserProfile::where('user_id', Auth::id())->first();
        $userProfile->update($request->all());

        $data = $request->get('tvsOptions', '[]');
        $userProfile->tvs()->sync($data);

        return redirect()->route('profile.show', [$user->username]);
    }

    public function insertTvOptions(InsertTvOptionsRequest $request)
    {
        $user = Auth::user();

        $tv = UserTv::create($request->all());

        return redirect()->route('profile.show', [$user->username]);
    }
}

UserProfileController.php

<?php
namespace App\Http\Controllers;

use App\User;
use App\UserTv;
use App\UserProfile;

class UserProfileController extends Controller
{
    public function showProfile($username, Request $request)
    {
        $profileId = User::getIdFromUsername($username);
        $userForShowProfile = User::with('userProfile')->where('id', $profileId)->firstOrFail();

        $tvsOptions = UserTv::get();

        $userTvsOptions = UserProfile::findOrFail($profileId)->tvs()->get();

        return view('profile.show', compact('userForShowProfile', 'tvsOptions', 'userTvsOptions'));
    }
}

show.blade.php

<section data-edit="movies" class="editMovies">
    <h3 class="textBold">Film</h3>
    <form action="{{ route('profile.update.tv.options') }}" method="POST" class="flex">
        @method('PATCH')
        @csrf
        <div class="form-group flex">
            @isset($tvsOptions, $userTvsOptions)
                @foreach($tvsOptions as $option)
                    <div class="interestedIn">
                        <input type="checkbox" name="tvsOptions[]" value="{{ $option->id }}" {{ $userTvsOptions->contains('id', $option->id)? 'checked': ''}}>
                        <label for="">{{ $option->name }}</label>
                    </div>
                @endforeach
            @endisset
        </div>
        <div class="form-group">
            <label for="" class="textBold">Button FOR CHECKBOX</label>
            <input type="submit" class="form-control" name="submit" value="BUTTON">
        </div>
    </form>
    <form action="{{ route('profile.insert.tv.options') }}" method="POST" class="flex">
        @csrf
        <div class="form-group mt-5">
            <input type="text" name="name" placeholder="INSERT NEW MOVIE GENRE">
        </div>
        <div class="form-group">
            <label for="" class="textBold">Button FOR INSERT!!!</label>
            <input type="submit" class="form-control" name="submit" value="BUTTON">
        </div>
    </form>
</section>
8
  • any error message? Commented May 7, 2020 at 11:07
  • No, this works perfectly. But I don't know how to make it so that those values that are inserted through input from form be only visible to that user who inserted it in foreach with checkboxes above. Commented May 7, 2020 at 11:13
  • you are looping on $tvsOptions , I guess it contains all the datas pulling fron db Commented May 7, 2020 at 11:21
  • Yes. it contains all data from tv table. And I want to contain first three options for all users and that fourth option for only this user that inserted that. In this example I mean Commented May 7, 2020 at 11:23
  • you cant recognize here that which tv_id is seeded or inserted !! can u?? Commented May 7, 2020 at 11:43

2 Answers 2

1

And I want to contain first three options for all users and that fourth option for only this user that inserted that.

Something like this?

$defaultTvsOptions = UserTv::whereIn('name', ['Action', 'Drama', 'Comedy'])->get(); // return only action, drama and comedy. you can use ids.
$userTvsOptions = UserProfile::findOrFail($profileId)->tvs;

$tvsOptions = $defaultTvsOptions->merge($userTvsOptions); // merge default and logged user tvs options

To make it more maintainable, you could use configs in your root directory of project.

$defaultTvsOptions = UserTv::whereIn('name', config('config name where return the array'));

Hope it helps you.

Sign up to request clarification or add additional context in comments.

8 Comments

I get Call to undefined method Illuminate\Database\Eloquent\Builder::merge() wjem O ise your first example
@rose Hi! Im sorry, forget to put the get() mehotd.fixed comment.
@rose I fix this line $defaultTvsOptions = UserTv::whereIn('name', ['Action', 'Drama', 'Comedy'])->get();
Hey, it works. Just one small thing. Now when I insert in input it writes in database but doesn't show in my checkboxes in foreach and I am the one who inserted it so it should.
@rose Could you check $tvsOptions usign dd($tvsOptions) in the controller? check if the data is correct. UserProfile::findOrFail($profileId)->tvs this line getting the tvs data of user.
|
0

Hey As you Have a pivot table You can pull the data Like This:

Userprofile model

public function tv() {
       return $this->hasManyThrough(
           'Tv class ',
           'user_tv class', 
           'user_id',
           'id',
           'user_id',
           'tv_id'
       );
   }

UserController

$data = UserProfile::with('tv')
            ->where(condition)        
                ->get();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.