CakePHP 3 upload plików

W tej części zajmiemy się implementacją uploadu plików. Utwórzmy w bazie danych tabelę przechowującą pliki. Jest ona powiązana z modelem Applications oraz z Users.

  1. CREATE TABLE `documents` (
  2. `id` bigint(11) NOT NULL,
  3. `application_id` bigint(11) NOT NULL,
  4. `user_id` bigint(11) NOT NULL,
  5. `name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
  6. `filename` varchar(125) COLLATE utf8mb4_unicode_ci NOT NULL,
  7. `description` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  8. `modified` datetime NOT NULL,
  9. `created` datetime NOT NULL
  10. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
  11. ALTER TABLE `documents` ADD PRIMARY KEY (`id`);
Teraz utworzmy pliki modelu najpierw src/Model/Entity/Document.php.
  1. namespace App\Model\Entity;
  2.  
  3. use Cake\ORM\Entity;
  4.  
  5. class Document extends Entity
  6. {
  7. protected $_accessible = [
  8. '*' => true,
  9. 'id' => false
  10. ];
  11. }
Potem src/Model/Table/DocumentsTable.php.
  1. namespace App\Model\Table;
  2.  
  3. use Cake\ORM\Query;
  4. use Cake\ORM\RulesChecker;
  5. use Cake\ORM\Table;
  6. use Cake\Validation\Validator;
  7.  
  8. class DocumentsTable extends Table
  9. {
  10. public function initialize(array $config)
  11. {
  12. parent::initialize($config);
  13.  
  14. $this->table('documents');
  15. $this->displayField('name');
  16. $this->primaryKey('id');
  17.  
  18. $this->addBehavior('Timestamp');
  19.  
  20. $this->belongsTo('Applications');
  21. $this->belongsTo('Users');
  22. }
  23.  
  24. public function validationDefault(Validator $validator)
  25. {
  26. $validator
  27. ->allowEmpty('id', 'create');
  28.  
  29. $validator
  30. ->requirePresence('name', 'create')
  31. ->notEmpty('name');
  32.  
  33. $validator
  34. ->requirePresence('filename', 'create')
  35. ->notEmpty('filename');
  36.  
  37. return $validator;
  38. }
  39.  
  40. public function buildRules(RulesChecker $rules)
  41. {
  42. $rules->add($rules->existsIn(['application_id'], 'Applications'));
  43. $rules->add($rules->existsIn(['user_id'], 'Users'));
  44.  
  45. return $rules;
  46. }
  47. }
Nasze dokumenty są powiązane z użytkownikami i aplikacjami więc musimy zaktualizować ich klasy Table src/Model/Table/UsersTable.php oraz src/Model/Table/ApplicationsTable.php. Dodajemy poniższą linię w funkcji initialize.
  1. $this->hasMany('Documents');
Podczas ładowania Aplikacji lub Użytkownika musimy koniecznie załączyć powiązane Dokumenty za pomocą contain. W kontrolerach zaktualizuj funkcję view. W pliku src/Controller/ApplicationsController.php:
  1. $application = $this->Applications->get($id, ['contain' => 'Documents']);
W pliku src/Controller/UsersController.php:
  1. $user = $this->Users->get($id, ['contain' => 'Documents']);
Dodamy dokumenty z poziomu widoku Aplikacji, a także listę powiązanych dokumentów, edytując widok src/Template/Applications/view.ctp i dodając na końcu tego pliku:
  1. <div class="related">
  2. <?php echo $this->Html->link(__('New Document'), ['controller' => 'Documents', 'action' => 'add', $application->id], ['class' => 'right']) ?>
  3. <h3><?php echo __('Documents') ?></h3>
  4. <?php if (!empty($application->documents)): ?>
  5. <table cellpadding="0" cellspacing="0">
  6. <tr>
  7. <th scope="col"><?php echo __('Name') ?>
  8. <th scope="col"><?php echo __('Description') ?>
  9. <th scope="col" class="actions"><?php echo __('Actions') ?>
  10. </tr>
  11. <?php foreach ($application->documents as $documents): ?>
  12. <tr>
  13. <td><?php echo $this->Html->link($documents->name, '/files/' . $documents->filename) ?>
  14. <td><?php echo h($documents->description) ?></td>
  15. <td class="actions">
  16. <?php echo $this->Html->link(__('View'), '/files/' . $documents->filename) ?> |
  17. <?php echo $this->Html->link(__('Edit'), ['controller' => 'Documents', 'action' => 'edit', $documents->id]) ?>
  18. </td>
  19. </tr>
  20. <?php endforeach; ?>
  21. </table>
  22. <?php endif; ?>
  23. </div>
Dodamy teraz widok dodawania dokumentu (src/Template/Documents/add.ctp).
  1. <div class="documents form large-9 medium-8 columns content">
  2. <?php echo $this->Form->create($document, ['type' => 'file']) ?>
  3. <fieldset>
  4. <legend><?php echo __('Add Document') ?></legend>
  5. <?php
  6. echo $this->Form->input('application', ['type' => 'text', 'default' => $application_id, 'disabled' => true]);
  7. echo $this->Form->input('name', ['autofocus' => 'true']);
  8. echo $this->Form->input('file', ['type' => 'file', 'required' => true]);
  9. echo $this->Form->input('description');
  10. echo $this->Form->input('application_id', ['type' => 'hidden', 'value' => $application_id]);
  11. echo $this->Form->input('user_id', ['type' => 'hidden', 'value' => $user_id]);
  12. ?>
  13. </fieldset>
  14. <?php echo $this->Form->button(__('Submit')) ?>
  15. <?php echo $this->Html->link(__('Cancel'), ['controller' => 'Applications', 'action' => 'view', $application_id], ['class' => 'button']); ?>
  16. <?php echo $this->Form->end() ?>
  17. </div>
Widok edycji dokumentu (src/Template/Documents/edit.ctp).
  1. <div class="documents form large-9 medium-8 columns content">
  2. <?php echo $this->Form->create($document, ['type' => 'file']) ?>
  3. <fieldset>
  4. <legend><?php echo __('Edit Document') ?></legend>
  5. <?php echo $this->Form->input('name'); ?>
  6. <div><strong>Current File</strong></div>
  7. <?php
  8. echo $this->Html->link($document->filename, '/files/' . $document->filename);
  9. echo $this->Form->input('file', ['type' => 'file']);
  10. echo $this->Form->input('description');
  11. ?>
  12. </fieldset>
  13. <?php echo $this->Form->button(__('Submit')) ?>
  14. <?php echo $this->Html->link(__('Cancel'), ['controller' => 'Applications', 'action' => 'view', $document->application_id], ['class' => 'button']); ?>
  15. <?php echo $this->Form->end() ?>
  16. </div>
Przejdźmy teraz do kontrolera dokumentów. Tworzymy następujący plik (src/Controller/DocumentsController.php).
  1. namespace App\Controller;
  2.  
  3. use App\Controller\AppController;
  4.  
  5. class DocumentsController extends AppController
  6. {
  7. public function isAuthorized($user) {
  8. if ($user['role'] == 'Admin') { // Only Admin can add/edit documents
  9. return true;
  10. }
  11. return false;
  12. }
  13.  
  14. public function add($application_id = null) {
  15. if (is_null($application_id)) { // Documents must be attached to an application
  16. $this->redirect(['controller' => 'Applications', 'action' => 'index']);
  17. }
  18. $document = $this->Documents->newEntity();
  19. if ($this->request->is('post')) {
  20. $file = $this->request->data['file'];
  21. $file['name'] = time() . '-' . str_replace(' ', '_', $file['name']); // timestamp files to prevent clobber
  22. if (move_uploaded_file($file['tmp_name'], WWW_ROOT . 'files/' . $file['name'])) {
  23. $this->request->data['filename'] = $file['name'];
  24. $document = $this->Documents->patchEntity($document, $this->request->data);
  25. if ($this->Documents->save($document)) {
  26. $this->Flash->success(__('The document has been saved.'));
  27. return $this->redirect(['controller' => 'Applications', 'action' => 'view', $document->application_id]);
  28. } else {
  29. $this->Flash->error(__('The document could not be saved. Please, try again.'));
  30. }
  31. } else {
  32. $this->Flash->error(__('Could not upload the file'));
  33. }
  34. }
  35. $user_id = $this->Auth->user('id');
  36. $this->set(compact('document', 'application_id', 'user_id'));
  37. $this->set('_serialize', ['document']);
  38. }
  39.  
  40. public function edit($id = null) {
  41. $document = $this->Documents->get($id);
  42. if ($this->request->is(['patch', 'post', 'put'])) {
  43. $file = $this->request->data['file'];
  44. if ($file['name'] != '' && move_uploaded_file($file['tmp_name'], WWW_ROOT . 'files/' . $file['name'])) {
  45. $this->request->data['filename'] = $file['name'];
  46. }
  47. $document = $this->Documents->patchEntity($document, $this->request->data);
  48. if ($this->Documents->save($document)) {
  49. $this->Flash->success(__('The document has been saved.'));
  50. return $this->redirect(['controller' => 'Applications', 'action' => 'view', $document->application_id]);
  51. } else {
  52. $this->Flash->error(__('The document could not be saved. Please, try again.'));
  53. }
  54. }
  55. $this->set(compact('document'));
  56. $this->set('_serialize', ['document']);
  57. }
  58. }
Ponieważ zapisujemy pliki do katalogu /webroot/files/ naszej aplikacji, upewnij się, że katalog ten istnieje i że użytkownik (np. Apache) ma prawo zapisu do tego katalogu.

Strona korzysta z plików cookies

Strona korzysta z plików cookies w celu realizacji usług i zgodnie z Polityką Plików Cookies. Możesz określić warunki przechowywania lub dostępu do plików cookies w Twojej przeglądarce.
OK
Więcej
Free cookie consent by cookie-script.com