# Keep the image after editing the form. - Cakephp 3

**URL:** <https://discourse.cakephp.org/t/keep-the-image-after-editing-the-form-cakephp-3/7971>\
**Category:** Need Help\
**Created:** [June 21, 2020, 9:20pm UTC](https://discourse.cakephp.org/t/keep-the-image-after-editing-the-form-cakephp-3/7971 "2020-06-21T21:20:04Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![ecei](https://avatars.discourse-cdn.com/v4/letter/e/f08c70/32.png) [@ecei](https://discourse.cakephp.org/u/ecei)\
**Post date:** [June 21, 2020, 9:20pm UTC](https://discourse.cakephp.org/t/keep-the-image-after-editing-the-form-cakephp-3/7971/1 "2020-06-21T21:20:04Z")

</div>

Friends,  
I’m trying to edit a form with the upload field not required, that is, keeping the images that have been added.

I’m adding the images like this:

```auto
.
.
$product = $this->Products->newEntity();
        if ($this->request->is('post')) {
            if(!empty($this->request->data['img_product']['name'])){
                $filename = $this->request->data['img_product']['name'];
                $myext = substr(strchr($filename, "."), 1);
                $path = "img/img_products/".Security::hash($filename);
                $uploadFile = $path.$filename;
                if(move_uploaded_file($this->request->data['img_product']['tmp_name'], $uploadFile))
                {
                    $this->request->data['img_product'] = $filename;
                    $this->request->data['path'] = $path;

                }
                $product = $this->Product->patchEntity($produto, $this->request->getData());
                if ($this->Products->save($product)) {
                    $this->Flash->success(__('Produto salvo com sucesso!'));

                    return $this->setAction('index');
                }
                $this->Flash->success(__('error!'));
            }
            
            if(empty($this->request->data['img_product']['name'])){
                $this->request->data['img_product'] = "sem-imagem.jpg";
                $product->path = "img/img_products/";
                $product = $this->Produtos->patchEntity($produto, $this->request->getData());
                if ($this->Products->save($product)) {
                    $this->Flash->success(__('save'));

                    return $this->setAction('index');
                }
            }
  }
.
.

```

This works perfectly.  
However, I want to edit this form without the need for the file field to be mandatory, that is, the image that was previously registered can be kept.

the products table has the img\_product and path fields to save the image path.

The method of editing is as follows:

```auto
$product = $this->Products->findBySlug($slug)->firstOrFail();
        if ($this->request->is('post') || $this->request->is('put')) {
            if(!empty($this->request->data['img_product']['name'])){
                unlink(WWW_ROOT .$product->path.$product->img_product);
                $filename = $this->request->data['img_product']['name'];
                $myext = substr(strchr($filename, "."), 1);
                $path = "img/img_products/".Security::hash($filename).".".$myext;
                $uploadFile = $path.$filename;
                if(move_uploaded_file($this->request->data['img_product']['tmp_name'], $uploadFile))
                {
                    $this->request->data['img_product'] = $filename;
                    $this->request->data['path'] = $path;

                }
                $produto = $this->Products->patchEntity($produto, $this->request->getData());
                if ($this->Products->save($produto)) {
                    $this->Flash->success(__('save'));

                    return $this->setAction('index');
                }
            }
        $this->Flash->success(__('error'));

}

```

edit.ctp

```auto
<small>Image</small>
                  <?= $this->Form->control('img_product', [
                  'class' => 'form-control form-control-user',
                  'type' => 'file',
                  'allowempty' => true,
                  'label' => false,
                  ]);?>

```

ProductTable.php

```auto
         $validator
        ->scalar('img_product')
        ->maxLength('img_product', 255)
        ->allowEmptyString('img_product');

        $validator
        ->scalar('path')
        ->maxLength('path', 255)
        ->notEmptyString('path');

```

When the image field is not empty, the image is replaced normally. But I’m having trouble maintaining the image. If a new image is not inserted. I appreciate any comments.

The basic idea is to keep a previously registered image.

---

<div class="post-metadata">

**Author:** ![dreamingmind](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/dreamingmind/32/1857_2.png) [@dreamingmind](https://discourse.cakephp.org/u/dreamingmind)\
**Post date:** [June 22, 2020, 4:26am UTC](https://discourse.cakephp.org/t/keep-the-image-after-editing-the-form-cakephp-3/7971/2 "2020-06-22T04:26:59Z")

</div>

The nesting of the `if`s in your edit method look strange.

The save only runs when there is a new file name.

How about this:

```auto
        $product = $this->Products->findBySlug($slug)->firstOrFail();
        if ($this->request->is('post') || $this->request->is('put')) {
            if (!empty($this->request->data['img_product']['name'])) {
                unlink(WWW_ROOT . $product->path . $product->img_product);
                $filename = $this->request->data['img_product']['name'];
                $myext = substr(strchr($filename, "."), 1);
                $path = "img/img_products/" . Security::hash($filename) . "." . $myext;
                $uploadFile = $path . $filename;
                if (move_uploaded_file($this->request->data['img_product']['tmp_name'], $uploadFile)) {
                    $this->request->data['img_product'] = $filename;
                    $this->request->data['path'] = $path;
                }
            }
            $produto = $this->Products->patchEntity($produto, $this->request->getData());
            if ($this->Products->save($produto)) {
                $this->Flash->success(__('save'));
                return $this->setAction('index');
            }
            $this->Flash->success(__('error'));
        }

```

---

<div class="post-metadata">

**Author:** ![ecei](https://avatars.discourse-cdn.com/v4/letter/e/f08c70/32.png) [@ecei](https://discourse.cakephp.org/u/ecei)\
**Post date:** [June 22, 2020, 2:02pm UTC](https://discourse.cakephp.org/t/keep-the-image-after-editing-the-form-cakephp-3/7971/3 "2020-06-22T14:02:48Z")

</div>

I am getting this error.

```auto
'[hasErrors]' => true,
	'[errors]' => [
		'img_product' => [
			'scalar' => 'The provided value is invalid',
			'maxLength' => 'The provided value is invalid'
		]
	],
	'[invalid]' => [
		'img_product' => [
			'tmp_name' => '',
			'error' => (int) 4,
			'name' => '',
			'type' => '',
			'size' => (int) 0
		]
	],

```

My ProductTable.php

```auto
$validator
        ->scalar('img_product')
        ->maxLength('img_product', 255)
        ->allowEmptyString('img_product');

        $validator
        ->scalar('path')
        ->maxLength('path', 255)
        ->allowEmptyString('path');

```

![tela](https://canada1.discourse-cdn.com/flex029/uploads/cakephp/original/2X/0/0783dc4bbcbd86ac2592a196c64e707ba9707a24.png)

---

<div class="post-metadata">

**Author:** ![dreamingmind](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/dreamingmind/32/1857_2.png) [@dreamingmind](https://discourse.cakephp.org/u/dreamingmind)\
**Post date:** [June 22, 2020, 3:21pm UTC](https://discourse.cakephp.org/t/keep-the-image-after-editing-the-form-cakephp-3/7971/4 "2020-06-22T15:21:11Z")

</div>

The error is for `img_product` and the validator you are showing is for `img_producto`.

Is this a typo in your code or your question?

That validation rule says image product can be an empty string, but the actual value appears to be an array and it is not empty.

Can you make the validator allow an empty string at `img_product.name` or change your code a little?

```auto
        $product = $this->Products->findBySlug($slug)->firstOrFail();
        if ($this->request->is('post') || $this->request->is('put')) {
            if (!empty($this->request->data['img_product']['name'])) {
               //handle the upload here
            } else {
                //unset request->data['img_product'] here
            }
            $produto = $this->Products->patchEntity($produto, $this->request->getData());
            if ($this->Products->save($produto)) {
                $this->Flash->success(__('save'));
                return $this->setAction('index');
            }
            $this->Flash->success(__('error'));
        }

```

---

<div class="post-metadata">

**Author:** ![ecei](https://avatars.discourse-cdn.com/v4/letter/e/f08c70/32.png) [@ecei](https://discourse.cakephp.org/u/ecei)\
**Post date:** [June 23, 2020, 1:27am UTC](https://discourse.cakephp.org/t/keep-the-image-after-editing-the-form-cakephp-3/7971/5 "2020-06-23T01:27:41Z")

</div>

I changed it to:

```auto
 $validator
 ->allowEmpty ('img_product'); 

```

in ProductTable.php

And now I get the empty string in:

```auto
.
if(move_uploaded_file($this->request->data['img_product']['tmp_name'], $uploadFile))
  {
  $this->request->data['img_product'] = $filename;
  $this->request->data['path'] = $path;
       
  }else {
  $produto->img_product = ' ';                
  }
.
.

```

This way I can leave the optional upload field, but as I get empty, the image that was supposed to be kept goes out, as I update the value of the img\_product in the bank. Now the question arises of how to preserve the image. I appreciate any comments.

---

<div class="post-metadata">

**Author:** ![dreamingmind](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/dreamingmind/32/1857_2.png) [@dreamingmind](https://discourse.cakephp.org/u/dreamingmind)\
**Post date:** [June 23, 2020, 2:27am UTC](https://discourse.cakephp.org/t/keep-the-image-after-editing-the-form-cakephp-3/7971/6 "2020-06-23T02:27:26Z")

</div>

In Cake4x the request is now immutable. That might be the case in 3x also. If so you would have to move request-\>data() to a variable and use/modify that or use `withData()`

```auto
$patchCandidate = $this->request->getData();
$patchCandidate['img_product'] = '';

$this->Products->patchEntity($produto, $patchCandidate);)

//or
$this->request = $this->request->withData('img_product', '');

```

---

<div class="post-metadata">

**Author:** ![ecei](https://avatars.discourse-cdn.com/v4/letter/e/f08c70/32.png) [@ecei](https://discourse.cakephp.org/u/ecei)\
**Post date:** [June 23, 2020, 9:51pm UTC](https://discourse.cakephp.org/t/keep-the-image-after-editing-the-form-cakephp-3/7971/7 "2020-06-23T21:51:50Z")

</div>

> [@dreamingmind](#):
>
> ```auto
> $this->request = $this->request->withData('img_product', '');
> 
> ```

I believe it doesn’t work in cakephp 3.8. The path is preserved, but the img\_product is empty and the image disappears.

```auto
if(move_uploaded_file($this->request->data['img_product']['tmp_name'], $uploadFile))
   {
    $this->request->data['img_product'] = $filename;
    $this->request->data['path'] = $path;
     }
   }else{
	$this->request = $this->request->withData('img_product', '');
  }

```

‘img\_product’ =\> ‘’,  
‘path’ =\> ‘img/img\_products/7588510c5ab9b55517e26ed9c87b83d576010a2e’,

I’ll think about it and post the result.
