问题
I'm building an e-commerce website with cakephp3.7, and for sellers to post their products they need to upload the image of the article to sell, and that through a form with a Blob column. The images are being uploaded well from the view, but in the database the real name of the image does not appear, instead of that, in that place the name that appears for all the images is 'Blob' for all the articles. The problem is now that when I try to retrieve the article's image (which is only knowledgeable by it's name) from the database to the controller in order to send it to the frontend of the website, it doesn't find the image, and I'm seriously stuck !!!
But when I get to webroot/img folder, I find the uploaded image and, when I manually copy/paste the name in the frontend view, the image appears on the frontend with the other properties of the articles.
This is the controller code that is supposed to find the articles and their images from the database, the table to adress is table 'annonces', and the field of the table to store the image in is 'piece_jointe':
public function articles()
{
$this->viewBuilder()->layout('react2019');
$annonces = $this->Annonces->find()
->where(['Annonces.subcategorie_id'=>1])
->contain(['Comptes', 'Subcategories'])
->all();
$this->set(compact('annonces'));
}
And this is the article view when to forward the posted article to the frontend, the field which I can't retreive now is 'piece_jointe':
<?php foreach ($annonces as $annonce): ?>
<div class="col-lg-4 col-md-6 mb-4">
<div class="card h-100">
<a href="#"><?= $this->Html->image($annonce->piece_jointe, array('height'=>90, 'width'=>90)); ?></a>
<div class="card-body">
<h4 class="card-title">
<a href="#"><?= h($annonce->annonce_titre) ?></a>
</h4>
<h5><?= h($annonce->prix_produit) ?></h5>
<p class="card-text"><?= h($annonce->annonce_description) ?></p>
</div>
<div class="card-footer">
<small class="text-muted">★ ★ ★ ★ ☆</small>
</div>
</div>
</div>
<?php endforeach; ?>
I want to know the way to retrieve the name of a Blob type 'piece_jointe' from the mysql database and use it in the cakephp syntax:
<?= $this->Html->image($annonce->piece_jointe, array('height'=>90, '
width'=>90)); ?>
since this works fine when I replace the $annonce->piece_jointe varaible to it's real name 'macbook' for example :
<?= $this->Html->image('macbook', array('height'=>90, 'width'=>90)); ?>
回答1:
So far so good ! I dived deeper into cakephp's conventions about dealing with files such as images, videos, pdf, docs etc.. and I understood more things. First I thought I should store the image as BLOB in database in order to respect the MVC concept. But I finally figure out that cakephp has a leverage on how to deal with images and files in general, for images and files are sensible informations that open loopholes in applications and cakephp recommends not to store images straight in database to prevent from attacks such as SQL INJECTION. Many people have asked questions about how to deal with images in cakephp, but the answers that were given were not all fully applicable. So I wanna give the essentials in some 4 steps: 1- When we upload a file just as I did with the column 'piece_jointe' which type I changed from 'BLOB' to 'VARCHAR', cakephp gives parameters to that image as you can see here from the rendering of my debug($this->request->data) :
[
'title' => 'computer',
'category_id' => '1',
'subcategory_id' => '3',
'announce_description' => 'smart price',
'prix_produit' => '500000',
'photo'=> '',
'compte_id' => '1',
'piece_jointe' => [
'tmp_name' => '/private/var/folders/kl/lgxkfn5x4r1fjht2wckngjzr0000gn/T/phpodWgh1',
'error' => (int) 0,
'name' => 'macbook.jpg',
'type' => 'image/jpeg',
'size' => (int) 37780
]
]
You can observe that 'piece_jointe' has fields such as 'temp_name','error', 'name', 'type', 'size' created by cakephp for us to customise image and file uploading. But what we do need in this bunch of informations is 'name'. So we are going to add an other varchar column to the table announce in database, and that's why I added the column 'photo' with varchar type that you can see in the above debug result. The aim is to give to 'photo' the image's path $uploadPath = WWW_ROOT.'img/products/' and its name $fileName = $this->request->data['piece_jointe']['name'] in our controller add() method so cakephp may follow that path and get the image from the relevant folder which is in my case products folder inside webroot/img. The overall actions look something like these:
if (!empty ($this->request->data['piece_jointe']['tmp_name']))
{
$fileName = $this->request->data['piece_jointe']['name'];
$uploadPath = WWW_ROOT.'img/products/';
$uploadFile = $uploadPath.$fileName;
if (move_uploaded_File($this->request->data['piece_jointe']['tmp_name'], $uploadFile))
{
$annonce->photo = 'products/'.$fileName;
}
}
2- Then in the Model/Table don't forget to add this to the public function initialize(array $config) method:
$this->addBehavior('Timestamp');
An other thing is also not to forget to mention in the add() view where to upload the image that 'piece_jointe' is of 'type'=>'file'. You may have it like this:
<?php
echo $this->Form->input('piece_jointe', [ 'type' => 'file']);
?>
</Div>
3- Finally the column 'photo' receives this value in database /products/macbook.jpg instead of 'BLOB' while I was going nuts. 4- And to retrieve the image we just have to add this to the view:
<?= $this->Html->image($annonce->photo, array('height'=>90, 'width'=>90)); ?>
In conclusion, these are reliable steps to handle images and files uploading in cakephp. Storing images into database with BLOB type and expecting it to be displayed in frontend frow a raw MVC concept is just too loopy. Also thanks to @ndm for making me know I was missing the concept.
来源:https://stackoverflow.com/questions/57333785/how-to-retrieve-in-cakephp3-7-the-name-as-string-of-an-image-uploaded-trough-a-f