why does laravel ignore my update method? [closed] - laravel

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I've an update function for my Gamecontroller but it gets completely ignored when I call it and it just redirects to show view instead of executing the function despite calling it, am I missing something obvious?
Things I know and tried:
Every other function works in the GameController
I tried calling other functions like game.create and game.delete from that same view so I doubt it has to do with my view
I tried making the validate fail which got ignored because the function somehow doesn't get called
I tried just commenting the entire function and it did nothing didn't even give an error like it should
Checked to see if there was somehow a double function (there wasn't)
My update function in GameController class
public function update(Request $request, $id)
{
$validated = $request->validate([
'naam' => 'required|max:1',
'img' => 'required',
'formaat' => 'required',
'datum' => 'required',
'locatie' => 'required',
]);
if($validated->fails()){
return redirect()->back()->withErrors($validated);
}
DB::table('games')
->where('id', $id)
->update([
'naam' => $request->naam,
'img' => $request->img,
'formaat' => $request->formaat,
'datum' => $request->datum,
'locatie' => $request->locatie,
]);
return Redirect::to('games')
->with('success','Great! game updated successfully.');
}
My view:
<form action="{{ route('games.update',$data->id) }}" method="PUT" name="edit_games">
#csrf
<div class="row">
<div class="col-md-12">
<div class="form-group">
<strong>Naam</strong>
<input type="text" name="naam" class="form-control" value= "{{ $data->naam }}" />
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<strong>Pad van de afbeelding</strong>
<input type="text" name="img" class="form-control" value="{{$data->img}}" />
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<strong>Formaat</strong>
<input type="text" class="form-control" name="formaat" value="{{$data->formaat}}" />
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<strong>Datum</strong>
<input type="date" class="form-control" name="datum" value={{$data->datum}}/>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<strong>Locatie</strong>
<input type="text" class="form-control" name="locatie" value="{{$data->locatie}}"/>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</form>
The route in web
Route::resource('/games', 'GameController');

HTML Forms can only have GET or POST method used. You have defined the method attribute as PUT: method="PUT"; this will end up using the GET method, which would end you up at your show route. Change your method attribute to POST then add a hidden field named _method with the desired HTTP method (PUT) in your case. (Form method spoofing)
<form method="POST" ....>
{{ method_field('PUT') }}
method_field('PUT') will end up putting a hidden input into your form:
<input type="hidden" name="_method" value="PUT">
Laravel 6.x Docs - Routing - Form Method Spoofing

Related

How to add form action to laravel function

I have a website I am currently editing tht was built with laravel. I have have a page that displays a "details of shipped package"
I added a form to page to update the current location of the shipped package on the details page.
<div class="row mb-30">
<div class="col-lg-12 mt-2">
<div class="card border--dark">
<h5 class="card-header bg--dark">#lang('Courier Location')</h5>
<div class="card-body">
<form action="{{route('....')}}" method="POST">
#csrf
<div class="modal-body">
<div class="form-group">
<label for="current_location" class="form-control-label font-weight-bold">#lang('Current Location')</label>
<input type="text" class="form-control form-control-lg" name="current_location" value="{{__($courierInfo->current_location)}}" required="">
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn--primary"><i class="fa fa-fw fa-paper-plane"></i>#lang('Update')</button>
</div>
</form>
</div>
</div>
</div>
I have also added the update function in the controller
public function courierUpdate(Request $request, $id)
{
$request->validate([
'current_location' => 'required',
]);
$courierInfoUpdate =CourierInfo::findOrFail($id);
$courierInfoUpdate->current_location = $request->current_location;
$courierInfoUpdate->save();
$notify[] = ['success', 'Courier location info has been updated'];
return back()->withNotify($notify);
}
I am having problem with the laravel route to call that should be added as form action.
Declare a route on the web.php
Route::post('/courier-Update/{id}','App\Http\Controllers\YourControllerName#courierUpdate')->name('courier.Update');
and now just call this route in your form and also pass the id of that courier
like this:
route('courier.Update',$courier->id)
You can add a new route in routes/web.php
//import your controller at Beginning of the file
use App\Http\Controllers\YourController;
Route::post('update_location/{id}', [YourController::class, 'courierUpdate'])->name('updateLocation');
//or
Route::post('update_location/{id}', 'YourController#courierUpdate')->name('updateLocation');
And then in your blade view
<form action="{{ route('updateLocation', [ 'id' => $id]) }}" method="POST">
#csrf
</form>

how to scroll to first validation error message in livewire laravel

I am new in livewire. i am working on registration process of user. Register form is quite big and validations also working fine to me. The problem is when user submits the form validations came but user not able to see because submit button is at bottom and form is at top.
When i manually scroll to top error message is displaying. So what i want when user submits the form its will automatically go to first error message. Here is my code:
<form wire:submit.prevent="userRegister">
<div class="row">
<div class="col-md-3">
<label>First Name *</label>
</div>
<div class="col-md-9">
<input type="text" wire:model="register.first_name" placeholder="Enter First Name" required>
#error('register.first_name') <span class="text-danger">{{ $message }}</span> #enderror
</div>
</div>
<div class="row">
<div class="col-md-3">
<label>Last Name *</label>
</div>
<div class="col-md-9">
<input type="text" wire:model="register.last_name" placeholder="Enter Last Name">
#error('register.last_name') <span class="text-danger">{{ $message }}</span> #enderror
</div>
</div>
<div class="row">
<div class="col-md-3">
<label>Test 1 Name *</label>
</div>
<div class="col-md-9">
<input type="text" wire:model="register.test1_name" placeholder="Enter Last Name">
</div>
</div>
<div class="row">
<div class="col-md-3">
<label>Test 2 Name *</label>
</div>
<div class="col-md-9">
<input type="text" wire:model="register.test2_name" placeholder="Enter Last Name">
</div>
</div>
<div class="row">
<div class="col-md-3">
<label>Test 3 Name *</label>
</div>
<div class="col-md-9">
<input type="text" wire:model="register.test3_name" placeholder="Enter Last Name">
</div>
</div>
<div class="row">
<div class="col-md-3"></div>
<div class="col-md-9">
<!--<input type="submit" value="Edit" class="edt-sb">-->
<input wire:click="userRegister" type="submit" value="Submit" class="edt-sv">
</div>
</div>
</form>
My Register.php
<?php
namespace App\Http\Livewire;
use Livewire\Component;
class Register extends Component
{
public $register;
protected $rules = [
'register.first_name' => 'bail|required|max:50',
'register.last_name' => 'bail|required|max:50',
];
protected $messages = [
'register.first_name.required' => 'Please enter first name',
];
public function userRegister(){
$this->validate();
}
I want when user submits the form it will immediately scroll to first error message. Currently my validations work perfects for me. Do i need to use alpine js? for this.
Livewire errors will be saved in $errors bag so probably you can add an id to each field in your form and use alpinejs to focus the first element with the id present in the errors bag, something like:
<div x-data="{
'errors': {{ json_encode(array_keys($errors->getMessages())) }},
focusField(input) {
fieldError = document.getElementById(input);
if (fieldError) {
fieldError.focus({preventScroll:false});
}
},
}"
x-init="() => { $watch('errors', value => focusField(value[0])) }">
<input id="register.test3_name" type="text" wire:model="register.test3_name" placeholder="Enter Last Name">
</div>
I nearly faced the same issue but with success message not error messages, for error messages I used updated(), they are shown on real time for user while filling the fields.
My Class Component :
class FormSubmissions extends Component
{
public $city;
public $fullname;
protected $rules = [
'city' => 'required',
'fullname' => 'required',
];
public $successMessage;
public function updated($propertyName)
{
$this->validateOnly($propertyName);
}
public function submitForm()
{
$submission = $this->validate();
$this->successMessage = trans('site.success');
$this->resetForm();
}
public function resetForm()
{
$this->city = '';
$this->fullname = '';
}
}
My Blade template :
<div id="formSection" class="form-wrapper">
#if ($successMessage)
<div class="alert alert-success alert-dismissible fade show" role="alert">
{{ $successMessage }}
<button wire:click="$set('successMessage', null)" type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<script>
var elmnt = document.getElementById("formSection");
elmnt.scrollIntoView();
</script>
#endif
<form wire:submit.prevent="submitForm" action="/" method="POST">
...
</div>
So the small script added with success message allowed me to scroll back to top of my form Section #formSection.
If you are using <x-jet-input-error/> component for displaying errors, you can just modify resources/views/vendor/jetstream/components/input-error.blade.php (make sure you have published livewire views) file to below code:
#props(['for'])
<span x-data="{hasError: '{{$errors->get($for)[0] ?? ''}}' }"
x-init="()=> { $watch('hasError', (value)=> {
let errorDiv = document.getElementsByClassName('invalid-feedback')[0];
if(errorDiv){
errorDiv.scrollIntoView({behavior: 'smooth', block: 'center', inline: 'nearest'});
}
})}">
#error($for)
<span {{ $attributes->merge(['class' => 'invalid-feedback d-block']) }} role="alert" style="font-size: inherit">
<strong>{{ $message }}</strong>
</span>
#enderror
</span>
Explanation : we use alpine to watch for changes in the validation message for the "$for" field. As soon as it changes (validation message shows up or vanishes), it looks for the error block and scrolls to it

