Deleting an Item from array of a table column in Laravel - ajax

There is a Posts table that has a column named images. in images I store data as JSON array as:
["p1.jpg", "p2.jpg","p4.jpg","p9.jpg","p11.jpg", "p12.jpg","p13.jpg", "p14.jpg"];
I want to delete one of these images by ajax. I send the id and image by ajax and get that id and image in the controller correctly:
public function remove() {
$imgs = Image::where('id', request()->id)->pluck('images');
return $imgs;
}
reults in console:
[Array(8)]
0: (8) ["p1.jpg", "p2.jpg", "p4.jpg", "p9.jpg", "p11.jpg", "p12.jpg", "p13.jpg", "p14.jpg"]
length: 1
__proto__: Array(0)
also, I get the image name by request()->img from ajax.
$image = request()->img; => p12.jpg
How I can delete the $image from $images array?

First You may cast images attr to array in your Image model
//App\Image
protected $casts = [
'images' => 'array'
];
Then in your remove function :
public function remove() {
if(request()->id && request()->img) {
$imgModel = Image::findOrFail(request()->id);
$imgs = $imgModel->images;
// find request()->img position inside imgs array
$position = array_search(request()->img, $imgs);
// delete request()->img
unset($imgs[$position]);
$imgModel->images = array_values($imgs);
$imgModel->save();
}
}

Related

Laravel Backpack Image Upload Issue

