Laravel Image intervention showing me Call to a member function getClientOriginalName() on a non-object Laravel - laravel

I am using Laravel Image Intervention Package with drop-zone plugin. And for sure I have installed it properly. When I try to upload images and then submit the form its showing me the following error message
"Call to a member function getClientOriginalName() on a non-object"
Even this error message showing me if i blank this input field form. In that case it is expected to me not showing me any error message as it is not mandatory field to submit the form But it did.
I have two query.
1) what's going wrong in my code
2) Right now I am trying to upload single image. For multiple images I want to store the files info as an array. In that case what would my code in controller.
Here is my live link you can check from here
http://thetoppinghouse.com/laravel/public/admin/index/create
http://laravel.io/bin/Jxmzo
Here is my controller code
public function store()
{
$validator = Validator::make($data = Input::all(), Index::$rules);
if ($validator->fails())
{
return Redirect::back()->withErrors($validator)->withInput();
}
if ($validator->passes()) {
$index = new Index;
$index->name = Input::get('name');
$index->category_ID = Input::get('category_ID');
$files = Input::file('files');
$filename = date('Y-m-d-H:i:s')."-".$files->getClientOriginalName();
$path = public_path('img/index/' . $filename);
Image::make($files->getRealPath())->save($path);
$index->files = 'img/index/'.$filename;
$index->save();
return Redirect::route('admin.index.index')->with('message', 'Index Created');
}
}
// Form Code
<ul class="post-list">
<li>
{{ Form::label('parent_ID', 'Category') }}
{{ Form::select('parent_ID',Category::lists('category_name','id'),Input::old('category'),array('class' => 'form-control input-sm', 'id' => 'parent_ID')) }}
</li>
<li>
{{ Form::label('name', 'Index Name') }}
{{ Form::text('name', null, array( 'class' => 'form-control input-sm', 'placeholder' => 'Name' )) }}
{{ $errors->first('name', '<p class="error">:message</p>' ) }}
</li>
<li>
{{ Form::label('image', 'Cover Image') }}
</li>
<div class="dropzone" id="DropzoneArea">
<div class="fallback">
<input name="files" type="file" id="files" multiple>
</div>
</div>
{{ Form::submit('Save') }}
</li>
</ul

handle the file upload with dropzone like,
var fileDropzone = new Dropzone("div#DropzoneArea", {
url: '/upload', // customize the URL
addRemoveLinks: false
});
then when u uploading something upload action will call and u can handle the file upload in that action. then you can return the server file path of uploaded file.
fileDropzone.on("success", function (file,data,e) {
var hiddenInput = $('<input name="filePath" type="hidden value=" '+ data.path +' "">');
// and append the hiddenInput in to the form
});
then after success upload you can set the server path of the uploaded file in a input hidden field. after you submit the form you can get the file by hidden field value.
when you submit the form, get uploaded file as,
$filePath = Input::input('filePath');
$file = File::get($filePath);

Related

How do I get my variable to show in my store function