Laravel 6 Validation Bug?

I have a problem about my Laravel project.
$request->validate(
[
'blogs_file' => 'required|image|mimes:jpeg,jpg,png|max:2048',
'blogs_title' => 'required|unique:App\Blogs,blogs_title',
'blogs_content' => 'required',
]);
I made a limit to blogs_file. It should only allowed jpg,png,jpeg and max 2 MB.
But when i try to put a mp4 file, it pass. What is the problem there?
I have already added enctype="multipart/form-data" to my form on blade page.
If i want to put an mp4 file or zip lower than 2 MB the validation works fine. But if i upload any kind of data upper than 2 MB; it passes. Actually, when i check to my db; blogs_file coming NULL on that way, but it returns with success message to user.
UPDATE:
my create.blade.php file;
<div class="box-body">
<form action="{{route('blogs.store')}}" method="POST" enctype="multipart/form-data">
#csrf
<div class="form-group">
<label>Resim Seç</label>
<div class="row">
<div class="col-xs-12">
<input class="form-control" required name="blogs_file" type="file">
</div>
</div>
</div>
<div class="form-group">
<label>Başlık</label>
<div class="row">
<div class="col-xs-12">
<input class="form-control" required type="text" placeholder="Blog Başlığı..." name="blogs_title">
</div>
</div>
</div>
<div class="form-group">
<label>Sayfa Linki</label>
<div class="row">
<div class="col-xs-12">
<input class="form-control" placeholder="Sayfa linki girebilirsiniz(isteğe bağlı)"
name="blogs_slug" type="text">
</div>
</div>
</div>
<div class="form-group">
<label>İçerik</label>
<div class="row">
<div class="col-xs-12">
<textarea class="form-control" id="editor1" name="blogs_content"
required></textarea>
</div>
<script>
CKEDITOR.replace( 'editor1' );
</script>
</div>
</div>
<div class="form-group">
<label>Durum</label>
<div class="row">
<div class="col-xs-12">
<select name="blogs_status" class="form-control">
<option value="1">Aktif</option>
<option value="0">Pasif</option>
</select>
</div>
</div>
</div>
<div align="right" class="box-footer">
<button type="submit" class="btn btn-primary">Ekle</button>
</div>
</form>
</div>
route:
Route::resource('blogs','BlogController');
BlogController:
public function store(Request $request)
{
if (strlen($request->blogs_slug)>3)
{
$slug=Str::slug($request->blogs_slug);
} else {
$slug=Str::slug($request->blogs_title);
}
if ($request->hasFile('blogs_file'))
{
$request->validate(
[
'blogs_file' => 'required|file|mimes:jpeg,jpg,png|max:2048',
'blogs_title' => 'required|unique:App\Blogs,blogs_title',
'blogs_content' => 'required',
]);
$file_name=uniqid().".".$request->blogs_file->getClientOriginalExtension();
$request->blogs_file->move(public_path('images/blogs'),$file_name);
$request->blogs_file=$file_name;
}
$blog= new Blogs;
$blog->blogs_file=$request->blogs_file;
$blog->blogs_title=$request->blogs_title;
$blog->blogs_slug=$slug;
$blog->blogs_content=$request->blogs_content;
$blog->blogs_status=$request->blogs_status;
$blog->uniqid=uniqid();
$blog->save();
if ($blog)
{
return redirect(route('blogs.index'))->with('success','İşlem Başarılı!');
} else {
return back()->with('error','İşlem Başarısız!');
}
}
1st. You have missed file rule.
2nd. You may use either image rule (that validates a file to be jpeg, png, bmp, gif, svg, or webp) or use mimes:jpeg,jpg,png:
So your validation would be either:
'blogs_file' => 'required|file|mimes:jpeg,jpg,png|max:2048',
Or:
'blogs_file' => 'required|file|image|max:2048',
3rd. You've put your validation $request->validate inside an if, it's wrong and makes the problem! You may conditionally adding rules or use after validation hook for more complex validations instead.

