├── .gitignore ├── workshop ├── files │ ├── 2-open-read-file.txt │ ├── 1-introduction-file.txt │ └── 3-create-write-file.txt ├── 4.1-upload-script.php ├── 3-file-create-write.php ├── 2-file-open-read.php ├── 4-file-upload.php └── 1-introduction.php ├── assets ├── img │ ├── folder.gif │ ├── assembler.png │ ├── file-manager.gif │ └── assembler_icon.jfif ├── js │ └── cheatsheet.js └── css │ └── cheatsheet.css ├── README.md ├── package.json └── index.php /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /workshop/files/2-open-read-file.txt: -------------------------------------------------------------------------------- 1 | This is the content of the "2-open-read-file.txt" file. -------------------------------------------------------------------------------- /workshop/files/1-introduction-file.txt: -------------------------------------------------------------------------------- 1 | This is the content of the "1-introduction-file.txt" file. -------------------------------------------------------------------------------- /assets/img/folder.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DogSoulDev/php-manage-files-workshop/HEAD/assets/img/folder.gif -------------------------------------------------------------------------------- /assets/img/assembler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DogSoulDev/php-manage-files-workshop/HEAD/assets/img/assembler.png -------------------------------------------------------------------------------- /assets/img/file-manager.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DogSoulDev/php-manage-files-workshop/HEAD/assets/img/file-manager.gif -------------------------------------------------------------------------------- /workshop/files/3-create-write-file.txt: -------------------------------------------------------------------------------- 1 | This is the content of the "3-create-write-file.txt" file. 2 | New content in a new line. -------------------------------------------------------------------------------- /assets/img/assembler_icon.jfif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DogSoulDev/php-manage-files-workshop/HEAD/assets/img/assembler_icon.jfif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | `php` `#backend` `#manage-files` `#master-in-software-engineering` 2 | 3 | # Assembler Institute: Manage files with PHP - Workshop 4 | 5 | In this workshop you will learn how to manage your backend files with PHP. 6 | 7 | ## Table of Contents 8 | 9 | - [Getting Started](#getting-started) 10 | 11 | ## Getting Started 12 | 13 | First of all, you will need to clone this repo: 14 | 15 | ```bash 16 | $ git clone https://github.com/assembler-institute/php-manage-files-workshop.git 17 | ``` 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "php-manage-files-workshop", 3 | "version": "1.0.0", 4 | "description": "`php` `#backend` `#manage-files` `#master-in-software-engineering`", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/assembler-school/php-manage-files-workshop.git" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "bugs": { 17 | "url": "https://github.com/assembler-school/php-manage-files-workshop/issues" 18 | }, 19 | "homepage": "https://github.com/assembler-school/php-manage-files-workshop#readme", 20 | "dependencies": { 21 | "bootstrap": "^5.0.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /workshop/4.1-upload-script.php: -------------------------------------------------------------------------------- 1 | File is an image - " . $check["mime"] . ".

"; 11 | $uploadOk = 1; 12 | if (move_uploaded_file($_FILES['fileToUpload']['tmp_name'], $target_file)) { 13 | echo "

El fichero es válido y se subió con éxito.

"; 14 | } else { 15 | echo "

¡Posible ataque de subida de ficheros!

"; 16 | } 17 | } else { 18 | echo "File is not an image."; 19 | $uploadOk = 0; 20 | } 21 | } 22 | 23 | ?> 24 |

Back