This is probably a very simple thing, but for some reason I just can't figure it out. I created a function that gets the images from my vue component.
What I'm trying to do is take the images from my postImage() and have them in my store() function, so that I can save everything into the database.
The problem I'm getting is when I do that I get this error
Too few arguments to function App\Http\Controllers\Admin\CategoryController::store(), 1 passed and exactly 2 expected
I do understand that the error is telling me that only the $request was sent and not the $image. I'm not sure how to get it working. If I've left anything out please let me know
Here is my controller
public function store(Request $request, $image)
{
$category = new Category();
$input = $this->safeInput($request);
$category->fill($input);
dd($image);
$slug = $category->slug($category->title);
$category->slug = $slug;
if($request->has('active'))
{
$category->active = 1;
}else{
$category->active = 0;
}
$category_order = $category->order_number();
$category->order = $category_order;
$category->save();
}
public function postImage(Request $request)
{
if($request->hasFile('image'))
{
$names = [];
foreach($request->file('image') as $image)
{
$destinationPath = 'product_images/category/';
$filename = $image->getClientOriginalName();
$image->move($destinationPath, $filename);
array_push($names, $filename);
}
$image = json_encode($names);
return $image;
}
}
This is my vue component
<template>
<div class="container">
<div class="uploader"
#dragenter="OnDragEnter"
#dragleave="OnDragLeave"
#dragover.prevent
#drop="onDrop"
>
<div v-show="!images.length" :value="testing()">
<i class="fas fa-cloud-upload-alt"></i>
<div>OR</div>
<div class="file-input">
<label for="file">Select a file</label>
<input type="file" id="file" #change="onInputChange" multiple>
</div>
</div>
<div class="images-preview" v-show="images.length">
<div class="img-wrapper" v-for="(image, index) in images">
<img :src="image" :alt="`Image Uplaoder ${index}`">
<div class="details">
<span class="name" v-text="files[index].name"></span>
<span class="size" v-text="getFileSize(files[index].size)"></span>
</div>
<div class="btn btn-danger" #click="funDeleteFile(index)">
Remove
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
mounted() {
console.log('Component mounted.')
},
data() {
return {
isDragging: false,
//Sets the dragCount to 0
dragCount: 0,
//Makes files an array, so that we can send the files to the server
files: [],
//Makes images an array, so that we can let the user see the images
images: [],
}
},
methods: {
testing() {
console.log('This is submit images - '+this.files);
var formData = new FormData();
this.files.forEach(file => {
formData.append('image[]', file, file.name);
});
axios.post('/admin/category/post-image', formData);
},
OnDragEnter(e) {
//Prevents the default action of the browser
e.preventDefault();
// This lets the dragCount become 1, so that the image uploader changes colour
this.dragCount++;
// Changes the isDragging variable to true instead of false
this.isDragging = true;
return false;
},
OnDragLeave(e) {
//Prevents the default action of the browser
e.preventDefault();
// This lets the dragcount become 0, so that the image uploader changes to it's original colour
this.dragCount--;
// This is if the dragCount is <= 0 then the isDragging variable is false
if (this.dragCount <= 0)
this.isDragging = false;
},
onInputChange(e) {
// Grabs the files from the event
const files = e.target.files;
// Creates an array for files, so that we can loop thru it
// Send the file to the addImage method via "this.addImage(file)"
Array.from(files).forEach(file => this.addImage(file));
},
onDrop(e) {
//Prevents the default action of the browser
e.preventDefault();
//Stops the propagation into the other elements inside the one we drop and file into
e.stopPropagation();
// This is to disable the dragging of the images
this.isDragging = false;
// Grabs the files from the event
const files = e.dataTransfer.files;
// Creates an array for files, so that we can loop thru it
// Send the file to the addImage method via "this.addImage(file)"
Array.from(files).forEach(file => this.addImage(file));
},
addImage(file) {
//Checks if the file type is an image
if (!file.type.match('image.*')) {
this.$toastr.e(`${file.name} is not an image`);
return;
}
this.files.push(file);
const img = new Image(),
reader = new FileReader();
reader.onload = (e) => this.images.push(e.target.result);
reader.readAsDataURL(file);
},
}
}
</script>
my create.blade.php
#extends('layouts.admin')
#section('content')
#component('admin.components.products.category-form', [
'formUrl' => route('category.store'),
'formMethod' => 'POST',
'model' => $category,
'category_id' => $category_id,
'image' => '',
'image2' => ''
])
#endcomponent
#endsection
and my form
{{ Form::model($model, array('url' => $formUrl, 'method' => $formMethod, 'class' => 'add-form', 'files' => true)) }}
<div class="form-group">
{{ Form::label('category_id', 'Parent Category') }}
{{ Form::select('category_id', $category_id->prepend('Please Select', '0'), null, array('class' => 'form-control')) }}
</div>
<div class="form-group">
{{ Form::label('title', 'Title') }}
{{ Form::text('title', null, array('class' => 'form-control')) }}
</div>
<div class="form-group">
<label>Active:</label>
{{ Form::checkbox('active', 0) }}
</div>
<div id="app" class="mb-20">
<category-image></category-image>
</div>
<div class="form-group">
{{ Form::submit('Save', array('class' => "btn btn-dark btn-lg btn-block")) }}
</div>
{{ Form::close() }}
My routes
Route::resource('admin/category', 'Admin\CategoryController');
Route::post('admin/category/post-image', 'Admin\CategoryController#postImage')->name('admin.category.post-image');
UPDATE
I've tried this to pass the image to a hidden field in my form so that I can grab it in the $request in my store function.
In my CategoryController#create
$category = new Category();
$category_list = Category::with('parentCategory')->get();
$category_id = Category::pluck('title', 'id');
// I've added this.
$image = '';
return view('admin.products.category.create', compact('category', 'category_list', 'category_id', 'image'));
in my CategoryController#postImage
//I've added this to, so that I can pass the image variable to the create.blade.php
return redirect()->route('category.create', compact('image'));
then in my create.blade.php I added
'my_image' => $my_image
and in my category-form.blade.php component I added
<div id="app" class="mb-20">
<category-image></category-image>
<input type="hidden" name="image" id="image" value="{{ $my_image }}">
</div>
at the moment I haven't been able to do that either. Though I'm not sure if this is the right way to go, I'm a bit worried that some random person can then add whatever they want by using the hidden input
For what do you have the parameter $image? This is not specified in your axios.post.
public function store(Request $request)
{
$category = new Category();
$input = $this->safeInput($request);
$category->fill($input);
dd($this->postImage($request));
$slug = $category->slug($category->title);
$category->slug = $slug;
if($request->has('active'))
{
$category->active = 1;
}else{
$category->active = 0;
}
$category_order = $category->order_number();
$category->order = $category_order;
$category->save();
}
public function postImage($request)
{
if($request->hasFile('image'))
{
$names = [];
foreach($request->file('image') as $image)
{
$destinationPath = 'product_images/category/';
$filename = $image->getClientOriginalName();
$image->move($destinationPath, $filename);
array_push($names, $filename);
}
$image = json_encode($names);
return $image;
}
}
If the $request is available there, Then there is no need to pass extra $image variable.
have you tried
dd($request)
or
print_r($request->toArray()); exit;
for see what's in your request!
In your create.blade you use 'formUrl' => route('category.store'), this route calls the "store" method, right? If so, it also needs to pass the $image parameter. It would be easier to identify the problem if we could se your web routes file too.
If route('category.store') does call the store method you have a few options.
1 - If you don't really need the $image parameter for the store method, you could just remove it.
2 - If you need it in a few cases, just make the parameter optional and check if it's received before handling it. Example: store(Request $request, $image = null)
3 - If this parameter actually is required, you will have to pass it everytime, even when calling routes. Example: route('category.store', ['image' => $something]). Looking at your code at this moment in create.blade you don't have the content to pass though, so I don't think this is an option.
The problem isn't the image missing in the request object sent through the form, it is the second parameter required by the category.store method.
Even if you now send the image in the form with a hidden field, you would still need to pass it as a parameter everytime you call the category.store.
Your store method is defined like
store(Request $request, $image)
So, when you call this method, even if you're just getting the route URL with route('category.store'), you do need to send the image parameter in this call.
Example:
route('category.store', ['image' => 'image id here']);
The same goes for the route definition in your web routes file. You're using a resource route, but laravel don't expect a second parameter for the store method in a default resource, so you will need to change that.
/*
adds exception to the resource so it will not handle the store method
*/
Route::resource('admin/category', 'Admin\CategoryController')->except(['store']);
//adds a custom route that supports the $image parameter.
Route::post('admin/category/{image}', 'Admin\CategoryController#store')
Now, if you're planning to send the image through the request object, you don't need it as a second parameter, so the only thing you will need to change is to make your category.store method like that.
public function store(Request $request)