I m trying to upload images in Laravel Backpack. I had added field in my Controller:
$this->crud->addfield([
'label' => "Logo",
'name' => "logo",
'type' => 'image',
'upload'=> true,
'crop' => true, // set to true to allow cropping, false to disable
'aspect_ratio' => 1, // ommit or set to 0 to allow any aspect ratio
//'disk' => 'public', // in case you need to show images from a different disk
'prefix' => 'uploads/college/' // in case your db value is only the file name (no path), you can use this to prepend your path to the image src (in HTML), before it's shown to the user;
]);
Here is my Model:
protected $fillable = ['name','description','logo','location','establised_at'];
// protected $hidden = [];
// protected $dates = [];
public function setImageAttribute($value)
{
$attribute_name = "logo";
$disk = "public";
$destination_path = "/uploads";
// if the image was erased
if ($value==null) {
// delete the image from disk
\Storage::disk($disk)->delete($this->{$attribute_name});
// set null in the database column
$this->attributes[$attribute_name] = null;
}
// if a base64 was sent, store it in the db
if (starts_with($value, 'data:image'))
{
// 0. Make the image
$image = \Image::make($value)->encode('jpg', 90);
// 1. Generate a filename.
$filename = md5($value.time()).'.jpg';
// 2. Store the image on disk.
\Storage::disk($disk)->put($destination_path.'/'.$filename, $image->stream());
// 3. Save the path to the database
$this->attributes[$attribute_name] = $destination_path.'/'.$filename;
}
}
It's trying to save the base64 data in database but I don't want to do so.
It would be great help if anyone solve it. Thank You!
I've tried the code shown in docs and it works.
I think your problem is the mutator function name. To define a mutator you have to define a method in your model like set{attribute_name}Attribute.
In your case, your mutator function is setImageAttribute then it is looking for an attribute called image.
I think that if you change this code:
public function setImageAttribute($value)
{
with this
public function setLogoAttribute($value)
{
it will work
you miss a step:
like in doc
\Storage::disk($disk)->delete($this->{$attribute_name});
$public_destination_path = Str::replaceFirst('public/', '', $destination_path);
$this->attributes[$attribute_name] = $public_destination_path.'/'.$filename;

Laravel: Trying to push url strings to array in database

I have a field in my AppSetup table called reference_images that is added as follows in the migration: $table->json('reference_images')->nullable(); and casted as an array in the AppSetup model. I have a method that adds image urls to the database. If it's for the reference_image field, I am trying to push it to the array but I keep getting an "Array to String conversion" error in Laravel.
public function addImagesToAppSetup($imageType=null, $image=null)
{
$appSetup = AppSetup::where('store', '=', id())->first();
if ($image) {
if ($imageType == "reference_images") {
$originalArray = $appSetup->$imageType;
$originalArray[] = $image;
$appSetup->$imageType = array_values(array_unique($originalArray));
} else {
$appSetup->$imageType = $image;
}
}
$appSetup->save();
return response()->json(['status' => 1, 'data' => $appSetup]);
}
Since reference_images is of type json, doing array_values(array_unique($originalArray)); is still an Array. You will have to convert it to json.
e.g. using collect()->json() docs
$appSetup->$imageType = collect($originalArray)->unique()->values()->toJson();

Store multiple objects in json column

I have table with some json column. I want to store multi objects in the json column in Laravel.
My json column look like this "position":[{"lat" : 500, "lon" : 5000, "date":"2020:04:21 16:58:23"}].
this is a function in a service that , i call in my controller
public static function savePositionCamion($id_tournee, $position)
{
$geoTour = GeoTournee::where('geo_tournee.id_tournee', $id_tournee)->first(['position']);
if (!$geoTour) {
$geoTournee = new self();
$geoTournee->id_tournee = $id_tournee;
$geoTournee->position = $position;
return $geoTournee->save() ? $geoTournee : false;
} else {
$arr_pos = json_decode($geoTour->position);
dd($arr_pos);
}
}
in the controller i call the function like this
$geoTourne = GeoTournee::savePositionCamion($request->id_tournee, json_encode($request->position));
anyone can help me to achieve this ! thank's
The array cast type is particularly useful when working with columns that are stored as serialized JSON. You have JSON or TEXT field type that contains serialized JSON, adding the array cast to that attribute will automatically deserialize the attribute to a PHP array when you access it on your Eloquent model:
class GeoTournee extends Model
{
...
protected $casts = [
'position' => 'array',
];
...
}
So you can save this json field like this:
$geoTournee->position = $position;
$geoTournee->save();
Accessing the position attribute and it will automatically be deserialized from JSON into a PHP array. When you set the value of the position attribute, the given array will automatically be serialized back into JSON for storage:
And you don't need to create savePositionCamion function, you can use firstOrCreate instead:
GeoTournee::firstOrCreate(['id_tournee' => $id_tournee], [ 'position' => $position ]);

How to display multiple images that stored as array in laravel?

please help me to display image that stored as array in database
my controller:
( filename is my image column name in database)
public function store(Request $request)
{
$this->validate($request, [
'filename' => 'required',
'filename.*' => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048'
]);
// Start multiple image upload code
if($request->hasfile('filename'))
{
foreach($request->file('filename') as $image)
{
$name=$image->getClientOriginalName();
$image->move(public_path().'/images/', $name);
$data[] = $name;
}
}
// End multiple image upload code
$houses= new House();
$houses->division = $request->input('division');
$houses->city = $request->input('city');
$houses->area = $request->input('area');
$houses->owner_name = $request->input('owner_name');
$houses->house_name = $request->input('house_name');
$houses->type = $request->input('type');
$houses->from = $request->input('from');
$houses->rent = $request->input('rent');
$houses->phone = $request->input('phone');
$houses->address = $request->input('address');
$houses->description = $request->input('description');
$houses->filename=json_encode($data); **// This for image upload**
$houses->save();
return back()->with('success', 'Your House has been successfully');
}
image column
First array cast the filename column in your model. For more: Array & JSON Casting
protected $casts = [
'filename' => 'array',
];
After that, whenever you fetch filename from House model, laravel will automatically convert the json data to array. Loop through the array and display the images.
$house = House::find(1);
foreach($house->filename as $filename) {
echo public_path().'/images/', $filename;
}
If you want to retrieve then display the images stored as an array what I'd suggest is casting the filename attribute to json/array in the model.
You can do that in your House model like this:
class House extends Model
{
protected $casts = [
'filename' => 'array',
];
}
To display it in a view you can loop through the casted array:
#foreach($house->filename as $image)
<img src="{{ url('link/to/assets/') . $image }}"
#endforeach
See more in the docs about casting here:
https://laravel.com/docs/5.7/eloquent-mutators#array-and-json-casting
A side point on image uploads, you may want to give uploaded files a unique name rather than using the user's filename so there's no conflict if a user uploads a document with the same name twice.
Laravel handles this all for you in the store() method seen here: https://laravel.com/docs/5.7/requests#storing-uploaded-files. You can create your own names if preferred using storeAs().

Yii2 display multiple images in gridview row

I want to display multiple images in a gridviews single row. For example: I have table A, Table B and table C.
Table A has my_id.
In Table B my_id is the foreign key. Along with my_id it has c_id.
Table C has c_id which is in reference in Table B.
Table C also has a filepath to display images.
in Table A i have my_id as follows:
1, 2, 3, 4, 5, 6.
In Table B i have my_id as follows.
1 ,1 ,1 ,2 ,3, 3.
In Table B i also have c_id as follows.
1, 2, 3, 4, 5, 6.
In table C my c_id's are:
1, 2, 3, 4, 5, 6. and these id's have filepath associated with each of them. They are different images.
Now my gridview should display 3 different images for my_id because of the foreign key constraints. but it displays only 1 image.
My code is below:
In my model
public function getPictogramsID()
{
$pictogramsID = SdsrefGhsPictograms::find()->where(['sdsref_id' => $this->sdsref_id])->all();
foreach ($pictogramsID as $picID){
return $picID->pictogram_id;
}
}
public function getPictogramPath()
{
$pictogramsID = GhsPictogram::find()->where(['pictogram_id' => $this->getPictogramsID()])->all();
foreach ($pictogramsID as $picID){
$pic = $picID->pictogram_filepath;
}
return $pic;
}
public function getPictogramUrl()
{
//var_dump($this->getPictogramPath()); exit();
return \Yii::$app->request->BaseUrl.'/web'.$this->getPictogramPath() ;
}
my index file grid view image code
[
'label' => 'Hazards',
'format' => 'raw',
'value' => function ($data) {
return Html::img($data->getPictogramUrl(), ['alt'=>'myImage','width'=>'20','height'=>'30']);
},
],
I am also trying to add a bootstrap tool tip to this.. tool tip is displaying successfully but I think the looping is not not done in a correct way so it is repeating my images.
here is my updated gridview code.
[
'label' => 'Hazards',
'format' => 'raw',
'value' => function ($data) {
$images = '';
// append all images
foreach($data->getPictogramName() as $name)
foreach ($data->getPictogramUrl() as $url)
$images = $images.Html::img($url,['alt'=>'','width'=>'30','height'=>'30', 'data-toggle'=>'tooltip','data-placement'=>'left','title' => $name ,'style'=>'cursor:default;']);
return $images;
}
],
You have few logical errors in model and grid view. In all these areas you are dealing with one item instead of three.
In your model
public function getPictogramsID()
{
$ids = [];
$pictogramsID = SdsrefGhsPictograms::find()->where(['sdsref_id' => $this->sdsref_id])->all();
foreach ($pictogramsID as $picID){
$ids[] = $picID->pictogram_id;
}
return $ids;// returning all three ids
}
public function getPictogramPath()
{
$pic = [];
$pictogramsID = GhsPictogram::find()->where(['pictogram_id' => $this->getPictogramsID()])->all();
foreach ($pictogramsID as $picID){
$pic[] = $picID->pictogram_filepath;
}
return $pic;
}
public function getPictogramUrl()
{
$url = [];
foreach($this->getPictogramPath() as $path):
$url[] = \Yii::$app->request->BaseUrl.'/web'.$path;
endforeach;
return $url; // returning al urls
}
Now in you view loop over all urls and append images with each url
[
'label' => 'Hazards',
'format' => 'raw',
'value' => function ($data) {
$images = '';
// append all images
foreach($data->getPictogramUrl() as $url):
$images = $images.Html::img($url, ['alt'=>'myImage','width'=>'20','height'=>'30']);
endforach;
return $images;
},
],

Resources