how to retrieve image and imagess data using one to many relationship - php

i'm working on a E-commerce like project where users can upload multiple images of a particular product, i have a one-to-many relation where many images has one description and price. so on the homepage i need to call a single image out of the total uploaded and also fetch the descrition of the image, so when view button is clicked the user can see the rest of the image sliding.
upload Controller
public function store(Request $request)
{
$request->validate([
'farm_name'=> 'required',
'farmer_name'=>'required',
'min_order'=>'required',
'qty'=>'required',
'product_package'=>'required',
'descr'=>'required',
'images' => 'required',
'images.*' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
//'' => 'image|mimes:jpeg,png,jpg,gif,svg|max:6048',
]);
$input = new Product;
$input->farm_name = $request->farm_name;
//$input->user_id = Auth::user()->id;
$input->farmer_name = $request->farmer_name;
$input->tel = Auth::user()->tel;
$input->farm_adrs = Auth::user()->adrs;
$input->state = Auth::user()->state;
$input->email = $request->email;
$input->qty = $request->qty;
$input->descr = $request->descr;
$input->product_package = $request->product_package;
$input->catr = $request->catr;
$input->lga = $request->product_name;
$input->amount = $request->amount;
//$input->img = $request->images;
//dd($input);
$input->save();
foreach($request->file('images') as $imageFile){
$image = new Image;
$imageName = time().rand(1,99).'.'.$imageFile->extension();
$imageFile->move(public_path('images'), $imageName);
$image->images_id = $input->id;
$image->name = $imageName;
$image->save();
}
return back()
->with('success','Your Product is succesfully Uploaded.');
}
//show image this where i have problem
public function index(){
$products = Product::all();
foreach($products as $product){
$product_id = $product->id;
$images = Image::find($product_id);
}
return view('app.index', compact('products', 'images'));
}

First of all u re saving product id as image_id on image table. Is this your correct column? if you are using image_id to save related product id, then change the index code to
public function index(){
$images=[];
$products = Product::all();
foreach($products as $product){
$product_id = $product->id;
$images[$product_id] = Image::where('image_id',$product_id)->get();
}
return view('app.index', compact('products', 'images'));
}
it will give you all the images from all product set upped with index of product id.
in a better way you can directly join the table. it will reduce the no. of executing query.

Related

how to add new category in post page laravel

when i want to make a post i have to first create a category on a different page, namely the category page, not the post page. how to make it like wordpress which can add categories and tags on the post page.
i have tried but i don't know how to make validation so that the category name and category slug (Str::slug) are unique.
after I tried to successfully add a category on the post page but when I added an existing category it still worked, not unique.
PostController.php
public function store(Request $request)
{
$this->validate($request,[
'name' => 'required',
'categories' => 'required',
]);
$slug = Str::slug($request->name);
$post = new Post();
$post->user_id = Auth::id();
$post->name = $request->name;
$post->slug = $slug;
$post->save();
// get old categories name
$existingCategory = $video->categories->pluck('name')->toArray();
// find new categories
foreach($request->categories as $category) {
if(! ( in_array($category, $existingCategory) ) ) {
//create a new category
$newCategory = new Category();
$newCategory->name = $category;
$newCategory->slug = Str::slug($category);
$newCategory->save();
}
}
$attachableCategory = [];
foreach($request->categories as $category) {
$attachableCategory[] = Category::where('name', $category)->pluck('id')->first();
}
$video->categories()->sync($attachableCategory);
return redirect()->route('admin.post.index');
}
It seem that your categories are an array. I they are. Problably your are looking for array validation
Validator::make($input, [
// validates there is an array
'categories' => 'required|array|min:1',
// validates values inside array
'categories.*' => 'required|string|min:4'
]);

How can I save a new column data into laravel pivot table?

I have this 3 table:
stations (id,station_name)
products (id,product_name)
pivot table
product_station (station_id,product_id, tank_volum)
Station Model
public function products(){
return $this->belongsToMany(Product::class)
->withTimestamps()
->withPivot('tank_volume');
}
Product Model
public function stations(){
return $this->belongsToMany(Station::class);
}
I'm trying to create a station with many products and every product
have it's tank volume but i can't save the tank volume value to
database:
product_station table
this is my controller:
public function store(StationsRequest $request)
{
// dd($request);
$input = $request->all();
if($file = $request->file('photo_id')) {
$name = time() . $file->getClientOriginalName();
$file->move('images', $name);
$photo = Photo::create(['file'=>$name]);
$input['photo_id'] = $photo->id;
}
$station = Station::create($input);
$station->products()->sync($request->products , false);
return redirect('/admin/stations');
}
Q: How can i Save Tank volume inside product_station table "pivot table" ?
if you want to sync() related extra fields :
$product_ids = [];
foreach ($station->products as $product) {
//collect all inserted record IDs
$product_ids[$product->id] = ['tank_volume' => 'tank_volume_value'];
}
//if you want to pass new id from new query
//$product_ids['new_created_product->id'] = ['tank_volume' => 'tank_volume_value'];
then
$station->products()->sync($product_ids);
in this case, better use attach() :
$station = Station::create(['fields']);
$station->products()->attach([$product->id => ['tank_volume'=>'value']]);

