'Indirect modification of overloaded element of Illuminate\Support\Collection has no effect

im quite new in laravel framework, and im from codeigniter.

I would like to add new key and value from database

static function m_get_promotion_banner(){
    $query = DB::table("promotion_banner")
        ->select('promotion_banner_id','promotion_link','about_promotion')
        ->where('promotion_active','1')
        ->get();
    if($query != null){
        foreach ($query as $key => $row){
            $query[$key]['promotion_image'] = URL::to('home/image/banner/'.$row['promotion_banner_id']);
        }
    }
    return $query;
}

that code was just changed from codeigniter to laravel, since in codeigniter there are no problem in passing a new key and value in foreach statement

but when i tried it in laravel i got this following error :

Indirect modification of overloaded element of Illuminate\Support\Collection has no effect

at HandleExceptions->handleError(8, 'Indirect modification of overloaded element of Illuminate\Support\Collection has no effect', 'C:\xampp\htdocs\laravel-site\application\app\models\main\Main_home_m.php', 653, array('query' => object(Collection), 'row' => array('promotion_banner_id' => 1, 'promotion_link' => 'http://localhost/deal/home/voucher', 'about_promotion' => ''), 'key' => 0))

please guide me how to fix this

thank you (:



Solution 1:[1]

For others who needs a solution you can use jsonserialize method to modify the collection. Such as:

$data = $data->jsonserialize();
//do your changes here now.

Solution 2:[2]

The problem is the get is returning a collection of stdObject

Instead of adding the new field to the result of your query, modify the model of what you are returning.

So, assuming you have a PromotionBanner.php model file in your app directory, edit it and then add these 2 blocks of code:

protected $appends = array('promotionImage');

here you just added the custom field. Now you tell the model how to fill it:

public function getPromotionImageAttribute() {
    return (url('home/image/banner/'.$this->promotion_banner_id)); 
}

Now, you get your banners through your model:

static function m_get_promotion_banner(){
    return \App\PromotionBanner::where('promotion_active','1')->get();
}

Now you can access your promotionImage propierty in your result

P.D: In the case you are NOT using a model... Well, just create the file app\PromotionImage.php:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;


class PromotionImage extends Model
{
    protected $appends = array('imageAttribute');
    protected $table = 'promotion_banner';    

    public function getPromotionImageAttribute() {
        return (url('home/image/banner/'.$this->promotion_banner_id)); 
    }

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'promotion_banner_id','promotion_link','about_promotion','promotion_active'
    ];

Solution 3:[3]

just improving, in case you need to pass data inside the query

$url = 'home/image/banner/';
$query = $query->map(function ($object) use ($url) {

    // Add the new property
    $object->promotion_image = URL::to( $url . $object->promotion_banner_id);

   // Return the new object
   return $object;
});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Alican Ali
Solution 2
Solution 3 Rodrigo Klim