I'm building API and I'm struggling with store data for multiple employee roles, how to store, could you provide me some example,
sorry for using the foreign language.
Karyawan=employee,
Jabatan=role
Karyawan.php
public function jabatan() {
return $this->hasMany('\App\Jabatan','id_jabatan');
}
Jabatan.php
public function karyawan(){
return $this->belongsTo('\App\Karyawan','id_jabatan');
}
how to KaryawanController at store function should be...
this is my model and controller
i created my pivot table and i got this error
SQLSTATE[42S22]: Column not found: 1054 Unknown column '0' in 'field list' (SQL: insert into tb_jabatan_karyawan (id_jabatan, id_karyawan, 0, 1) values (0, 57, 1, 2))
ini controller sama modelnya..
I am using User and Role instead of Karyawan and Jabatan respectively (sorry for that). User and Role has Many-to-Many relation because one User may have multiple Roles and vice versa.
roles Table
+----+------+-----------+
| id | role | timeStamps|
+----+------+-----------+
role_user Pivot Table
+----+---------+---------+
| id | user_id | role_id |
+----+---------+---------+
Role Model
public function users(){
return $this->belongsToMany('App\User');
}
User Model
public function roles(){
return $this->belongsToMany('App\Role');
}
RoleUser Pivot
namespace App;
use Illuminate\Database\Eloquent\Relations\Pivot;
class RoleUser extends Pivot
{
protected $table='role_user';
protected $fillable = [
'user_id','role_id'
];
public static $role_attach_rules = [
'roles' => 'required|array|min:1|exists:roles,id'
];
public function user(){
return $this->hasOne('App\User', 'id', 'user_id');
}
public function role(){
return $this->hasOne('App\Role', 'id', 'user_id');
}
}
Controller Code for Assigning Roles to the User
Here you will understand the methods by their names.
public function getAssignRole(){
$users = User::all();
$roles=Role::all();
return View::make('assignrole', compact('users', 'roles'));
}
public function postAssignRole(Request $request){
$attachvalidator = Validator::make($request->all(),RoleUser::$role_attach_rules);
if ($attachvalidator->fails()){
return Redirect::back()->withErrors($attachvalidator)->withInput();
}
$user=$request->get('user');
$role=$request->get('roles');
$attach = User::find($user)->roles()->attach($role);
return 'Success';
}
public function detachRole(Request $request){
$user=$request->get('user_update');
$role=$request->get('roles_update');
$attach = User::find($user)->roles()->detach($role);
return 'detach Success';
}
View file (assignrole.blade.php) for Assigning Roles
//This form is for assigning roles
<form method="post" action="{{route('role.assignrole.post')}}">
{{csrf_field()}}
<select id="user" name="user" class="select_with_style" required>
#foreach($users as $user)
<option value="{{$user['id']}}">{{$user['name']}}</option>
#endforeach
</select>
<select id="roles" name="roles[]" class="select_with_style" multiple="" required>
#foreach($roles as $role)
<option value="{{$role['id']}}">{{$role['role']}}</option>
#endforeach
</select>
<br>
<input type="submit" name="submit" class="submit action-button" value="Submit"/>
</form>
//This is for detaching roles from user
<form method="post" action="{{route('role.detach')}}">
{{csrf_field()}}
<select id="user_update" name="user_update" class="select_with_style" required>
#foreach($users as $user)
<option value="{{$user['id']}}">{{$user['name']}}</option>
#endforeach
</select>
<select id="roles_update" name="roles_update[]" class="select_with_style" multiple="" required>
#foreach($roles as $role)
<option value="{{$role['id']}}">{{$role['role']}}</option>
#endforeach
</select>
<br>
<input type="submit" name="submit" class="submit action-button" value="Update"/>
</form>
Routes
Route::get('role/assignrole', array('as' => 'role.assignrole', 'uses' => 'YourController#getAssignRole'));
Route::post('role/assignrole', array('as' => 'role.assignrole.post', 'uses' => 'YourController#postAssignrole'));
Route::post('role/detach', array('as' => 'role.detach', 'uses' => 'YourController#detachRole'));
Hope this helps.
Edit
You can use Voyager instead of doing this much work. It is very easy to understand and well structured and I think you will love it.
Related
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>
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.
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();
Trying to write a function to create a new "profile" in my profiles table and get the following error:
"SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: profiles.about (SQL: insert into "profiles" ("dateofbirth", "state", "zipcode", "profilepic", "user_id", "updated_at", "created_at") values (2020-04-15, FL, 12345, /tmp/phpTT6CZr, 1, 2020-04-30 00:48:23, 2020-04-30 00:48:23))"
I've been reading answers to similar questions for the past few hours. Tried several different things, no luck so far. Hoping to see a solution that works in my code, and also get a better understanding of where exactly the error begins. The error message leads me to believe it's something to do with my "about" section in table. But unsure. I thought adding " protected $guarded = []; " to controller would solve but that gave the same result.
Here is what I'm working with:
Migration File:
public function up()
{
Schema::create('profiles', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id'); //foreign key
$table->text('about')->nullable;
$table->text('profilepic')->nullable;
$table->date('dateofbirth')->nullable;
$table->unsignedinteger('zipcode')->nullable;
$table->string('state')->nullable;
$table->timestamps();
$table->index('user_id'); //index for foreign key
});
}
Profile Model:
class profile extends Model {
protected $guarded = [];
public function user()
{
return $this->belongsTo(User::class);
} }
I have also tried changing the profile model like below:
class profile extends Model {
public function user()
{
return $this->belongsTo(User::class);
}
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'dateofbirth' => 'datetime',
'zipcode' => 'unsignedinteger'
];
/*
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'about','profilepic','state', 'user_id', 'updated_at', 'created_at'
]; }
They both provide the same error message but with slightly different array values
Here is my controller store function:
public function store()
{
$data = request()->validate([
'dateofbirth' => 'required',
'state' => 'required',
'zipcode' => 'required',
'profilepic' => 'image'
]);
auth()->user()->profile()->create($data);
dd(request()->all());
}
Here is the view:
#extends('layouts.app')
#push('styles')
<link href="{{ asset('css/profile.css') }}" rel="stylesheet">
#endpush
#section('content')
{{-- This needs to present a create profile form --}}
<div class="row">
<h1 class="pl-4">CREATE YOUR PROFILE</h1>
</div>
<form action="/profile" class="pl-4" enctype="multipart/form-data" method="post">
#csrf
<div class="form-group row">
<label for="profilepic"
class="col-md-4 ocl-form-label"
>Upload a Profile Picture</label>
<input type="file"
class="form-control-file"
id="profilepic"
name="profilepic">
</div>
<div class="form-group">
<label for="about">Write your "About" Section here. What do you want us to know about you?</label>
<textarea type="text" class="form-control" id="about" name="about" rows="3"></textarea>
</div>
<div class="form-group">
<label for="dateofbirth">Date of Birth</label>
<input type="date"
id="dateofbirth"
name="dateofbirth">
</div>
<div class="form-group">
<label for="zipcode">Zipcode</label>
<input type="text" id="zipcode" name="zipcode">
</div>
<div class="form-group">
<label for="State">State</label>
<input type="text" id="state" name="state">
</div>
<div class="form-group row pt-4">
<button class="btn btn-primary">Submit</button>
</div>
</form> #endsection
That error means you're trying to set a foreign key column as null which is unacceptable, in this case, user_id on profiles table. Try to modify your code as such:
In your Profile model, add mass assignment columns:
protected $fillable = ['dateofbirth', 'state', 'zipcode', 'profilepic'];
In your controller store method:
//assuming the route method is authenticated such that there's always a logged in user
$user = auth()->user();
$data['user_id'] = $user->id;
$profile = Profile::create($data);
I'll add in also, I have since gotten this resolved with implementing #djunehor's answer. But one thing that helped get the problem resolved was adding in this to the controller:
public function store(Request $request)
At first I was not passing the request in and saving it to a variable like this, but this step seems to have made a big difference for the errors I was running into.
At first I was just doing this:
public function store()
I would like to learn to create a dropdown list with a foreign key on Laravel.
For information, I have a table named series with 3 fields id, name, fk_mark.
Then, I have another table named marks with 2 fields id, name_mark.
My create works correctly, here is the proof.
I am stuck about the dropdownlist, what is the syntax please for my foreign key ?
<fieldset class="form-group">
<label for="form-group-input-1">Name serie</label>
<input type="text" name="name" class="form-control" id="form-group-input-1">
</fieldset>
<fieldset class="form-group">
<label for="form-group-input-1">FK Mark</label>
<input type="text" name="fk_mark" class="form-control" id="form-group-input-1">
</fieldset>
I have tried this but without result...
<div class="form-group">
<label for="company-content">Select compagny</label>
<select name="fk_mark" class="form-control">
#foreach($series as $serie)
<option value="{{$serie->id}}"> {{$serie->name}} </option>
#endforeach
</select>
</div>
Here is my Models
Model Mark
class Mark extends Model
{
protected $fillable = ['name_mark'];
public function series(){
return $this->hasMany('App\Serie', 'fk_mark');
}
}
Model Serie
class Serie extends Model
{
protected $fillable = ['name', 'fk_mark'];
public function marks(){
return $this->belongsTo('App\Mark', 'fk_mark');
}
}
SerieController
public function index()
{
$series = Serie::oldest()->paginate(5);
return view('admin.series.index', compact('series'))
->with('i', (request()->input('page', 1)-1)*5);
}
public function create()
{
return view('admin.series.create');
}
public function store(Request $request)
{
$request->validate([
'name' => 'required',
'fk_mark' => 'required'
]);
Serie::create($request->all());
return redirect()->route('series.index')
->with('success', 'save');
}
Thank you very much for your help.
I have made an edit page for my users and everything works except changing the role. I have made a select menu which displays all the roles through a foreach loop. And it displays the current role of the user like this:
<div class="form-group row">
<div class="col-md-4">
<label for="Datum">Rol:</label>
</div>
<div class="col-md-8">
<select class="form-control" id="Datum" name="role">
<option selected>{{ $user->role->role_name }}</option>
#foreach($roles as $role)
<option>{{ $role->role_name }}</option>
#endforeach
</select>
</div>
</div>
I want to be able to change the role by the role_name instead of ID. I honestly don't know where to look. How can I achieve this?
The controller that the form goes through looks like this:
public function updateUser(Request $request, $id)
{
$user = User::find($id);
$user->update($request->all());
$user->save();
return back()->with('flash', 'Account is geupdate');
}
In the database, a user has a role_id and in the role table, it has all the roles. So the relations are: User has a Role, Role has many users. These relations are set in the models. So {{ $user->role->role_name }} works just fine.
Thanks in advance!
Assume role_name is unique. In your post method you can do the following-
public function updateUser(Request $request, $id)
{
$role = Role::where('role_name','=',$request->input('role_name'))->first();
$user = User::find($id);
$user->role_id = $role->id;
$user->save();
return back()->with('flash', 'Account is geupdate');
}
As per your comment, add this on your user model-
public function setPasswordAttribute($password)
{
$this->attributes['password'] = bcrypt($password);
}
Hope it helps :)
I Want to Create multi category for posts in database but I Just create one category with this code:
post.php
public function Category()
{
return $this->belongsTo('App\Category');
}
Category.php
public function posts()
{
return $this->belongsToMany('App\Post');
}
posts_table:
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->integer('category_id');
$table->string('title');
$table->integer('price');
$table->string('description');
$table->timestamps();
});
}
and view for create category is here:
<form method="post" action="/storePost">
{{csrf_field()}}
<input type="hidden" id="user_id" name="user_id" value="
{{Auth::user()->id}}">
<lable>title</lable>
<input type="text" id="title" name="title">
<label>description</label>
<input type="text" id="description" name="description">
<label>price</label>
<input type="text" name="price" id="price">
<label>Category</label>
<select name="category_id">
#foreach($categories as $category)
<option value={{$category->id}}>{{$category->name}}</option>
#endforeach
</select>
<button type="submit" id="AddProduct">add</button>
</form>
And my postcontroller to create category is:
public function store()
{
Post::create([
'user_id'=>request('user_id'),
'title' => request('title'),
'category_id'=>request('category_id'),
'description'=>request('description'),
'price'=>request('price'),
]);
return redirect('/show');
}
How I Can create multi category for one posts in table?
You are going to need to design your database somewhat differently. You need a proper join table between the two tables. Your database should look something like this:
posts
id
//other
categories
id
//other
post_categories
post_id
category_id
Once you have the database setup with a proper join. You have to define the relations a little bit differently:
// App\Models\Post
public function categories() {
return $this->belongsToMany('App\Category', 'post_categories', 'category_id', 'post_id');
}
// App\Models\Category
public function posts() {
return $this->belongsToMany('App\Post', 'post_categories', 'post_id', 'category_id');
}
You can then use attach and detach to add and remove relations:
$post = Post::find(1);
$post->categories()->attach($categoryId);
You can read more about many-to-many relationships in the Laravel Documentation.