-------------------------------------------------------------------------------- /assets/js/cheatsheet.js: -------------------------------------------------------------------------------- 1 | /* global bootstrap: false */ 2 | 3 | (function () { 4 | "use strict"; 5 | 6 | // Tooltip and popover demos 7 | document.querySelectorAll(".tooltip-demo").forEach(function (tooltip) { 8 | new bootstrap.Tooltip(tooltip, { 9 | selector: '[data-bs-toggle="tooltip"]', 10 | }); 11 | }); 12 | 13 | document 14 | .querySelectorAll('[data-bs-toggle="popover"]') 15 | .forEach(function (popover) { 16 | new bootstrap.Popover(popover); 17 | }); 18 | 19 | document.querySelectorAll(".toast").forEach(function (toastNode) { 20 | var toast = new bootstrap.Toast(toastNode, { 21 | autohide: false, 22 | }); 23 | 24 | toast.show(); 25 | }); 26 | 27 | // Disable empty links 28 | document.querySelectorAll('[href="#"]').forEach(function (link) { 29 | link.addEventListener("click", function (event) { 30 | event.preventDefault(); 31 | }); 32 | }); 33 | 34 | function setActiveItem() { 35 | var hash = window.location.hash; 36 | 37 | if (hash === "") { 38 | return; 39 | } 40 | 41 | var link = document.querySelector('.bd-aside a[href="' + hash + '"]'); 42 | var active = document.querySelector(".bd-aside .active"); 43 | var parent = link.parentNode.parentNode.previousElementSibling; 44 | 45 | link.classList.add("active"); 46 | 47 | if (parent.classList.contains("collapsed")) { 48 | parent.click(); 49 | } 50 | 51 | if (!active) { 52 | return; 53 | } 54 | 55 | var expanded = active.parentNode.parentNode.previousElementSibling; 56 | 57 | active.classList.remove("active"); 58 | 59 | if (expanded && parent !== expanded) { 60 | expanded.click(); 61 | } 62 | } 63 | 64 | setActiveItem(); 65 | window.addEventListener("hashchange", setActiveItem); 66 | })(); 67 | -------------------------------------------------------------------------------- /workshop/3-file-create-write.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | You also can create your own files and modify it, there is two main functions for this. 5 | Keep in mind that you must have permissions on you server side in order to create/modify files. 6 | Every time that you modify a file, you're replacing all the previous content of the file. 7 |

8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
FunctionDescriptionDocumentation
fopen()This function is also used to create a file. If you specify a file that doesn't exist, it will create it, given that the file is opened for writing (w) or appending (a).Link
fwrite()This function is used to write to a file. The first parameter of fwrite() contains the name of the file to write to and the second parameter is the string to be written.Link
30 | 31 |

Code:

32 | 33 |
<?php

34 | try { 35 | $newFileName = "./workshop/files/3-create-write-file.txt"; 36 | $fileContent = 'This is the content of the "3-create-write-file.txt" file.'; 37 | 38 | // Now the file is created, but it's empty. 39 | $file = fopen($newFileName, "w"); 40 | 41 | // Here we add the content to the file 42 | fwrite($file, $fileContent); 43 | 44 | // You can add new content to the file 45 | fwrite($file, "\nNew content in a new line."); 46 | 47 | $file = fopen($newFileName, "r"); 48 | 49 | // Print the content 50 | $content = fread($file, filesize($newFileName)); 51 | echo nl2br($content); 52 | 53 | // Close the file buffer 54 | fclose($file); 55 | } catch (Throwable $t) { 56 | echo $t->getMessage(); 57 | } 58 |

?>
59 | 60 |

Result:

61 | 62 | 71 |
72 |
-------------------------------------------------------------------------------- /workshop/2-file-open-read.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | Like you can see before, the readFile() function it's very simple to use, but you can't customize how you want to retrieve 5 | the information from the file. 6 |

7 |

8 | Now you will learn how to open, read, and close a file on the server in a manual way. 9 | There is tree main functions that you will have to use are: 10 |

11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |
FunctionDescriptionDocumentation
fopen()Opens a URL or a file, it requires two parameters, the file/url that you want to open and the way that you want to be opened.Link
fread()Once the file is opened, fread() function reads the file, you must provide two parameters, the path and the length of the file.Link
fclose()Finally, you should close the file in order to save server memory (not mandatory but recommended).Link
37 | 38 |

Code:

39 | 40 |
<?php

41 | try { 42 | $fileName = "./workshop/files/example-file.txt"; 43 | 44 | if (!file_exists($fileName)) { 45 | throw new Exception('File open failed'); 46 | } 47 | 48 | // The function returns a pointer to the file if it is successful or zero if it is not. Files are opened for read or write operations. 49 | $file = fopen($fileName, "r"); 50 | 51 | // Reads the file 52 | $content = fread($file, filesize($fileName)); 53 | 54 | echo $content; 55 | 56 | // Close the file buffer 57 | fclose($file); 58 | } catch (Throwable $t) { 59 | echo $t->getMessage(); 60 | } 61 |

?>
62 | 63 |

Result:

64 | 65 | 74 |
75 |
-------------------------------------------------------------------------------- /workshop/4-file-upload.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | You also can create your own files and modify it, there is two main functions for this. 5 | Keep in mind that you must have permissions on you server side in order to create/modify files. 6 | Every time that you modify a file, you're replacing all the previous content of the file. 7 |

8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
FunctionDescriptionDocumentation
fopen()This function is also used to create a file. If you specify a file that doesn't exist, it will create it, given that the file is opened for writing (w) or appending (a).Link
fwrite()This function is used to write to a file. The first parameter of fwrite() contains the name of the file to write to and the second parameter is the string to be written.Link
30 | 31 |

Code:

32 | 33 |
<?php

34 | $target_dir = "./files/"; 35 | $target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]); 36 | $uploadOk = 1; 37 | $imageFileType = strtolower(pathinfo($target_file, PATHINFO_EXTENSION)); 38 | // Check if image file is a actual image or fake image 39 | if (isset($_POST["submit"])) { 40 | $check = getimagesize($_FILES["fileToUpload"]["tmp_name"]); 41 | if ($check !== false) { 42 | echo "<p>File is an image - " . $check["mime"] . ".</p>"; 43 | $uploadOk = 1; 44 | if (move_uploaded_file($_FILES['fileToUpload']['tmp_name'], $target_file)) { 45 | echo "<p>El fichero es válido y se subió con éxito.</p>"; 46 | } else { 47 | echo "<p>¡Posible ataque de subida de ficheros!</p>"; 48 | } 49 | } else { 50 | echo "File is not an image."; 51 | $uploadOk = 0; 52 | } 53 | } 54 |

?>
55 | 56 |

Result:

57 | 58 | 65 |
66 |
-------------------------------------------------------------------------------- /workshop/1-introduction.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |

6 | 9 |

10 |
11 |
12 |

When you are working in the server environment you are able to manipulate the information and files of the backend part. 13 | In PHP you have built-in methods that allows you to read, modify, create and delete files and directories

14 | 19 |
20 |
21 |
22 |
23 |

24 | 27 |

28 |
29 |
30 |

Some of the most used cloud tools to manage files are Google Drive, Dropbox, OneDrive, ... This tools 31 | must manipulate files in the backend part in order to simulate an environment similar to the one you have on your computer.

32 | File manager 33 |
34 |
35 |
36 |
37 |

38 | 41 |

42 |
43 |
44 |

In PHP there is a simple function to read a file and print their content. The readfile() function reads a file and writes it to the output buffer.

45 |

In this repository you have a file called "example-file.txt" that contains some plain text.

46 |

Code:

47 | 48 |
<?php

php echo readfile("./workshop/files/example-file.txt");

?>
49 | 50 |

Result:

51 | 58 |
59 |
60 |
61 |
62 |
63 |
-------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Manage files with PHP - Workshop 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

18 | Bootstrap 19 | Manage files with PHP - Workshop 20 |

21 |
22 |
23 | 39 |
40 |
41 |

Contents

42 | 43 |
44 |
45 |

Introduction

46 | Documentation 47 |
48 | 49 |
50 | 51 |
52 |
53 |
54 |
55 |

Open/Read

56 | Documentation 57 |
58 | 59 |
60 | 61 |
62 |
63 |
64 |
65 |

Create/Write

66 | Documentation 67 |
68 | 69 |
70 | 71 |
72 |
73 |
74 |
75 |

Upload

76 | Documentation 77 |
78 | 79 |
80 | 81 |
82 |
83 |
84 |
85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /assets/css/cheatsheet.css: -------------------------------------------------------------------------------- 1 | body { 2 | scroll-behavior: smooth; 3 | } 4 | 5 | /** 6 | * Bootstrap "Journal code" icon 7 | * @link https://icons.getbootstrap.com/icons/journal-code/ 8 | */ 9 | .bd-heading a::before { 10 | display: inline-block; 11 | width: 1em; 12 | height: 1em; 13 | margin-right: 0.25rem; 14 | content: ""; 15 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%25230d6efd' viewBox='0 0 16 16'%3E%3Cpath d='M4 1h8a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2h1a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H4a1 1 0 0 0-1 1H2a2 2 0 0 1 2-2z'/%3E%3Cpath d='M2 5v-.5a.5.5 0 0 1 1 0V5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H2zm0 3v-.5a.5.5 0 0 1 1 0V8h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H2zm0 3v-.5a.5.5 0 0 1 1 0v.5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H2z'/%3E%3Cpath fill-rule='evenodd' d='M8.646 5.646a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1 0 .708l-2 2a.5.5 0 0 1-.708-.708L10.293 8 8.646 6.354a.5.5 0 0 1 0-.708zm-1.292 0a.5.5 0 0 0-.708 0l-2 2a.5.5 0 0 0 0 .708l2 2a.5.5 0 0 0 .708-.708L5.707 8l1.647-1.646a.5.5 0 0 0 0-.708z'/%3E%3C/svg%3E"); 16 | background-size: 1em; 17 | } 18 | 19 | /* stylelint-disable-next-line selector-max-universal */ 20 | .bd-heading + div > * + * { 21 | margin-top: 3rem; 22 | } 23 | 24 | /* Table of contents */ 25 | .bd-aside a { 26 | padding: 0.1875rem 0.5rem; 27 | margin-top: 0.125rem; 28 | margin-left: 0.3125rem; 29 | color: rgba(0, 0, 0, 0.65); 30 | text-decoration: none; 31 | } 32 | 33 | .bd-aside a:hover, 34 | .bd-aside a:focus { 35 | color: rgba(0, 0, 0, 0.85); 36 | background-color: rgba(121, 82, 179, 0.1); 37 | } 38 | 39 | .bd-aside .active { 40 | font-weight: 600; 41 | color: rgba(0, 0, 0, 0.85); 42 | } 43 | 44 | .bd-aside .btn { 45 | padding: 0.25rem 0.5rem; 46 | font-weight: 600; 47 | color: rgba(0, 0, 0, 0.65); 48 | border: 0; 49 | } 50 | 51 | .bd-aside .btn:hover, 52 | .bd-aside .btn:focus { 53 | color: rgba(0, 0, 0, 0.85); 54 | background-color: rgba(121, 82, 179, 0.1); 55 | } 56 | 57 | .bd-aside .btn:focus { 58 | box-shadow: 0 0 0 1px rgba(121, 82, 179, 0.7); 59 | } 60 | 61 | .bd-aside .btn::before { 62 | width: 1.25em; 63 | line-height: 0; 64 | content: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='rgba%280,0,0,.5%29' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/%3e%3c/svg%3e"); 65 | transition: transform 0.35s ease; 66 | 67 | /* rtl:raw: 68 | transform: rotate(180deg) translateX(-2px); 69 | */ 70 | transform-origin: 0.5em 50%; 71 | } 72 | 73 | .bd-aside .btn[aria-expanded="true"]::before { 74 | transform: rotate(90deg) /* rtl:ignore */; 75 | } 76 | 77 | /* Examples */ 78 | .scrollspy-example { 79 | position: relative; 80 | height: 200px; 81 | margin-top: 0.5rem; 82 | overflow: auto; 83 | } 84 | 85 | [id="modal"] .bd-example .btn, 86 | [id="buttons"] .bd-example .btn, 87 | [id="tooltips"] .bd-example .btn, 88 | [id="popovers"] .bd-example .btn, 89 | [id="dropdowns"] .bd-example .btn-group, 90 | [id="dropdowns"] .bd-example .dropdown, 91 | [id="dropdowns"] .bd-example .dropup, 92 | [id="dropdowns"] .bd-example .dropend, 93 | [id="dropdowns"] .bd-example .dropstart { 94 | margin: 0 1rem 1rem 0; 95 | } 96 | 97 | pre { 98 | background-color: #d5d5d5; 99 | border-radius: 0.25rem; 100 | } 101 | 102 | /* Table */ 103 | 104 | td { 105 | vertical-align: middle; 106 | } 107 | 108 | /* Layout */ 109 | @media (min-width: 1200px) { 110 | body { 111 | display: grid; 112 | gap: 1rem; 113 | grid-template-columns: 1fr 4fr 1fr; 114 | grid-template-rows: auto; 115 | } 116 | 117 | .bd-header { 118 | position: fixed; 119 | top: 0; 120 | /* rtl:begin:ignore */ 121 | right: 0; 122 | left: 0; 123 | /* rtl:end:ignore */ 124 | z-index: 1030; 125 | grid-column: 1 / span 3; 126 | } 127 | 128 | .bd-aside, 129 | .bd-cheatsheet { 130 | padding-top: 4rem; 131 | } 132 | 133 | /** 134 | * 1. Too bad only Firefox supports subgrids ATM 135 | */ 136 | .bd-cheatsheet, 137 | .bd-cheatsheet section, 138 | .bd-cheatsheet article { 139 | display: inherit; /* 1 */ 140 | gap: inherit; /* 1 */ 141 | grid-template-columns: 1fr 4fr; 142 | grid-column: 1 / span 2; 143 | grid-template-rows: auto; 144 | } 145 | 146 | .bd-aside { 147 | grid-area: 1 / 3; 148 | scroll-margin-top: 4rem; 149 | } 150 | 151 | .bd-cheatsheet section, 152 | .bd-cheatsheet section > h2 { 153 | top: 2rem; 154 | scroll-margin-top: 2rem; 155 | } 156 | 157 | .bd-cheatsheet section > h2::before { 158 | position: absolute; 159 | /* rtl:begin:ignore */ 160 | top: 0; 161 | right: 0; 162 | bottom: -2rem; 163 | left: 0; 164 | /* rtl:end:ignore */ 165 | z-index: -1; 166 | content: ""; 167 | background-image: linear-gradient( 168 | to bottom, 169 | rgba(255, 255, 255, 1) calc(100% - 3rem), 170 | rgba(255, 255, 255, 0.01) 171 | ); 172 | } 173 | 174 | .bd-cheatsheet article, 175 | .bd-cheatsheet .bd-heading { 176 | top: 8rem; 177 | scroll-margin-top: 8rem; 178 | } 179 | 180 | .bd-cheatsheet .bd-heading { 181 | z-index: 1; 182 | } 183 | } 184 | --------------------------------------------------------------------------------