Add parameter to submit form laravel

here you can see my form where I put in a username and have a hidden idgroup field.
{!! Form::open(array('route'=>'create.invitation')) !!}
<div class="form-group">
{{Form::label('username', 'Username')}}
{{Form::text('username', '', ['class' => 'form-control', 'placeholder' => 'Enter Username'])}}
<input type="hidden" name="idgroup" value="{{$group}}"/>
{{ csrf_field() }}
</div>
<div>
{{Form::submit('Submit',['class' => 'btn btn-primary'])}}
<a class="btn btn-default btn-close" href="{{ route('home') }}">Cancel</a>
</div>
{!! Form::close() !!}
After that this route leads me to my controller function
Route::post('invitation/show', 'InvitationController#create')->name('create.invitation');
How can I add the username and the idgroup to my url?
My problem is now when I click submit I get back this url http://127.0.0.1:8000/invitation/create and when I click enter to the url line I get an error no message because no parameter will pass to the function.
Add. Here is the function
public function create(Request $request)
{
$request->validate([
'username' => [
'required', 'alpha_num', new ExistingUser, new UserNotAdmin
]
]);
$username = $request->username;
$iduser = User::where('name', $username)->select('id')->first();
$group = $request->idgroup;
return view('invitation.overview')->with('group', $group)->with('iduser', $iduser);
}
You cannot pass parameter inside POST body without submitting a form.
But you can try to allow both GET or POST by using any() for the route, so you can test the page around.
Route::any('invitation/show', 'InvitationController#create')->name('create.invitation');
And then, you can try pass variable through queries inside URL
http://127.0.0.1:8000/invitation/create?username=something&idgroup=1

How to pass array to flash message?

