I have two tables at db, one of them is named users which simply contains user information of website and the other one is tags which contains some hashtags that users can choose from them.
I also created a table named tag_user that can store the tag_id and user_id like this image:
(just like Stackoverflow that a user can select multiple tags such as php, javascript & etc)
So in order to make this relationship between these two, I added this to User model:
public function tags()
{
return $this->belongsToMany(Tag::class);
}
And also this one to Tag model:
public function users()
{
return $this->belongsToMany(User::class);
}
And here is the select option on blade, and users can select multiple tags from db:
<select class="form-control BSinaBold" name="skills[]" id="skills" multiple>
#foreach(\App\Models\Tag::all() as $tag)
<option value="{{ $tag->id }}" {{ in_array($tag->id , Auth::user()->tags->pluck('id')->toArray()) ? 'selected' : '' }}>{{ $tag->name }}</option>
#endforeach
</select>
Then at the Controller, I added this in order to update data at tags table:
public function update(Request $request, $profile)
{
$validate_data = Validator::make($request->all(),[
'job' => 'nullable',
'stackoverflow' => 'nullable',
'github' => 'nullable',
'instagram' => 'nullable',
'linkedin' => 'nullable',
'website' => 'nullable',
'location' => 'nullable',
'skills' => 'array',
]);
$user = User::findOrFail($profile);
$user->update([
'job' => request('job'),
'stackoverflow' => request('stackoverflow'),
'github' => request('github'),
'instagram' => request('instagram'),
'linkedin' => request('linkedin'),
'website' => request('website'),
'location' => request('location'),
]);
$user->tags()->sync(request('skills'));
$user->save();
return view('profile');
}
And it works fine and perfect but the only problem is this line, that does not sync data at tags table:
$user->tags()->sync(request('skills'));
So I tried debugging and I found out that request('skills') is EMPTY!
So the question is, why it does not send any data to the Controller?
I would really appreciate any idea or suggestion from you guys...
Thanks in advance.
UPDATE #1:
If the skills array is not being posted correctly on the form submission, then there could just be a simple problem with the form. Are you posting normally or using an AJAX call? Do you have a conflicting field on the form called 'skills' like a hidden input? Is the skills field located within the <form> tag?
Otherwise, if the browser is in fact posting the skills correctly but just not being read correctly by the request (unlikely), how about you try to switch your request helper functions request() to use the $request object that was passed into your function. IDK, but maybe it will work differently by some chance since we can't see all your code.
Also note that the validation function isn't doing much of anything since nothing is required.
public function update(Request $request, $profile)
{
$user = User::findOrFail($profile);
$user->update([
'job' => $request->input('job', null),
'stackoverflow' => $request->input('stackoverflow', null),
'github' => $request->input('github', null),
'instagram' => $request->input('instagram', null),
'linkedin' => $request->input('linkedin', null),
'website' => $request->input('website', null),
'location' => $request->input('location', null),
]);
$user->tags()->sync($request->input('skills', []));
// I don't think you need this since update & sync trigger saving
// $user->save();
return view('profile');
}
If you want to see all the data getting posted you can just dump or log the data for debugging:
public function update(Request $request, $profile)
{
Log::debug($request->all());
dd($request->all());
...
Related
I have two models:
User:
id
Post:
id
user_id
belongsTo User
text
I want to update a Post record, which way to validate user_id is better?
Number 1
Pass user_id to controller with get method like:
Route::post('/post/edit/{user_id}/{post_id}', 'PostController#update')->name('post.update');
and validate it in controller:
public function update($user_id, $post_id, Request $request){
abort_if(!User::first($user_id), 404);
$request->validate([
'text' => 'string|...',
]);
Post::findOrFail($post_id)->update([
'user_id' => $user_id,
'text' => $request->text,
]);
Number 2
Pass user_id with hidden field with POST method like:
view:
<input type="hidden" name="user_id" value="{{ $user_id }}>
Routing:
Route::post('/post/edit/{post_id}', 'PostController#update')->name('post.update');
Controller:
public function update($post_id, PostUpdate $request){
Post::findOrFail($post_id)->update([
'user_id' => $request->user_id,
'text' => $request->text,
]);
}
PostUpdate request:
public function rules()
{
return [
'user_id' => 'required|exists:users,id',
'text' => 'string',
];
}
Which way is proper or better?
If the user is the authentified user, use the Auth::class
public function update($post_id, Request $request){
$request->validate([
'text' => 'string|...',
]);
Post::findOrFail($post_id)->update([
'user_id' => \Auth::id(),
'text' => $request->text,
]);
}
You can even make sure the post owner is the current user (which is better).
public function update($post_id, Request $request){
$request->validate([
'text' => 'string|...',
]);
Post::where('user_id', \Auth::id())->findOrFail($post_id)->update([
'text' => $request->text,
]);
}
//or (and this is the proper way to do it. It does the same amout of queries and is way easier to read/maintain).
public function update($post_id, Request $request){
$request->validate([
'text' => 'string|...',
]);
$user = \Auth::user();
$post = $user->posts()->findOrFail($post_id);
$post->text = $request->text;
$post->save();
}
No need for the user validation since all of that is handled at login and the rest is maintained through middleware.
Route:
Route::post('/post/edit/{post_id}', 'PostController#update')->middleware('auth')->name('post.update');
I suggest another way for you. Work with middlewares.
In the gate you can check the type of user, so users should be able to edit if they are the owner. In this case you can add some other rules just in one file and user everywhere you want.
In app/Providers/AuthServiceProvider.php define your gate:
Gate::define('update-post', function ($user, \App\Post $post) {
return $user->id === $post->user_id;
});
Then in your routes web.php:
Route::get('/edit/{post}', 'PostController#edit')
->name('edit_post')
->middleware('can:update-post,post');
Route::post('/edit/{post}', 'PostController#update')
->name('update_post')
->middleware('can:update-post,post');
I have two tables at db, one of them is named users which simply contains user information of website and the other one is tags which contains some hashtags that users can choose from them.
(just like Stackoverflow that a user can select multiple tags such as php, javascript & etc)
So in order to make this relationship between these two, I added this to User model:
public function tags()
{
return $this->belongsToMany(Tag::class);
}
And also this one to Tag model:
public function users()
{
return $this->belongsToMany(User::class);
}
And here is the select option on blade, and users can select multiple tags from db:
<select class="form-control BSinaBold" name="skills[]" id="skills" multiple>
#foreach(\App\Models\Tag::all() as $tag)
<option value="{{ $tag->id }}" {{ in_array($tag->id , Auth::user()->tags->pluck('id')->toArray()) ? 'selected' : '' }}>{{ $tag->name }}</option>
#endforeach
</select>
Then at the Controller, I added this in order to update data at tags table:
public function update(Request $request, $profile)
{
$validate_data = Validator::make($request->all(),[
'job' => 'nullable',
'stackoverflow' => 'nullable',
'github' => 'nullable',
'instagram' => 'nullable',
'linkedin' => 'nullable',
'website' => 'nullable',
'location' => 'nullable',
'skills' => 'array',
]);
$user = User::findOrFail($profile);
$user->update([
'job' => request('job'),
'stackoverflow' => request('stackoverflow'),
'github' => request('github'),
'instagram' => request('instagram'),
'linkedin' => request('linkedin'),
'website' => request('website'),
'location' => request('location'),
]);
$user->tags()->sync(request('skills'));
$user->save();
return view('profile');
}
And it works fine and perfect but the only problem is this line, that does not sync data at tags table:
$user->tags()->sync(request('skills'));
So I tried debugging and I found out that request('skills') is EMPTY!
So the question is, why it does not send any data to the Controller?
I would really appreciate any idea or suggestion from you guys...
Thanks in advance.
I think you define your model relation wrong.
Tag model should be:
public function user()
{
return $this->belongsTo(User::class);
}
and the User Model relations:
public function tags()
{
return $this->hasMany(Tag::class);
}
If you aim to establish a one-to-many relation.
My project requires that the admin has to approve the item uploaded by the user in order for this item to be seen in the website as in sort of validation or some kind of keeping everything under control.
so in the Item table, I have a field called (status) and has a default value = (denied).
$table->enum('status',['available','denied'])->default('denied');
The admin sees all items and I want a button next to each item called approve if the admin clicks it the status change from denied to approved, how can I create a function in the controller that changes only the status field? one besides the default edit and update function that is already working in my controller.
public function edit($itemid)
{
$where = array('itemid' => $itemid);
$data['item_info'] = Item::where($where)->first();
return view('items.edititem', $data);
}
public function update(Request $request, $itemid)
{
$request->validate([
'name' => 'required',
'description' => 'required',
'state' => 'required',
'price' => 'required',
'charityfee' => 'required',
'status' => 'required',
'category' => 'required',
]);
$update = [
'name' => $request->name, 'description' => $request->description,
'state' => $request->state, 'price' => $request->price,
'charityfee' => $request->charityfee, 'status' => $request->status,
'category' => $request->category, 'itemphoto' => $request->itemphoto
];
Item::where('itemid', $itemid)->update($update);
return Redirect::to('profile')
->with('success', 'Great! item updated successfully');
}
Although I tried this following code, an error appeared that the function I have called is not defined:(
public function editstatus($itemid)
{
Item::where('itemid', $itemid)->update(array('itemid' => 'available'));
}
function in controller
<td>approve</td>
the code in the view
Your problem is on editstatus function.
you want to update status => 'available' but you code update itemid => 'available'. that why it error.
you code should change to below:
public function editstatus($itemid)
{
Item::where('itemid', $itemid)->update(array('status' => 'available'));
}
I'm pretty sure your $where variable is wrong, You want to compare a variable with a field just get rid of the '=>'. You are basically doing an assigment operation and not a comparison.
You can have it this way
$data['item_info'] = Item::where($itemid, 'item_id')->first();
I made a page for a user to update his company information, all companies default values are null, when a user is created. When a user fills the information, i get this error:
Method Illuminate\Database\Eloquent\Collection::update does not exist
I am sure this error is because of my CompanyController#edit
public function edit(Request $request)
{
$this->validate($request, [
'company_name' => 'alpha|max:50',
'phone' => 'integer|max:50',
'gst_hst_number' => 'integer|max:50',
'country' => 'alpha|max:50',
]);
$companies = Company::where('id', Auth::user()->id)->get();
$companies->update([
'company_name' => $request->input('company_name'),
'phone' => $request->input('phone'),
'gst_hst_number' => $request->input('gst_hst_number'),
'country' => $request->input('country')
]);
return redirect()->route('company.index')->with('info', 'Company information was updated.');
}
I am stuck quite some time on this issue, would gladly apriciate help and information how to properly update my company models fillable fields.
As the error message says, you are using the update method on a collection, you have to change the select query to this:
$companies = Company::where('id', Auth::user()->id)->first();
Because the get() method returns a collection, not a single record.
Try this. ->get() is for multiple collections here you can directly update your records.
$companies = Company::where('id', Auth::user()->id)->update([
'company_name' => $request->input('company_name'),
'phone' => $request->input('phone'),
'gst_hst_number' => $request->input('gst_hst_number'),
'country' => $request->input('country')
]);;
Your using update method on collection, but collection doesn't have update method,
what you need is remove the get(), so you can use update method on eloquent builder:
$companies = Company::where('id', Auth::user()->id);
$companies->update([
'company_name' => $request->input('company_name'),
'phone' => $request->input('phone'),
'gst_hst_number' => $request->input('gst_hst_number'),
'country' => $request->input('country')
]);
I have a customers table that I use a CustomerRequest to validate the fields, through the use of the rules function. The table has an email field which is required and is unique. This works fine when I create the customer, however when I update the customer info (let's say I got their last name spelled wrong) my request fails because the email address is already in the database.
Here is my CustomerRequest:
public function rules()
{
return [
'givenname' => 'required',
'surname' => 'required',
'email' => 'required|unique:customers,email',
];
}
I would like to reuse the CustomerRequest for all of the customer vaildation, how can I go about doing this?
You need to check here for request type as well as customer id for update and then return rules according to request. Something like this
public function rules(Request $customer_request)
{
return [
'givenname' => 'required',
'surname' => 'required',
'email' => 'required|unique:customers,email,'.$customer_request->get('customer_id'),
];
}