Caio Kawasaki
Caio Kawasaki

Reputation: 2950

Laravel - Prevent from create empty key in database

I have a table where I keep all the settings that will be used on the website, they are saved in the cache, I'm trying to upload the favicon, however when uploading the image the favicon row is updated and an empty key value with the temp path is created at the same time, how can I solve this?

enter image description here You can see the empty field in the image...

Route

Route::put('/', ['as' => 'setting.update', 'uses' => 'Admin\AdminConfiguracoesController@update']);

Model

class Setting extends Model
{
    protected $table = 'settings';

    public $timestamps = false;

    protected $fillable = ['value'];
}

Controller

class AdminConfiguracoesController extends AdminBaseController
{
    private $repository;

    public function __construct(SettingRepository $repository){
        parent::__construct();
        $this->repository = $repository;
    }

    public function update(Request $request, Factory $cache)
    {
        $settings = $request->except('_method', '_token');

        $this->repository->update($settings);

        $cache->forget('settings');

        return redirect()->back();
    }
}

Repository

class SettingRepository{
    private $settings;

    public function __construct(Setting $settings)
    {
        $this->settings = $settings;
    }

    public function update($key, $value = null)
    {
        if (is_array($key))
        {
            foreach ($key as $name => $value)
            {
                if( $name == "website_favicon" ){
                    $imageName = $key['website_favicon']->getClientOriginalName();

                    $this->update($name, asset('public/images/website/'.$imageName));

                    $key['website_favicon']->move(
                        base_path() . '/public/images/website/', $imageName
                    );
                } else{
                    $this->update($name, $value);
                }
            }
        }

        $setting = $this->settings->firstOrCreate(['name' => $key]);
        $setting->value = $value;
        $setting->save();
    }

    public function lists()
    {
        return $this->settings->lists('value', 'name')->all();
    }
}

Upvotes: 0

Views: 197

Answers (1)

tommy
tommy

Reputation: 3615

The problem is a missing return statement after the foreach loop in your repository. The code after the loop will be executed. $key is an array and $value is the temp value of the uploaded file, which will be set inside the loop.

As I mentioned in my comment, you shouldn't use the repository to upload files. Do it in your controller instead:

AdminConfiguracoesController.php

class AdminConfiguracoesController extends AdminBaseController
{
    private $repository;

    public function __construct(SettingRepository $repository)
    {
        parent::__construct();
        $this->repository = $repository;
    }

    public function update(Request $request, Factory $cache)
    {
        $settings = $request->except('_method', '_token', 'website_favicon');

        if ($request->hasFile('website_favicon'))
        {
            $this->uploadImage($request->file('website_favicon'), 'website_favicon');
            $cache->forget('website_favicon');
        }

        $this->repository->update($settings);

        $cache->forget('settings');

        return redirect()->back();
    }

    private function uploadImage(UploadedFile $image, $key)
    {
        $image->move(public_path('images/website'), $image->getClientOriginalName());

        $this->repository->update($key, $image->getClientOriginalName());
    }
}

SettingRepository.php

class SettingRepository
{

    private $settings;

    public function __construct(Setting $settings)
    {
        $this->settings = $settings;
    }

    public function update($key, $value = null)
    {
        if (is_array($key))
        {
            foreach ($key as $name => $value)
            {
                $this->update($name, $value);
            }

            return; // This was missing!
        }

        $setting = $this->settings->firstOrCreate(['name' => $key]);
        $setting->value = $value;
        $setting->save();
    }

    public function lists()
    {
        return $this->settings->lists('value', 'name')->all();
    }
}

You can refactor this even further to use a Job that uploads the image, but this would be overkill for now.

Upvotes: 1

Related Questions