PUT/POST in Laravel

I'm brand new to Laravel and am working my way through the [Laravel 6 from Scratch][1] course over at Laracasts. The course is free but I can't afford a Laracasts membership so I can't ask questions there.
I've finished Section 6 of the course, Controller Techniques, and am having unexpected problems trying to extend the work we've done so far to add a few new features. The course has students build pages that let a user show a list of articles, look at an individual article, create and save a new article, and update and save an existing article. The course work envisioned a very simple article containing just an ID (auto-incremented in the database and not visible to the web user), a title, an excerpt and a body and I got all of the features working for that, including updating an existing article and saving it.
The update form sets method to POST but then uses a #METHOD('PUT') directive to tell the browser that it is actually supposed to do a PUT. This worked perfectly in the original code. However, now that I've added two more fields to the form, when I click Submit after editing an existing record, the save fails with this message:
Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
The PUT method is not supported for this route. Supported methods: GET, HEAD, POST.
http://localhost:8000/articles
I don't understand why adding two fields to the form would cause this to break. Can someone enlighten me? I added the two new fields/columns to the migration and ran migrate:rollback and migrate. I've also added the new fields/columns to the fillable attribute and added validations for them in the ArticlesController.
Here is my routing:
Route::get('/articles', 'ArticlesController#index');
Route::post('/articles', 'ArticlesController#store');
Route::get('/articles/create', 'ArticlesController#create');
Route::get('/articles/{article}', 'ArticlesController#show');
Route::get('/articles/{article}/edit', 'ArticlesController#edit');
Route::put('/articles/{article}', 'ArticlesController#update');
//Route::delete('/articles/{article}', ArticlesController#destroy');
This is my ArticlesController:
<?php
namespace App\Http\Controllers;
use App\Article;
use Illuminate\Http\Request;
class ArticlesController extends Controller
{
public function index()
{
$articles = Article::latest()->get();
return view ('articles.index', ['articles' => $articles]);
}
public function show(Article $article)
{
return view('articles.show', ['article' => $article]);
}
public function create()
{
return view('articles.create');
}
public function store()
{
//Stores a NEW article
Article::create($this->validateArticle());
return redirect('/articles');
}
public function edit(Article $article)
{
return view('articles.edit', ['article' => $article]);
}
public function update(Article $article)
{
//Updates an EXISTING article
$article->update($this->validateArticle());
return redirect('/articles/', $article->id);
}
public function validateArticle()
{
return request()->validate([
'title' => ['required', 'min:5', 'max:20'],
'author' => ['required', 'min:5', 'max:30'],
'photopath' => ['required', 'min:10', 'max:100'],
'excerpt' => ['required', 'min:10', 'max:50'],
'body' => ['required', 'min:50', 'max:500']
]);
}
public function destroy(Article $article)
{
//Display existing record with "Are you sure you want to delete this? Delete|Cancel" option
//If user chooses Delete, delete the record
//If user chooses Cancel, return to the list of articles
}
}
Here's my edit form, edit.blade.php:
#extends('layout')
#section('content')
<div id="wrapper">
<div id="page" class="container">
<h1>Update Article</h1>
<form method="POST" action="/articles">
#csrf
#method('PUT')
<div class="form-group">
<label class="label" for="title">Title</label>
<div class="control">
<input class="form-control #error('title') errorborder #enderror" type="text" name="title" id="title" value="{{ $article->title }}">
#error('title')
<p class="errortext">{{ $errors->first('title') }}</p>
#enderror
</div>
</div>
<div class="form-group">
<label class="label" for="author">Author</label>
<div class="control">
<input class="form-control #error('author') errorborder #enderror" type="text" name="author" id="author" value="{{ $article->author }}">
#error('title')
<p class="errortext">{{ $errors->first('author') }}</p>
#enderror
</div>
</div>
<div class="form-group">
<label class="label" for="photopath">Path to Photo</label>
<div class="control">
<input class="form-control #error('photopath') errorborder #enderror" type="text" name="photopath" id="photopath" value="{{ $article->photopath }}">
#error('title')
<p class="errortext">{{ $errors->first('photopath') }}</p>
#enderror
</div>
</div>
<div class="form-group">
<label class="label" for="excerpt">Excerpt</label>
<div class="control">
<textarea class="form-control #error('excerpt') errorborder #enderror" name="excerpt" id="excerpt">{{ $article->excerpt }}</textarea>
#error('excerpt')
<p class="errortext">{{ $errors->first('excerpt') }}</p>
#enderror
</div>
</div>
<div class="form-group">
<label class="label" for="body">Body</label>
<div class="control">
<textarea class="form-control #error('body') errorborder #enderror" name="body" id="body">{{ $article->body }}</textarea>
#error('body')
<p class="errortext">{{ $errors->first('body') }}</p>
#enderror
</div>
</div>
<div class="control">
<button class="btn btn-primary" type="submit">Submit</button>
</div>
</form>
</div>
</div>
#endsection
Is there anything else you need to see?
[1]: https://laracasts.com/series/laravel-6-from-scratch/episodes/33?autoplay=true
Your Laravel route is:
Route::put('/articles/{article}', 'ArticlesController#update');
So your form action url should match that uri:
<form action="{{ url('/articles/'.$article->id) }}">
where the {article} parameter is the record id (you can read more about in the docs here).
Then in your controller update() method, you have:
return redirect('/articles/', $article->id);
which means redirect to /articles with status code $article->id (you can read more about in the docs here). I think you are trying to redirect to the show route, which is:
Route::get('/articles/{article}', 'ArticlesController#show');
So change the , (comma) to a . (dot) to concatenate the article id with the uri:
return redirect('/articles/' . $article->id);
The route in the form for /articles, However your route for updating should be /articles/{article}
Try this:
<form method="POST" action="/articles/{{ $article->id }}">

