for a dynamic form in which fields can be added and modified:
in form
<input name="gallery[1][title]">
<input name="gallery[1][text]">
.
.
.
<input name="gallery[n][title]">
<input name="gallery[n][text]">
in controller for validation:
'gallery.*.file' => 'nullable|image',
'gallery.*.title' => 'nullable|string',
in localization file:
I never know how many are going to be in the array.
'gallery.*.text' => 'text of gallery 1',
'gallery.*.title' => 'title of gallery 1',
how can I write it?
I want something like this in results:
title of gallery 1
.
.
.
title of gallery n
Here's a hacky way to do this. Unfortunately laravel does not currently support adding general message replacers for specific tokens so here's what you could do:
In controller:
$replacer = function ($message, $attribute) {
$index = array_get(explode(".",$attribute),1);
$message = str_replace(":index",$index,$message);
//You may need to do additional replacements here if there's more tokens
return $message;
}
$this->getValidationFactory()->replacer("nullable", $replacer);
$this->getValidationFactory()->replacer("string", $replacer);
$this->getValidationFactory()->replacer("image", $replacer);
$v = $this->getValidationFactory()->make($request->all(), $rules);
if ($v->fails()) {
$this->throwValidationException($request, $v); //Simulate the $this->validate() behaviour
}
You could also add the replacers in the service provider to have them available in all routes, but unfortunately you need to register them for each rule you want them available for.
In localisation file:
'gallery.*.text' => 'text of gallery :index',
'gallery.*.title' => 'title of gallery :index',
Update in laravel 7
your_language/validation.php
es it/validation.php
'attributes' => [
'gallery.*.file' => 'Your custom message!!',
],
Need to modify the form and controller validation
IN Form
{!! Form::open(['url' => 'actionURL']) !!}
{{ csrf_field() }}
<input name="gallery[]">
{!! Form::close() !!}
In Controller
foreach ($request->gallery as $key => $gallery) {
$validator = Validator::make(array('gallery => $gallery),
array('gallery' => 'required'));
}
Related
I am creating a simple blog site with CRUD functionality in Laravel 8. I have done this before using the deprecated Laravel forms, but am now trying to do it using HTML forms.
However, I am having some problem with the update part of the website. I have a controller called BlogsController with this function to be called to update the blog in the database which should be called when the user submits the form to update.
BlogsController update function
public function update(Request $request, $id)
{
$this->validate($request, [
'title' => 'required',
'body' => 'required',
'category' => 'required',
'description' => 'required',
'read_time' => 'required'
]);
$blog = Blog::find($id);
$blog->title = $request->input('title');
$blog->body = $request->input('body');
$blog->category = $request->input('category');
$blog->description = $request->input('description');
$blog->read_time = $request->input('read_time');
$blog->user_id = auth()->user()->id;
$blog->save();
return redirect('/dashboard')->with('success', 'Blog Updated');
}
What action does the form need to direct to? Top of update form
<form method="POST" action="update">
Route in web.php
Route::resource('blog', 'App\Http\Controllers\BlogsController');
Implementation in Laravel forms
{!! Form::open(['action' => ['App\Http\Controllers\BlogsController#update', $blog->id], 'method' => 'POST']) !!}
You can get a list of all your application routes and names by running
$ php artisan route:list
For your blog update route you should use
<form method="POST" action="{{ route('blog.update', ['blog' => $blog]) }}">
#method('PATCH')
</form>
in your template.
Make sure you have you have your csrf token set correctly at your form by using the #csrf, see Laravel docs.
One thing that's cool with Laravel is Route model binding. So what's that mean? We can do something like this in your update method
// BlogController.php
public function update(Request $request, Blog $blog) {
$request->validate([
'title' => 'required',
'body' => 'required',
'category' => 'required',
'description' => 'required',
'read_time' => 'required'
]);
$blog->title = $request->title;
$blog->body = $request->body;
$blog->category = $request->category;
$blog->description = $request->description;
$blog->read_time = $request->read_time;
if ($blog->save()) {
return redirect('/dashboard')->with('success', 'Blog Updated');
} else {
// handle error.
}
}
In your template, you'll want to make sure you're using a PATCH method:
<form method="POST" action="{{ route('blog.update', ['blog' => $blog]) }}">
#csrf
#method('PATCH')
...
</form>
I assume you are using Resource route for your CRUD functionality. In that case, Update method in resource controller called via PUT method and not POST. So, in your form, just add this to change the Form submission method to PUT:
<input name="_method" type="hidden" value="PUT">
Also, in your form declaration, you have to add the destination route like this:
<form method="POST" action="{{ route('blog.update', $blog->id) }}">
You also have the option of using the action to get a URL to the registered route:
action('App\Http\Controllers\BlogsController#update', ['blog' => $blog])
Check all route list:
$ php artisan route:list
your route should be like:
<form method="POST" action="{{ route('blog.update', ['blog' => $blog]) }}">
{{csrf_field()}}
{{ method_field('PATCH') }}
</form>
I want to make an edit_Item functionality, but I'm having a little bit of trouble with routing when submiting the edited form. I get this error:
InvalidArgumentException in UrlGenerator.php line 314:
Route [userItems] not defined.
First of all, in my Edit page, I have a form which passes 2 arguments from the Items table (item_id and user_id) to the controller and it looks like this:
{!! Form::model($items, ['action' => ['ItemController#update', $items->id, $items->user_id], 'method' => 'PUT']) !!}
//Form inputs
{{ Form::close() }}
My Update controller looks like this:
public function update($id, $user_id){
// validate
// read more on validation at http://laravel.com/docs/validation
$rules = array(
'title' => 'required',
'description' => 'required|description',
);
// store
$items = Item::find($id);
$items->title = Input::get('title');
$items->description = Input::get('description');
$items->save();
// redirect
Session::flash('message', 'Successfully updated item!');
return Redirect::route('userItems');
}
And my Route with the Update method looks like this:
Route::put('/userItems/{id}/{user_id}', 'ItemController#update');
Now, when I submit I'm currently getting routed to:
http://localhost:8000/userItems/26/3
And I need to get routed to:
http://localhost:8000/userItems/3
Any ideas on how to make the item_id(26) disappear from the route?
You could use an hidden input
Define a hidden field (not visible to a user).
Your form
{!! Form::model($items, ['action' => ['ItemController#update', $items->user_id], 'method' => 'PUT']) !!}
<input type="hidden" name="item_id" value="{{$items->id}}">
//Form inputs
{{ Form::close() }}
Your route
Route::put('/userItems/{user_id}', 'ItemController#update');
Your controller
public function update($user_id){
// validate
// read more on validation at http://laravel.com/docs/validation
$rules = array(
'title' => 'required',
'description' => 'required|description',
);
// store
$item_id = Request::input('item_id');
$items = Item::find($item_id);
$items->title = Input::get('title');
$items->description = Input::get('description');
$items->save();
// redirect
Session::flash('message', 'Successfully updated item!');
return Redirect::route('userItems');
}
The part of form (the field text array)[1]:
<div id="cp1">
<div class="form-group">
{!! Form::text('names[]',null,['class'=>'form-control', 'maxlength'=>'30', 'placeholder'=>'Name']) !!}
</div>
<div class="form-group">
{!! Form::text('contents[]',null,['class'=>'form-control', 'maxlength'=>'30', 'placeholder'=>'Content']) !!}
</div>
</div>
When i send the form, validation fails with:
htmlentities() expects parameter 1 to be string, array given (View: /Applications/MAMP/htdocs/telovendogdl/resources/views/ads/new.blade.php)
this is the rules in form request:
return ['title' => 'required|min:8|max:100',
'description' => 'required|min:10|max:1100',
'price' => 'required|integer|max:15',
'city_name'=> 'required|max:70',
'category_id' => 'required|integer',
'delivery'=> 'max:70',
];
This is the function in the controller:[2]
public function newAdStore(StoreNewAdRequest $request)
{
$newAd = new Ad;
$newAd->user_id = \Auth::user()->id;
$newAd->active = 0;
$newAd->city_name = $request->input('city_name');
$newAd->category_id = $request->input('category_id');
$newAd->fill($request->all());
$newAd->save();
}
but only fails when i send the array fields from the form [1], when a delete this fields all works? what happen with that[2]?
I don't have a clear vision of your code but I am gonna try to help you debug your code ... first you need to add a rule to your StoreNewAdRequest to handle an array instead of string for names[] and contents[] :
public function rules()
{
$rules = [
'field2' => 'required|...',
'field3' => 'required|...',
....
];
foreach($this->request->get('names') as $key => $val)
{
$rules['names.'.$key] = 'required|max:100';
}
return $rules;
}
Make sure you have the right fillable params in your model
Note: the problem maybe occurred at this stage
$newAd->fill($request->all())
you are trying to fill an array of names[] & contents[] instead of strings ..
I am having trouble getting getting my parameter of 'item id' to tack onto the end of my route being generated for my form action url.
I have a page setup to 'update' an existing item. The routes looks something like this:
Route::get('/item/edit/{id}', array(
'as' => 'item-edit',
'uses' => 'ItemController#getEditItem',
));
Route::post('/item/edit/{id}', array(
'as' => 'item-edit-post',
'uses' => 'ItemController#postEditItem',
));
and my ItemController contains these methods:
public function getEditItem($id) {
$states = State::where('user_id', '=', Auth::user()->id)->get();
$types = Type::where('user_id', '=', Auth::user()->id)->get();
$item = Item::where('user_id', '=', Auth::user()->id)
->where('id', '=', $id)
->first();
return View::make('items.edit')
->with('item', $item)
->with('states', $states)
->with('types', $types);
}
public function postEditItem($id) {
// Validate input for Item changes
$validator = Validator::make(Input::all(),
array(
'label' => 'required|min:3|max:128|unique:items,label,null,id,user_id,' . Auth::user()->id,
'type_id' => 'required|integer',
'state_id' => 'required|integer',
)
);
if( $validator->fails() ) {
return Redirect::route('item-edit')
->withErrors($validator)
->withInput();
} else {
$item = Item::find($id);
$item->label = Input::get('label');
$item->type_id = Input::get('type_id');
$item->state_id = Input::get('state_id');
$item->save();
return Redirect::route('item-create')
->with('global', 'Your new item has been edited successfully!');
}
}
The last piece of the puzzle is my items.edit view:
#extends('layout.main')
#section('content')
<form action="{{ URL::route('item-edit-post', $item->id) }}" method="post" class="form-horizontal form-bordered" autocomplete="off">
<!-- some inputs and such -->
</form>
#stop
The action URL being generated here is wrong:
<form method="POST" action="http://manageitems.com/item/edit/%7Bid%7D" accept-charset="UTF-8" hello="hello" class="form-horizontal form-bordered">
For some reason it is escaping my {id} in the route and not adding on the actual item ID on the end of the route. I have tried a few different ways of doing this and read through the route parameter docs, but I haven't made any progress. I also tried using Laravel's for builder like so:
{{ Form::open(array('action' => 'ItemController#postEditItem', $item->id, 'class'=>'form-horizontal form-bordered')) }}
but this did the same thing. I am new to Laravel so this may be a simple problem that I am overlooking, any help is much appreciated.
Use an array in the second parameter.
URL::route('item-edit-post', ['id' => $item->id])
Or the route helper (what I would go with, fits more in view files).
route('item-edit-post', ['id' => $item->id])
It seems that $item->id returns null.
And this is how you do it, when you specify action or route in the Form::open:
Form::open(['route' => ['some.route', $param]]);
Form::open(['action' => ['controller#action', $param]]);
I've built a basic application in Laravel here - however I have two models namely an article and photo model. An Article can have many photos and so I have set up my form so that you can dynamically via javascript add multiple file inputs. The problem here is that if there are no validation errors the form works just swell - however if there is a validation error - I get this scary error message that says
htmlentities() expects parameter 1 to be string, array given (View: D:\wamp\www\one1\one1info-revamped\app\views\administration\articles\create.blade.php)
Here is the code of my store method in the controller:
public function store()
{
$input = Input::except('photos', 'captions');
$validation = Validator::make($input, Article::$rules);
$photos = Input::file('photos');
$captions = Input::file('captions');
if ($validation->passes() ){
$article = $this->article->create($input);
foreach($photos as $ii => $one_photo){
$photo = new Photo();
$name = $article->title . '-' . $ii;
$photo->create_n_upload($one_photo, array( 'name'=>$name,
'caption'=>$captions[$ii],
'imageable_type'=>'Article',
'imageable_id'=>$article->id ));
}
return Redirect::route('admin.articles.index');
}
return Redirect::route('admin.articles.create')
->withInput()->withErrors($validation);
}
I don't really know where am I getting this wrong here - also here is my article model:
class Article extends Eloquent {
protected $guarded = array();
public function photos()
{
return $this->morphMany('Photo', 'imageable');
}
public static $rules = array(
'title' => 'required',
'author' => 'required',
'caption' => 'required',
'body' => 'required',
'section_id'=>'required',
'dated'=>'',
'is_published' => 'required',
'created_by' => ''
);
}
You can see I haven't put any rules yet for the images - however just including them within the form has started to cause this error. It only happens if the validation fails - if everything is entered as required - it goes smoothly however I need to make sure that error handling is working fine here.
Here is what the upload file looks like on my form:
<li>
{{ Form::label('images', 'Images:') }}
ADD IMAGE
<div class="clearfix"></div>
<ul id="image-upload-holder">
<li>
<div class="well">
<input name="photos[]" type="file" />
{{ Form::text('captions[]') }}
<i class="icon-cross"/>
</div>
</li>
</ul>
</li>