I want to send array of additional_feature that they are exist to flash message. Now i only send one additional_feature. Any suggestion how can i do that?
if(!empty($additional_features)){
foreach($additional_features as $additional_feature){
$data = [
'name' => $additional_feature,
];
if (!Feature::where('name', '=', $additional_feature)->exists()) {
$additional = Feature::firstOrCreate($data);
$additional_ids[] = $additional->id;
}
else{
return redirect()->back()->withFlashMessage($additional_feature . ' exists!');
}
}
}
You can use session() instead of with():
session->flash('someVar', $someArray);
Another thing you could try is to seriallize array and pass it as string. Then unserilize it and use.
Also, you could save an array using simple session:
session(['someVar' => $someArray]);
Then get it and delete manually:
session('somevar');
session()->forget('someVar');
We had the same problem and forked the package. you can find it here:
Forked at first from Laracasts/Flash to use multiple message
#if (Session::has('flash_notification.message'))
#if (Session::has('flash_notification.overlay'))
#include('flash::modal', ['modalClass' => 'flash-modal', 'title' => Session::get('flash_notification.title'), 'body' => Session::get('flash_notification.message')])
#else
<div class="alert alert-{{ Session::get('flash_notification.level') }}">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
{!! Session::get('flash_notification.message') !!}
</div>
#endif
#endif
And the content of the include flash::modal
#if (Session::has('flash_notification.messages'))
#foreach (Session::get('flash_notification.messages') as $flashMessage)
#foreach($flashMessage as $type => $message)
<script>
$(function() {
var message = ('{{ $message }}<br>').replace(/'/g, "’");
customFlashMessage({
type: "{{ $type }}",
message: message
});
});
</script>
#endforeach
#endforeach
#endif
return redirect()->back()->with(['session1' => $value, 'session2' => $value]);
In the blade template:
{{ Session::get('session1') }}
{{ Session::get('session2') }}

Submit form, add input to URL

I have a regular form with a single input:
{{ Form::open(array('id' => 'form_search')) }}
<div class="form-group">
{{ Form::text('search', '', array('class' => 'form-control', 'placeholder' => 'Search...')) }}
</div>
{{ Form::close() }}
When the form is submitted, I want it to redirect to a page showing the results by the following URL:
http://www.website.com/search/<QUERY_HERE>
For example, if someone typed john in the form input and submitted the form, the URL redirected to would look like:
http://www.website.com/search/john
How can I do this?
In your routes.php
//Handle form submit
Route::get('search', 'YourSearchController#yourSearchFunction');
//Return results
Route::get('search/{search}', 'YourSearchController#yourSearchResults');
Then add the route to your form:
{{Form::open(['route' => 'search'])}}
Then in yourSearchController:
function yourSearchFunction() {
$search = Input::only(['search']);
return Redirect::to('search/'.$search);
}
Then also in yourSearchController:
function yourSearchResults($search) {
return View::make('results')->with(compact('search'));
}

Laravel 4: Submitting <option> Value To Controller

I have a form which is generated in a controller before being passed to the view:
public function displayUsers(){
$html = "";
//get all users
$users = $this->entityManager->getRepository('User')->findBy(array(), array('last_name'=>'ASC'));
if($users){
$html .= '<h3>Permissions By User</h3>';
$html .= '<select class="form-control" id="permissions-username">';
foreach($users as $user){
$html .= '<option value="'.$user->getId().'">'.$user->getLastName().', '.$user->getFirstName().'</option>';
}
$html .= '</select>';
}
return View::make('admin')->with('output', $html);
}
Then in the 'admin' view, I have the following to display the form:
{{ Form::open(array('route'=>'permissions.edit', 'method' => 'GET')) }}
<div class="form-group">
#if($output)
{{ $output }}
#endif
</div>
{{ Form::submit('Edit User', ['class'=>'btn btn-warning btn-sm', 'name' => 'edit_user', 'title'=>'Edit User']) }}
{{ Form::close() }}
When I submit this form to the controller, the value of the selected option is not carried over. The output of the permissions.edit function ends up as:
{"edit_user":"Edit User"}
With a generated URL of:
*(BASE)*/permissions/%7Bpermissions%7D/edit?edit_user=Edit+User
If I create a form on the view using blade templating, this problem is resolved. However, I do not want to have all the logic of the form on my view.
It's because your select has no name, which is right now as geven below:
<select class="form-control" id="permissions-username">
Assign a name to it, for example, something like this:
<select name="permissions_username" class="form-control" id="permissions-username">
Every form element must have a name otherwise you can't access them on server side. So, now you are able to access that element on the server (in your script) using something like this (In case of Laravel):
$permissions_username = Input::get('permissions_username');
Otherwise (Using Vanilla PHP) you may use:
$permissions_username = $_GET['permissions_username'];
Because you've used GET method in the form. So, whatever you use, you need to assign a name to your form's element, it's necessary (Even with or without Laravel).

Resources