为什么patchEntity()会剪切图像信息? (CakePHP3)

时间:2018-01-24 14:46:09

标签: cakephp cakephp-3.0

使用POST方法$data = $this->request->getData();,我得到了存档:

[
        'category_id' => '62',
        'title' => 'Name-1',
        'body' => '<p>Text</p>
    ',
        'price' => '30',
        'is_new' => '1',
        'img' => [
            'tmp_name' => 'D:\Web\OpenServer\userdata\temp\php70D9.tmp',
            'error' => (int) 0,
            'name' => 'IronMan.jpg',
            'type' => 'image/jpeg',
            'size' => (int) 131830
        ]
]

通过为数据库中的记录准备这些数据:

$product = $this->Products->patchEntity($product, $data);

但patchEntity()方法会删除有关图像的所有信息。 我明白了:

object(App\Model\Entity\Product) {

    'category_id' => (int) 62,
    'title' => 'Name-1',
    'body' => '<p>Text</p>
',
    'price' => (float) 30,
    'is_new' => (int) 1,
    'img' => '', // <--- empty :(
    '[new]' => true,
    '[accessible]' => [
        'category_id' => true,
        'title' => true,
        'body' => true,
        'price' => true,
        'img' => true,
        'is_new' => true,
        'created' => true,
        'modified' => true,
        'category' => true
    ],
    '[dirty]' => [
        'category_id' => true,
        'title' => true,
        'body' => true,
        'price' => true,
        'is_new' => true,
        'img' => true
    ],
    '[original]' => [],
    '[virtual]' => [],
    '[errors]' => [],
    '[invalid]' => [],
    '[repository]' => 'Products'

}

可以修复吗?至少告诉我一下。谢谢。

2 个答案:

答案 0 :(得分:1)

在修补/创建实体时,数据将根据相应的列数据类型进行编组,正如您可以看到的price等其他属性,它们从字符串转换为浮点数。

您的img列可能是字符串类型,导致编组人员相应地转换数据(请参阅\Cake\Database\Type\StringType::marshal())。

有多种方法可以避免这种情况,例如使用不会映射到现有列的其他属性名称,例如img_upload,然后在移动上载后,手动设置生成的文件系统路径到img属性并保存。

这也可以在beforeMarshal类的ProductsTable事件中完成,以便视图模板可以继续使用img属性:

public function beforeMarshal(
    \Cake\Event\Event $event,
    \ArrayObject $data,
    \ArrayObject $options
) {
    if (isset($data['img'])) {
        $data['img_upload'] = $data['img'];
        unset($data['img']);
    }
}

您还可以为img列创建自定义数据库类型,该列不会将数据封送到字符串,而只是传递它:

namespace App\Database\Type;

use Cake\Database\Type;

class FileType extends Type
{
    public function marshal($value)
    {
        return $value;
    }
}

你必须分配文件系统路径,但你基本上只是避免使用单独的/临时属性。

另见

答案 1 :(得分:0)

我不知道这是多少是正确的,但最后我做了以下事情,一切都按照我的需要运作:

在ProductsController中

 public function add()
{
    $product = $this->Products->newEntity();

    if ($this->request->is('post')) {
        $data = $this->request->getData();

        $product = $this->Products->patchEntity($product, $data);

        // If there is a picture that we checked (by the method of validationDefault, when calling patchEntity) and have already uploaded to the server in a temporary folder, then
        if($product->img_upload['name']){
            // We call the user method of processing the downloaded image
            $product = $this->_customUploadImg($product);
            // Leave only the name of the new file, adding it to the new property, with the name corresponding to the name of the table in the database
            $product->img = $product->img_upload['name'];
        }
        // Delete an unnecessary property
        unset($product->img_upload);

        if ($this->Products->save($product)) {
            // ...
        }
    // ...
}

在Product.php中:

    class Product extends Entity{
    protected $_accessible = [
        'category_id' => true,
        'title' => true,
        'body' => true,
        'price' => true,
        'is_new' => true,
        'created' => true,
        'modified' => true,
        'category' => true,

        // 'img' => true,
        // Here we specify not 'img' as in the database table, but 'img_upload', in order for ProductsController not to delete our data file about the uploaded file when patchEntity was called.
        'img_upload' => true,
    ];
}

在ProductsTable.php

public function validationDefault(Validator $validator)
{
    //...

     $validator
        ->allowEmpty('img_upload', 'create')
        ->add('img_upload', [
            'uploadError' => [
                'rule' => 'uploadError',
                'message' => 'Error loading picture'
            ],
            'mimeType' => [
                'rule' => ['mimeType', ['image/jpeg', 'image/jpg', 'image/png', 'image/gif']],
                'message' => 'Only image files are allowed to be uploaded: JPG, PNG и GIF'
            ],
            'fileSize' => [
                'rule' => ['fileSize', '<=', '2MB'],
                'message' => 'The maximum file size should be no more than 2 MB'
            ]
        ]);

    //...
}

在add.ctp

echo $this->Form->create($product, ['type' => 'file']) ?>
// ...
echo $this->Form->control('img_upload', ['type' => 'file', 'label'=>'Product photo']);
//...

谢谢&#34; ndm&#34;和&#34;标记&#34;!