how to fetch the old image in edit form in laravel ?what would be the code?

//Here is my edit form (image field)
I have an edit form which has an image field where a user can upload a new image if he wants to.
But if the user does not upload a new photo I want to just use the photo that's already in the database. And not update the image field at all. But in my code whenever I am trying to without uploading new image form is not taking the old input value.
<div class="form-group">
<input type="file" name="image">
</div>
//this is the update function
public function update(Request $request, $id)
{
$this->validate($request,[
'name' => 'required',
'image' => 'mimes:jpeg,bmp,png,jpg'
]);
// get form image
$image = $request->file('image');
$slug = str_slug($request->name);
$category = Category::find($id);
if (isset($image))
{
// make unique name for image
$currentDate = Carbon::now()->toDateString();
$imagename = $slug.'-'.$currentDate.'-'.uniqid().'.'.$image->getClientOriginalExtension();
// check category dir is exists
if (!Storage::disk('public')->exists('category'))
{
Storage::disk('public')->makeDirectory('category');
}
// delete old image
if (Storage::disk('public')->exists('category/'.$category->image))
{
Storage::disk('public')->delete('category/'.$category->image);
}
// resize image for category and upload
$categoryimage = Image::make($image)->resize(1600,479)->stream();
Storage::disk('public')->put('category/'.$imagename,$categoryimage);
// check category slider dir is exists
if (!Storage::disk('public')->exists('category/slider'))
{
Storage::disk('public')->makeDirectory('category/slider');
}
// delete old slider image
if (Storage::disk('public')->exists('category/slider/'.$category->image))
{
Storage::disk('public')->delete('category/slider/'.$category->image);
}
// resize image for category slider and upload
$slider = Image::make($image)->resize(500,333)->stream();
Storage::disk('public')->put('category/slider/'.$imagename,$slider);
} else {
$imagename = $category->image;
}
$category->name = $request->name;
$category->slug = $slug;
$category->image = $imagename;
$category->save();
Toastr::success('Category Successfully Updated :)' ,'Success');
return redirect()->route('admin.category.index');
}
// When i click on the edit button it shows the No file Chosen it is not displaying the old image ..
you should change your validation
in STORE function, you should give an image and upload it (if it is required)
but in UPDATE function maybe the user does'nt want to change image and user only wants to change for exmaple just the name, so user can select no image in update
so your validation in UPDATE must be NULLABLE.
$this->validate($request,[
'name' => 'required',
'image' => 'nullable|mimes:jpeg,bmp,png,jpg'
]);

Pass parent id to relationship factory?

I have a factory of posts and a factory of posts_images, a post can have many images, I did create a seeder for posts that look like this.
$posts = factory(App\Models\Post::class, 100)->create()
->each(function($post) {
$post->images()->saveMany(factory(App\Models\PostsImage::class, 3)->make());
});
I want to create 100 posts and that each post have 3 images, this kind of work, the problem is when the image is created
I want the image to be created from a base_64 string and saved in certain directory but I need the id of the post so I can create the folder where it will be created.
$factory->define(App\Models\PostsImage::class, function (Faker $faker) {
//this does not get me the id
$id = factory(\App\Models\Post::class)->make()->id;
$name = time();
$b64_image = \Config::get('constants.seed_image');
$data = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $b64_image));
if(!file_exists(public_path('images/eventos/'.$id.'/'))) {
mkdir(public_path('images/noticias/'.$id.'/'));
}
file_put_contents(public_path('images/noticias/'.$id.'/'.$name.'.jpg'), $data);
return [
//
'image' => $name,
'order' => $id + 1
];
});
The only line that seems not to be working is
$id = factory(\App\Models\Post::class)->make()->id;
I did try using create instead of make, but this create more rows in the post table, and I don't want that.
Is there a way to pass the post id to the images factory?
The best option will be to create the directory in the posts seeder, since you have the access to the $post object when a Post is created. Try something like this:
$posts = factory(App\Models\Post::class, 100)->create()
->each(function($post) {
//id is available on the $post object created
$id = $post->id;
$name = time();
$b64_image = \Config::get('constants.seed_image');
$data = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $b64_image));
if(!file_exists(public_path('images/eventos/'.$id.'/'))) {
mkdir(public_path('images/noticias/'.$id.'/'));
}
file_put_contents(public_path('images/noticias/'.$id.'/'.$name.'.jpg'), $data);
$post->images()->saveMany(factory(App\Models\PostsImage::class, 3)->make());
});
What I do usually in this situation is to get the last record of the created parent object.
$factory->define(App\Models\PostsImage::class, function (Faker $faker) {
// get last record of Post
$id = \App\Models\Post::orderBy('id', 'desc')->first()->id;
$name = time();
$b64_image = \Config::get('constants.seed_image');
$data = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $b64_image));
if(!file_exists(public_path('images/eventos/'.$id.'/'))) {
mkdir(public_path('images/noticias/'.$id.'/'));
}
file_put_contents(public_path('images/noticias/'.$id.'/'.$name.'.jpg'), $data);
return [
//
'image' => $name,
'order' => $id + 1
];
});