How i will get current page title in hidden field, when i submit the form in laravel

I have a form which have name, email and phone. But i want current page title or url when user submit the form, Because I want to track the user page. Please let me know How i can do it.
This is my form code.
<form class="callus" method="post" action="{{url('/sendmailuser')}}">
#csrf
<div class="col-md-3 col-sm-6">
<div class="single-query form-group">
<input type="hidden" name="product_title" value="{{ request('request') }}" class="keyword-input" placeholder="Enter Your Name" required="">
</div>
</div>
<div class="col-md-3 col-sm-6">
<div class="single-query form-group">
<input type="text" name="user_name" class="keyword-input" placeholder="Enter Your Name" required="">
</div>
</div>
<div class="col-md-3 col-sm-6">
<div class="single-query form-group">
<input type="text" name="user_email" class="keyword-input" placeholder="Enter Your Email" required="">
</div>
</div>
<div class="col-md-3 col-sm-6">
<div class="single-query form-group">
<input type="text" name="user_phone" class="keyword-input" placeholder="Enter Your Phone" required="Field is required">
</div>
</div>
<div class="col-md-3 col-sm-6">
<div class="single-query form-group">
<input type="submit" value="submit now" class="btn-blue">
</div>
</div>
</form>
This is my Email send code...
public function sendyourmail(Request $r)
{
$validator = Validator::make($r->all(), [
'user_name' => 'required',
'user_email' =>'required',
'user_phone' =>'required',
'user_desc' =>'required',
]);
if ($validator->fails()) {
return redirect()->back()->withErrors($validator);
}
$data=[
'user_email' => $r->user_email,
'user_name' => $r->user_name,
'user_phone' => $r->user_phone,
'user_desc' => $r->user_desc,
];
Mail::send('mail', $data, function($message) use($data) {
$message->from($data['user_email'], 'Email Form Sumit');
$message->to('sumit#gmail.com')->cc('sumit#sumit.com');
$message->subject($data['user_desc']);
});
return redirect()->back()->with('message','Your Mail Has Been sent Successfully, We Will Get Back to You Shortly.');
}
You should define the title of the rendered page within the controller and past it as parameter to the view when you specify which template should be rendered.
public function sendyourmailform()
{
$title = 'Sample Page Title';
return view('email_template.blade.php', compact('title'));
}
Because the title variable is past to the template you can access it inside the template by rendering it twice inside the title section
#section('title')
{{ $title }}
#endsection
Inside the layout page which is extends by the template which render the form you should have define section named title like this
<head>
<title>
#section('title')
#endsection
<title>
</head>
And you have access to the title variable inside the template part which show the related form.
<form class="callus" method="post" action="{{url('/sendmailuser')}}">
#csrf
<div>
<input type="hidden" name="page_title" value="{{ $title }}">
</div>
<!-- ... -->
</form>

Resources