I am new in Laravel.
I am going to upload image in Laravel I use Intervention Image and this is my controller:
public function store()
{
$validator = Validator::make($data = Input::all(), City::$rules);
if ($validator->fails())
{
return Redirect::back()->withErrors($validator)->withInput();
}
$image_temp=Input::file('image');
$name = Input::file('image')->getClientOriginalName();
if(Image::make($image_temp->getRealPath())->save('public/up/city/'.$name)){
$image='public/up/city/'.$name;
}
City::create($data);
return Redirect::route('siteadmin.cities.index');
}
And this is my model:
class City extends \Eloquent {
protected $primaryKey='city_id';
protected $fillable = ['name', 'parent_id', 'english_name','population','phone_prefix','image'];
}
And this is my route:
Route::resource('cities', 'CitiesController');
everything is working well but I don't know how to send an variable as a special field to Mass Assignment.
I need $image variable to save in cities table image field
if(Image::make($image_temp->getRealPath())->save('public/up/city/'.$name)){
$image='public/up/city/'.$name;
}
But image in my database filled with temporary name of uploaded file:
Just override the value in the $data array:
$data['image'] = 'public/up/city/'.$name;
If you do
$image = 'public/up/city/'.$name;
... you store the value in a local variable but nothing happens with it. The value in your DB comes from the "original" $data, the form data. It's the temporary path of the uploaded file. You need to change that in order for Laravel to fill the new value in the DB.
And here the (nearly) full code to avoid any confusion:
$validator = Validator::make($data = Input::all(), City::$rules);
if ($validator->fails())
{
return Redirect::back()->withErrors($validator)->withInput();
}
$image_temp=Input::file('image');
$name = Input::file('image')->getClientOriginalName();
if(Image::make($image_temp->getRealPath())->save('public/up/city/'.$name)){
$data['image'] = 'public/up/city/'.$name;
}
City::create($data);
return Redirect::route('siteadmin.cities.index');
Related
I have a form with two pivot tables. One of them works just fine but I can't seem to be making the second one work despite them being quite similar. The one not working is for an image table called 'photos' and the form upload in called 'releases'. I called the pivot table 'photo_releases' with the 'photo_id' and a 'release_id' field.
DB Pivot Table
here is the release Modal
class Release extends Model
{
public function photos()
{
return $this->belongsToMany('App\Photo', 'photo_releases', 'release_id', 'photo_id');
}
}
and the photo modal
class Photo extends Model
{
public function releases()
{
return $this->belongsToMany('App\Release', 'photo_releases', 'photo_id', 'release_id');
}
}
and the ReleaseController
public function store(ReleasesCreateRequest $request)
{
$input = $request->all();
$user = Auth::user();
if ($file = $request->file('photo_01')) {
$file_name = preg_replace("/[^a-zA-Z0-9.]/", "", $file->getClientOriginalName());
$name = time() . 'photo_01' . $file_name;
$file->move('images', $name);
$input['photo_01'] = $name;
$photo = new Photo();
$photo->url = $input['photo_01'];
$photo->save();
}
$release = Release::create($request->except('release_id'));
dd($request->except('release_id'), $request->get('photo_id', []), $request->get('artiste_id', []));
$release->photos()->attach($request->get('photo_id', []));
$release->artistes()->attach($request->get('artiste_id', []));
return redirect('/admin06000/releases');
}
There is two pivot tables being used in this function. the one using
"$release->artistes()->attach($request->get('artiste_id', []));"
is working correctly but the photos is not. The url is being logged in the correct DB and the image is uploading fine, but the pivot table is not being updated. If anyone could help it would be greatly appriciated.
try This if you need some select in relation ship change
with('photos')
to
with(['photos'=>function($query){$query->where(....)->get();}])...
use Image;
use Illuminate\Support\Facades\Input;
...
public function store(ReleasesCreateRequest $request)
{
$input = $request->all();
$user = Auth::user();
if ($file = $request->file('photo_01'))
{
$image= Input::file('photo_01');
$name = time().'photo_01'.'.'.$image->getClientOriginalExtension();
$path=public_path('/YourPath/'.$name);
Image::make($image->getRealPath())->save($path);
$photo = new Photo();
$photo->url = '/YourPath/'.$name;
$photo->save();
}
$release = Release::create
([
'release_field'=>$amount,
'release_field2'=>$amount2,
....
]);
$release->with('photos')->with(artistes)->get();
}```
I have 2 tables that are in one to one relationship:
tours :
id|title|content
featured_image:
id|tour_id|name|path
My models FeaturedImage.php:
class FeaturedImage extends Model
{
public function tour()
{
return $this->hasOne('App\Tour');
}
}
Tour.php
class Tour extends Model
{
public function featuredimage()
{
return $this->belongsTo('App\FeaturedImage');
}
}
I want to save tour_id in featured_image table when tour is created. I'm using same form to fill tours table and to upload featured_image.
This is my store method looks like:
public function store(Request $request)
{
//validate the date
$this->validate($request, [
'title' => 'required|max:255',
'content' => 'required'
]);
//store the date
$tour = new Tour;
$tour->title = $request->title;
$tour->content = $request->trip_code;
$tour->save();
$featured_image= new FeaturedImage;
// save featured_image
if($request->hasFile('featured_image')){
$image = $request->file('featured_image');
$filename = $image->getClientOriginalName();
$location = public_path('images/featured_image/'.$filename);
Image::make($image)->resize(800, 600)->save($location);
$featured_image->path= $location;
$featured_image->tour()->associate($tour);
$featured_image->save();
}
//redirect to
Session::flash('success','Tour is successfully created !');
return redirect()->route('tours.show',$tour->id);
}
I'm successful to save data into tours table but unable to save in featured_image table. I 'm getting this error:
Call to undefined method Illuminate\Database\Query\Builder::associate()
I would be thankful if anyone can help me out.
You can user Mass Assignment to create your entries into DB like this:
$this->validate(request()->all(), [
'title' => 'required|max:255',
'content' => 'required'
]);
$tour_inputs = array_only(
$tour_inputs.
[
'title',
'content',
]
);
$tour = Tour::create($tour_inputs);
if($request->hasFile('featured_image')) {
$image = $request->file('featured_image');
$filename = $image->getClientOriginalName();
$location = public_path('images/featured_image/'.$filename);
Image::make($image)->resize(800, 600)->save($location);
$featuredImage = $tour->featuredImage()->save(new FeaturedImage([
'name' => $filename,
'path' => $location,
]));
}
Remember to define the $fillables inside your models, your models should look like this,
do check your relations, that you've made in the models, according to me they aren't correct:
class Tour extends Model
{
protected $fillables = [
'title',
'content',
];
public function featuredImage()
{
return $this->hasOne('App\FeaturedImage');
}
}
class FeaturedImage extends Model
{
protected $fillables = [
'name',
'path',
'tour_id',
];
public function tour()
{
return $this->belongsTo('App\Tour');
}
}
Hope this helps!
From your code the relationships that you have defined are in reverse order.
I mean logically, a Tour has one FeaturedImage and a FeaturedImage belongs to a Tour.
class Tour extends Model
{
//Mass Assignable fields for the model.
$fillable = ['title', 'content'];
public function featuredimage()
{
return $this->hasOne('App\FeaturedImage');
}
}
and
class FeaturedImage extends Model
{
//Mass Assignable fields for the model
$fillable = ['tour_id', 'name', 'path'];
public function tour()
{
return $this->belongsTo('App\Tour');
}
}
Then in your controller
public function store(Request $request)
{
//validate the data
$this->validate($request, [
'title' => 'required|max:255',
'content' => 'required'
]);
//store the data
$tour = Tour::firstOrCreate([ //protection against duplicate entry
'title' => $request->get('title'),
'content' => $request->get('trip_code')
]);
if($tour) //if the Tour exists then continue
{
// save featured_image
if($request->hasFile('featured_image')){
$image = $request->file('featured_image');
$filename = $image->getClientOriginalName();
$location = public_path('images/featured_image/'.$filename);
Image::make($image)->resize(800, 600)->save($location);
$featured_image = $tour->featuredimage()->create([
'path' => $location,
'name' => $filename //if you have this field on your FeaturedImage
}
//you could also have an else block to redirect back if the input doesn't have a file
//redirect to
Session::flash('success','Tour is successfully created !');
return redirect()->route('tours.show',$tour->id);
}
else
{
//if there occurs any error display the error message and redirect back - probably with validation errors or exception errors
Session::flash('error','Error message');
return redirect()->back()->withInput()->withErrors();
}
}
And don't forget to add the mass assignable fields to the $fillable array on your models.
UPDATE
For cases where a single form submission includes database transactions in multiple tables, you should use a try{}catch{} to ensure that either all related transactions run without any issue or neither of the transactions go through - to avoid data discrepancy.
You can rewrite your controller code as
public function store(Request $request)
{
//validate the data
$this->validate($request, [
'title' => 'required|max:255',
'content' => 'required'
]);
//store the data
//use the DB::beginTransaction() to manually control the transaction
//You would ideally want to persist the data to the database only if the input provided by the user
//has valid inputs for Tour as well as FeaturedImage, in case if any one invalid input you do not
//want to persist the data
DB::beginTransaction();
try
{
//firstOrCreate gives protection against duplicate entry for tour with same title and content
$tour = Tour::firstOrCreate([
'title' => $request->get('title'),
'content' => $request->get('trip_code')
]);
//proceed further only if $tour exists
if($tour)
{
// get featured_image
if($request->hasFile('featured_image')){
$image = $request->file('featured_image');
$filename = $image->getClientOriginalName();
$location = public_path('images/featured_image/'.$filename);
Image::make($image)->resize(800, 600)->save($location);
//save the featured_image
$featured_image = $tour->featuredimage()->create([
'path' => $location,
'name' => $filename //if you have this field on your FeaturedImage
}
}
}
catch(\ValidationException $e)
{
//In case of validation error, rollback the database transactions to avoid data discrepancy.
DB::rollBack();
$errors = $e->getMessage();
Session::flash('error', 'Whoops.. Please check the provided inputs');
return redirect()->back()->withInput()->withErrors['errors', $errors];
}
catch(\Exception $e)
{
//In case of any other error, rollback the database transactions to avoid data discrepancy.
DB::rollBack();
$errors = $e->getMessage();
Session::flash('error', 'Whoops.. Something went wrong. Please try again');
return redirect()->back()->withInput()->withErrors['errors', $errors];
}
//If both the transactions to the database i.e. saving the Tour as well as FeaturedImage ran without problem
//Commit to the database
DB::commit();
//redirect to
Session::flash('success','Tour is successfully created !');
return redirect()->route('tours.show',$tour->id);
}
Hope this helps.
I am trying to store an uploaded file with a relationship to an Employee model. I am unable to retrieve the employee id after uploading the file to save it to the DB table as a foreign key.
Routes:
Route::resource('employees', 'EmployeesController');
Route::post('documents', 'DocumentsController#createdocument')
So I am on a URL that says http://localhost/public/employees/8 when I hit upload it redirects to http://localhost/public/documents and the file does upload but shows error when writing to DB.
Here is my code. How can I do it?
public function createdocument(Request $request, Employee $id)
{
$file = $request->file('file');
$allowedFileTypes = config('app.allowedFileTypes');
$maxFileSize = config('app.maxFileSize');
$rules = [
'file' => 'required|mimes:'.$allowedFileTypes.'|max:'.$maxFileSize
];
$this->validate($request, $rules);
$time = time(); // Generates a random string of 20 characters
$filename = ($time.'_'.($file->getClientOriginalName())); // Prepend the filename with
$destinationPath = config('app.fileDestinationPath').'/'.$filename;
$uploaded = Storage::put($destinationPath, file_get_contents($file->getRealPath()));
if($uploaded){
$employee = Employee::find($id);
$empdoc = new EmpDocuments();
$empdoc->name = $filename;
$empdoc->employee_id = $employee->id;
$empdoc->save();
}
return redirect('employees');
}
These are my models.
Employee.php
public function EmpDocuments()
{
return $this->hasMany('App\EmpDocuments');
}
public function createdocument(){
return $this->EmpDocuments()->create([
'name' => $filename,
'employee_id' => $id,
]);
}
EmpDocuments.php
public function Employee()
{
return $this->belongsTo('App\Employee');
}
With the above models and controller I am now getting error
General error: 1364 Field 'employee_id' doesn't have a default value (SQL: insert into empdocuments.
How do I capture the employee_id?
Managed to fix it, in case someone has similar problem. Ensure you pass the id with the route action for it to be capture in the next request.
Here is the final controller.
public function update(Request $request, $id)
{
$file = $request->file('file');
$allowedFileTypes = config('app.allowedFileTypes');
$maxFileSize = config('app.maxFileSize');
$rules = [
'file' => 'required|mimes:'.$allowedFileTypes.'|max:'.$maxFileSize
];
$this->validate($request, $rules);
$time = time(); // Generates a random string of 20 characters
$filename = ($time.'_'.($file->getClientOriginalName())); // Prepend the filename with
$destinationPath = config('app.fileDestinationPath').'/'.$filename;
$uploaded = Storage::put($destinationPath, file_get_contents($file->getRealPath()));
if($uploaded){
$employee = Employee::find($id);
$empdoc = new EmpDocuments();
$empdoc->name = $filename;
$employee->empdocuments()->save($empdoc);
return redirect('employees/' . $id . '#documents')->with('message','Document has been uploaded');
}
}
Do you have a relationship between Employee and EmpDocuments ??
If I am understanding well EmpDocuments belongsTO Employees right??
I'm trying to help but I need to understand, one employee can have many documents right?? but each document belongs to just one employee right??
If is like that you should make a relationship in your employee model,
` public function employeeDocuments(){
return $this->hasMany(EmpDocuments::class);
}`
Then in the same model
`public function createEmployeeDocuments(){
return $this->employeeDocuments()->create([
'your_db_fields' =>your file,
'your_db_fields' => your other some data,
]);
}`
The id will be inserted automatically
I hope I helped you!!
https://laravel.com/docs/5.3/eloquent-relationships
Are your fillable empty???
To use the Eloquent create method you need to set you fillable array to mass assignment. Try this, if is still not working tell me and I will try to do my best.
protected $fillable = [ 'employee_id', 'Your_db_field', 'Your_db_field', 'per_page', 'Your_db_field', 'Your_db_field' ];
I am trying to save my uploaded file with a new name, so I must update the file attribute again to give it the new name to avoid the mismatching between the file name in the db and the name of the real file in my directory.
But the file attribute type is file, so I'll get an error saying please upload a file every time I do this process, here is my create action code:
if(isset($_POST['Customers'])) {
$model->attributes=$_POST['Customers'];
$model->image = UploadedFile::getInstance($model, 'image');
if($model->save()){
$model->image->saveAs(getcwd()."/images/customers/CUST-".$model->id."-".$model->image);
$model->image = "CUST-".$model->id."-".$model->image;
if($model->save())
return $this->redirect(['view', 'id' => $model->id]);
}
}
Here's your solution: you need two different fields.
One field is to store the name of the file. This field will be saved into the database. This field should not be set in your rules at all, because you'll never be getting it from forms.
Another field is to receive the actual file upload. This field needs to exist in your rules as type file and also be declared in your model class as a property.
Let's assume that your customer table already has a column named image.
class Customer extends ActiveRecord
{
public $imageFile;
//...
public function rules()
{
return [
//...
[['imageFile'], 'file'],
[['imageFile'], 'required'],
//...
];
}
//...
}
Now, in your controller:
if (Yii::$app->request->isPost) {
$model->load(Yii::$app->request->post());
$model->imageFile = UploadedFile::getInstance($model, 'imageFile');
if ($model->save()) {
$model->refresh();
//set image name
$model->image = "CUST-".$model->id."-".$model->imageFile->name;
//save file
$model->imageFile->saveAs(getcwd()."/images/customers/".$model->image);
//update model with file name
$model->save();
}
}
return $this->redirect(['view', 'id' => $model->id]);
It would also be a good idea to use aliases to get your upload folder. Something like Yii::getAlias("#uploads/{$model->image}").
Saving A model after Image SaveAs call .. Should Be Like
if(isset($_POST['Customers'])) {
$model->attributes=$_POST['Customers'];
$model->image = UploadedFile::getInstance($model, 'image');
if($model->validate()){
$model->image->saveAs(getcwd()."/images/customers/CUST-".$model->id."-".$model->image);
$model->image = "CUST-".$model->id."-".$model->image;
if($model->save())
return $this->redirect(['view', 'id' => $model->id]);
}
}
I use Laravel 4 and my store function in controller is :
public function store()
{
$validation = new Services\Validators\Speaker;
if($validation->passes())
{
$file = Input::file('image');
$imageName = time().'_'.$file->getClientOriginalName();
$file->move('photos/',$imageName);
$input = Input::all();
$speaker = $this->speaker->create(Input::all());
return Redirect::route('speaker.index');
}
The uploaded photo is moved to the specified place and named correctly. But in the database, the image file name is not correctly saved. "C:\xampp\tmp\php2B7D.tmp" this kind of data is saved. I want to save image name and path. Any ideas. Thanks in advance.
I found solution. here the code
public function store()
{
$validation = new Services\Validators\Speaker;
if($validation->passes())
{
$file = Input::file('image');
$imageName = time().'_'.$file->getClientOriginalName();
$file->move('photos/',$imageName);
$input = array('name'=>Input::get('name'),
'image'=> 'photos/'.$imageName,
'desc'=>Input::get('desc')
);
$speaker = $this->speaker->create($input);
return Redirect::route('speaker.index');
}