groupBy only gets the first id

I have a many to many relationship between departments and users my pivot table is department_user. I wanted to select all the department_name depending of the user's department using groupBy method to merge all the department_name into one. See below my statement.
$departmentRecipient = DB::table('users')->select('departments.department_name', 'users.id')
->join('department_user', 'users.id', '=', 'department_user.user_id')
->join('departments', 'department_user.department_id', '=', 'departments.id')
->groupBy('departments.department_name')
->get();
Result using die and dump.
As you can see here I have an id of 4 under "Department of Engineering". My main problem is it doesn't fetch all the id under "Department of Engineering". But in my SQL I have id of 5 not only 4. How can I solve this problem? Any help would greatly appreciated. Please see result below.
Output:
This is the output of my list. I wanted to get all the users id belongs to the specific option for the user. But if I choose "Department of Engineering" it only gets the id of 4 not 5. I wanted to get 4 and 5 once.
Controlller:
public function getDocuments()
{
$departmentRecipient = DB::table('departments')->get();
return view ('document.create')->with('departmentRecipient', $departmentRecipient);
}
public function postDocuments(Request $request)
{
$this->validate($request,
[
'title' => 'required|regex:/(^[A-Za-z0-9 ]+$)+/|max:255',
'content' => 'required',
'category' => 'required',
'recipient' => 'required',
]);
$document = new Document();
//Request in the form
$document->title = $request->title;
$document->content = $request->content;
$document->category_id = $request->category;
$document->save();
$user = Auth::user();
foreach($request->recipient as $recipientId)
{
$document->sentToUsers()->sync([ $recipientId => ['sender_id' => $user->id]],false );
}
}
Model
User
public function departments()
{
return $this->belongsToMany('App\Models\Department', 'department_user');
}
Department
public function users()
{
return $this->belongsToMany('\App\Models\User', 'department_user');
}
View
<div class = "form-group">
<label for = "recipient" class = "control-label">Recipient:</label>
<select name = "recipient[]" multiple class = "form-control select2-multi" id = "myUserList">
#foreach ($departmentRecipient as $list)
<option value = "{{ $list->id }}">{{ $list->department_name }}</option>
#endforeach
</select>
</div>
From your given code it seems you are not using Eloquent ORM, you are doing it using Query Builder.
If you don't have a performance concern right now you can do it using separate queries. Like-
$departmentRecipient = DB::table('departments')->all();
foreach($departmentRecipient as $department){
$department->users = DB::table('department_user')->where('department_id',$department->id)->pluck('user_id');
}
But the better way is to use the eloquent with relationships. Define the many to many relationship in your eloquent model of Users and Departments (assuming you have eloquent model for them). You will find details about eloquent relationships at laravel documentation.
Update:
From the update of your post it is actually pretty easy to do what you want. If your Request contains the selected department id then you can do the following:
public function postDocuments(Request $request)
{
$document = new Document();
$document->title = $request->title;
$document->content = $request->content;
$document->category_id = $request->category;
$document->save();
//get the users list of the selected department id
$selected_department = $request->department_id; //this must be included in your POST data
$users = DB::table('department_user')->where('department_id',$selected_department)->pluck('user_id');
//now you have the list of the users id
foreach($users as $user){
// do what you need here
}
}
Update 2:
Following controller code might work for you.
Controller:
public function getDocuments()
{
// I am suggesting here to change the '$departmentRecipient' to '$departmentlist', as it is more meaningful. Also in your view
$departmentlist = DB::table('departments')->get();
return view ('document.create')->with('departmentlist', $departmentlist);
}
public function postDocuments(Request $request)
{
//same as you have till the $document->save()
....
....
//then do this
$recipients = array();
$departments = $request->recipient;
foreach($departments as $department){
$users = DB::table('department_user')->where('department_id',$department)->pluck('user_id');
$recipients = array_merge($recipients, $users);
}
//now you have a complete list of the users from selected departments
//Do as you intend to like this
$user = Auth::user();
foreach($recipients as $recipientId)
{
$document->sentToUsers()->sync([ $recipientId => ['sender_id' => $user->id]],false );
}
}

Categories