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>
Related
Laravel 5.4 version
The validate() function works until I test more than 3 errors in the form. Upon automatic redirect after buildfailedvalidationresponse function, the 4 $error messages aren't present on and neither is the old form data. This only doesn't work in chrome. Firefox/internet explorer is fine. I have data dumped throughout the process of validatesrequest file and it shows the $error variables being passed correctly to the buildfailedvalidationresponse function but no errors/old form data are presented after redirect. I was just wondering if anybody has had an issue like this with different browsers.
validation method
protected function validateRegistration(Request $request) {
$rules = array(
'name' => 'required|string',
'email' => array('required','string','email','unique:users,email'),
'phone' => 'required|digits:10',
'userid' => array('required','string','min:6','max:10','unique:users,userid','regex:/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*(_|[^\w])).+$/'),
'password' => array('required','string','min:8','max:12','regex:/^(?
=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*(_|[^\w])).+$/'),
'repeatedpassword' => 'required|string|same:password',
'code' => 'required|digits:4|exists:codes,code'
);
$this->validate($request, $rules);
if ($this) {
$store = new User();
return $store->insertuser();
}
}
blade validation display errors statement
<div class="container">
#if ($errors->any())
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li> {{ $error }} </li>
#endforeach
</ul>
</div>
#endif
</div>
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 ..
Following are my codes:
Model:
class Slide extends \Eloquent {
// Add your validation rules here
public static $rules = [
'title' => 'required|between:3,100',
'image' => 'required',
'url' => 'url',
'active' => 'integer'
];
// Don't forget to fill this array
protected $fillable = ['title', 'image', 'url', 'active'];
}
Controller Update Method:
public function update($id)
{
$slide = Slide::find($id);
$validator = Validator::make($data = Input::all(), Slide::$rules);
if ($validator->fails())
{
return Redirect::back()->withErrors($validator)->withInput();
}
$slide->update($data);
return Redirect::route('admin.slides.index')
->with('message', 'Slide has been updated.')
->with('message-type', 'alert-success');
}
Route:
Route::group(array('prefix' => 'admin'), function() {
# Slides Management
Route::resource('slides', 'AdminSlidesController', array('except' => array('show')));
});
Form in View:
{{ Form::model($slide, array('route' => 'admin.slides.update', $slide->id, 'method' => 'put')) }}
#include('admin/slides/partials/form')
{{ Form::close() }}
Partial Form is simple form, not sure if I need to share it here or not. Let me know.
Error:
Edit page loads perfectly and populates data from db, but when I submit the edit form, I get following error:
Call to a member function update() on a non-object
The following line seems to be creating problems:
$slide->update($data);
I have searched over the internet for solution but nothing is working. Have tried composer dump_autoload, even tried doing everything from scratch in a new project, still same issue. :(
Help please!!
---- Edit ----
Just quickly tried following:
public function update($id)
{
$slide = Slide::find($id);
$slide->title = Input::get('title');
$slide->save();
return Redirect::route('admin.slides.index')
->with('message', 'Slide has been updated.')
->with('message-type', 'alert-success');
}
Now the error:
Creating default object from empty value
----- Solution: -----
The problem was with my form as suggested by #lukasgeiter
I changed my form to following at it worked like a charm:
{{ Form::model($slide, array('route' => array('admin.slides.update', $slide->id), 'method' => 'put')) }}
use $slide->save(); instead of $slide->update($data);
to update a model please read the laravel doc here
To update a model, you may retrieve it, change an attribute, and use the save method:
EX :
$user = User::find(1);
$user->email = 'john#foo.com';
$user->save();
The actual problem is not your controller but your form.
It should be this instead:
{{ Form::model($slide, array('route' => array('admin.slides.update', $slide->id), 'method' => 'put')) }}
This mistake causes the controller to receive no id. Then find() yields no result and returns null.
I recommend besides fixing the form you also use findOrFail() which will throw a ModelNotFoundException if no record is found.
$slide = Slide::findOrFail($id);
I have built a simple application laravel 4. I have scaffolding setup for adding posts which seems to be working fine. I have setup Stapler and image uploading package. When I setup to use single image uploads its pretty good and it works a charm. I recently looked at the docs here
It states that you can do multiple uploads so I went about doing it as explained in the docs. Here are my coded pages:
Post.php model:
<?php
class Post extends Eloquent {
use Codesleeve\Stapler\Stapler;
protected $guarded = array();
// A user has many profile pictures.
public function galleryImages(){
return $this->hasMany('GalleryImage');
}
public static $rules = array(
'title' => 'required',
'body' => 'required'
);
public function __construct(array $attributes = array()) {
$this->hasAttachedFile('picture', [
'styles' => [
'thumbnail' => '100x100',
'large' => '300x300'
],
// 'url' => '/system/:attachment/:id_partition/:style/:filename',
'default_url' => '/:attachment/:style/missing.jpg'
]);
parent::__construct($attributes);
}
}
PostsController.php
/**
* Store a newly created resource in storage.
*
* #return Response
*/
public function store()
{
$input = Input::all();
$validation = Validator::make($input, Post::$rules);
if ($validation->passes())
{
$this->post->create($input);
return Redirect::route('posts.index');
}
$post = Post::create(['picture' => Input::file('picture')]);
foreach(Input::file('photos') as $photo)
{
$galleryImage = new GalleryImage();
$galleryImage->photo = $photo;
$user->galleryImages()->save($galleryImage);
}
return Redirect::route('posts.create')
->withInput()
->withErrors($validation)
->with('message', 'There were validation errors.');
}
This has save functions and other functions inside it too.
GalleryImage.php gallery image model to use in the post controller
<?php
class GalleryImage extends Eloquent {
protected $guarded = array();
public static $rules = array();
public function __construct(array $attributes = array()) {
$this->hasAttachedFile('photo', [
'styles' => [
'thumbnail' => '300x300#'
]
]);
parent::__construct($attributes);
}
// A gallery image belongs to a post.
public function post(){
return $this->belongsTo('Post');
}
}
My create.blade.php template to post the post itself
#extends('layouts.scaffold')
#section('main')
<h1>Create Post</h1>
{{ Form::open(array('route' => 'posts.store', 'files' => true)) }}
<ul>
<li>
{{ Form::label('title', 'Title:') }}
{{ Form::text('title') }}
</li>
<li>
{{ Form::label('body', 'Body:') }}
{{ Form::textarea('body') }}
</li>
<li>
{{ Form::file('picture') }}
</li>
<li>
{{ Form::file( 'photo[]', ['multiple' => true] ) }}
</li>
<li>
{{ Form::submit('Submit', array('class' => 'btn btn-info')) }}
</ul>
{{ Form::close() }}
#if ($errors->any())
<ul>
{{ implode('', $errors->all('<li class="error">:message</li>')) }}
</ul>
#endif
#stop
When I post the form with a single images attached its fine and saves to the db and it works a treat but when I save it with multiple image uploads I get this error:
ErrorException
preg_replace(): Parameter mismatch, pattern is a string while replacement is an array
The full stack trace is here in my gist of the files
Can anyone point out to me why this error happens. From my research its creating a multidimensional array that needs flattening I think but I am unsure if this is true.
I have been banging my head against a brick wall with this for ages.
Problem is when your submitting multiple images it becomes an array of pictures instead of a single string. So its trying to save an array to the database instead of a string which its expecting. If you make it so your photo variable is a json_encoded array of pictures then you should be able to save them.
Hope this helps.
I'm trying to learn to an process image form that uploads images to a database and lets users view the image on the website, this is done using Laravel 4. I must have some sort of bug, because the view doesn't have any errors, but when I select an image to upload and hit the "save" button on my form, nothing happens other than it looks like the form has been refreshed because the file is gone.
Routes
// This is for the get event of the index page
Route::get('/', array(
'as' => 'index_page',
'uses' => 'ImageController#getIndex'
));
// This is for the post event of the index page
Route::post('/', array(
'as' => 'index_page_post',
'before' => 'csrf',
'uses' => 'ImageController#postIndex'
));
ImageController.php
class ImageController extends BaseController {
public function getIndex()
{
// Let's first load the form view
return View::make('tpl.index');
}
public function postIndex()
{
// Let's validate the form first with the rules which are set at the model
$input = Input::all();
$rules = Photo::$upload_rules;
$validation = Validator::make($input, $rules);
// If the validation fails, we redirect the user to the index page, with errors
if ($validation->passes()) {
// If the validation passes, we upload the image to the database and process it
$image = Input::file('image');
// This is the original uploaded client name of the image
$filename = $image->getClientOriginalName();
// Because Symfony API does not provide filename
// without extension, we will be using raw PHP here
$filename = pathinfo($filename, PATHINFO_FILENAME);
// We should salt and make an url-friendly version of the file
$fullname = Str::slug(Str::random(8) . $filename) . '.' .
$image->getClientOriginalExtension();
// We upload the image first to the upload folder, then
// get make a thumbnail from the uploaded image
$upload = $image->move
(Config::get('image.upload_folder'), $fullname);
Image::make(Config::get('image.thumb_folder').'/'.$fullname)
->resize(Config::get('image.thumb_width'), null, true)
->save(Config::get('image.thumb_folder').'/'.$fullname);
// If the file is now uploaded we show a success message
// otherwise, we show an error
if ($upload) {
// image is now uploaded, we first need to add column to the database
$insert_id = DB::table('photos')->insertGetId(
array(
'title' => Input::get('title'),
'image' => $fullname
)
);
// Now we redirect to the image's permalink
return Redirect::to(URL::to('snatch/'.$insert_id))
->with('success', 'Your image is uploaded successfully!');
}
else {
// Image cannot be uploaded
return Redirect::to('/')->withInput()
->with('error', 'Sorry, the image could not be uploaded.');
}
}
else {
return Redirect::to('/')
->withInput()
->withErrors($validation);
}
}
Image Model
class Photo extends Eloquent {
// the variable that sets the table name
protected $table = 'photos';
// the variable that sets the table name
protected $fillable = array('title', 'image');
// the timestamps enabled
public $timestamps = true;
// Rules of the image upload form
public static $upload_rules = array(
'title' => 'required|min:3',
'image' => 'required|image'
);
}
The view for the form
#extends('frontend_master')
#section('content')
{{ Form::open(array('url' => '/', 'files' => true )) }}
{{ Form::text('title', '', array(
'placeholder' => 'Please insert your title here')) }}
{{ Form::file('image') }}
{{ Form::submit('save', array('name' => 'send')) }}
{{ Form::close() }}
#stop
Let me know if you can find any bugs, I'm pretty sure something must be going wrong in my ImageController#postIndex
Thanks for any insights
2 things you need to check out.
1st off, once you updated your composer.json to include the Intervention/Image package. you should run composer dump-autoload to refresh the autoload file.
2ndly, there's a logical error in your controller.
Image::make(Config::get('image.thumb_folder').'/'.$fullname)
->resize(Config::get('image.thumb_width'), null, true)
->save(Config::get('image.thumb_folder').'/'.$fullname);
should be
Image::make(Config::get('image.image_folder').'/'.$fullname)
->resize(Config::get('image.thumb_width'), null, true)
->save(Config::get('image.thumb_folder').'/'.$fullname);
because you've already moved the image file to image_folder with the code below:
$upload = $image->move
(Config::get('image.upload_folder'), $fullname);
Hope this helps.