Chapters
40 Chapters
|
4:39:58
|
Login to bookmark this video
-
Course Code
Subscribe to download the code!Compatible PHP versions: ^7.1.3
Subscribe to download the code!Compatible PHP versions: ^7.1.3
-
This Video
Subscribe to download the video!
Subscribe to download the video!
-
Subtitles
Subscribe to download the subtitles!
Subscribe to download the subtitles!
-
Course Script
Subscribe to download the script!
Subscribe to download the script!
08.
Upload Field Styling & Bootstrap
Scroll down to the script below, click on any sentence (including terminal blocks) to jump to that spot in the video!
Subscribe to jump to this part in the video!
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
This tutorial is built on Symfony 4 but works great in Symfony 5!
What PHP libraries does this tutorial use?
// composer.json
{
"require": {
"php": "^7.1.3",
"ext-iconv": "*",
"aws/aws-sdk-php": "^3.87", // 3.87.10
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"doctrine/annotations": "^1.0", // 1.10.1
"doctrine/doctrine-bundle": "^1.6.10", // 1.10.2
"doctrine/doctrine-migrations-bundle": "^1.3|^2.0", // v2.0.0
"doctrine/orm": "^2.5.11", // v2.7.2
"knplabs/knp-markdown-bundle": "^1.7", // 1.7.1
"knplabs/knp-paginator-bundle": "^2.7", // v2.8.0
"knplabs/knp-time-bundle": "^1.8", // 1.9.0
"league/flysystem-aws-s3-v3": "^1.0", // 1.0.22
"league/flysystem-cached-adapter": "^1.0", // 1.0.9
"liip/imagine-bundle": "^2.1", // 2.1.0
"nexylan/slack-bundle": "^2.0,<2.2.0", // v2.1.0
"oneup/flysystem-bundle": "^3.0", // 3.0.3
"php-http/guzzle6-adapter": "^1.1", // v1.1.1
"phpdocumentor/reflection-docblock": "^3.0|^4.0", // 4.3.0
"sensio/framework-extra-bundle": "^5.1", // v5.2.4
"stof/doctrine-extensions-bundle": "^1.3", // v1.3.0
"symfony/asset": "^4.0", // v4.2.3
"symfony/console": "^4.0", // v4.2.3
"symfony/flex": "^1.9", // v1.21.6
"symfony/form": "^4.0", // v4.2.3
"symfony/framework-bundle": "^4.0", // v4.2.3
"symfony/property-access": "4.2.*", // v4.2.3
"symfony/property-info": "4.2.*", // v4.2.3
"symfony/security-bundle": "^4.0", // v4.2.3
"symfony/serializer": "4.2.*", // v4.2.3
"symfony/twig-bundle": "^4.0", // v4.2.3
"symfony/validator": "^4.0", // v4.2.3
"symfony/web-server-bundle": "^4.0", // v4.2.3
"symfony/yaml": "^4.0", // v4.2.3
"twig/extensions": "^1.5" // v1.5.4
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.0", // 3.1.0
"easycorp/easy-log-handler": "^1.0.2", // v1.0.7
"fzaninotto/faker": "^1.7", // v1.8.0
"symfony/debug-bundle": "^3.3|^4.0", // v4.2.3
"symfony/dotenv": "^4.0", // v4.2.3
"symfony/maker-bundle": "^1.0", // v1.11.3
"symfony/monolog-bundle": "^3.0", // v3.3.1
"symfony/phpunit-bridge": "^3.3|^4.0", // v4.2.3
"symfony/stopwatch": "4.2.*", // v4.2.3
"symfony/var-dumper": "^3.3|^4.0", // v4.2.3
"symfony/web-profiler-bundle": "4.2.*" // v4.2.3
}
}
22 Comments
A small contribution:
The javascript code to change the placeholder don't always work, when click on browse and dont actually choose a file the place holder wont change because
inputFile.files[0].nameis not define and will throw an exception I fixed it by counting the number of files selected and if its zero then put "select a file instead of the file name.Bonus, for a multiple file field you should use this one :
<b>It Rocks #RyanVoice
</b>
Hey Mamour W.!
Nice catch on that edge case! I see it now: if I (A) select a file and then (B) go back and select NO file, then the
changeevent is triggered, but the files are empty. Excellent catch - thanks for sharing that :).😂
Cheers!
Is there a way to get the upload field to display the value of a currently uploaded image (which, in this case, would be a string representing an image path, in my case), before clicking "Choose File" and replacing the currently uploaded image? Can a FileType field store a string value for a currently uploaded URL?
Hey @Jeff!
Hmm. Part of this answer depends on exactly WHERE you want to show the filename. Fore example, on solution would be to do a "form theme" for just this one field - e.g. - https://symfonycasts.com/screencast/symfony-forms/custom-field-theme - or render the field a bit more manually - something like this:
(the trick here is getting all the styling / CSS classes correct since you're taking more control over things).
OR, you might want to do something a bit more similar to what we do in the video: where we replace the
labelwith the current filename. In that case, it can be done when rendering the field:Let me know if that helps :)
Cheers!
$(inputFile).parent().find('.custom-file-label').html()<br />Shouldn't that be
.text()?Hey there!
Yea, I think you're right, since we're not injecting any HTML content, it would be safer to use the
.text()functionCheers!
Really thanks, save my day
4:15 https://hackernoon.com/why-...
Hey TomaszGasior!
You're right! But in this case, because I'm writing this code in my template (and not in a system where it will be compiled/transpiled with Babel), I'm being conservative: about 5% of browsers still don't support "var". So it's "probably" safe to use on my sites... but I'm being conservative. Of course, inside a Webpack-powered system, it's fine because if you need to support older browser, you can allow it to rewrite that code for you.
Cheers!
Probably you are right but please consult https://caniuse.com/#feat=let . For my country it shows 95% coverage. :)
Yea, you may want to ignore that missing 5% but as Ryan said, the best way would be to use Encore Webpack and let it compile your javascript
Hello Ryan,
sorry to disturb.
I would like to customize also the label of the file field (ie the "Browse" button) changing the text and adding a on hover effect, but I have big difficulties in finding where and what should change.
can you please just give me a hint in the right direction?
thank you for your attention and for the great job you do!
cheers
Hey chieroz
Nice question! You made me dig :)
What's happening here is that Bootstrap4 adds the text of the button via CSS. If you inspect that element, you will notice that the button is added via a pseudo-element (check the "custom-file-label" CSS class). What you can do is to override it by defining your own CSS rules for that class, or do it via Javascript (ugly)
Cheers!
Hello!
I have added as mimeTypes "text/csv" but validation failed even if the file is a csv file.
Error displayed:
The mime type of the file is invalid ("text/plain"). Allowed mime types are "text/csv".If I dd my $uploadedFile variable, I can see that the mimeType value is set to "text/csv". Any idea?
Thx!
Hey be_tnt
How are you uploading your file? Remember that you need to specify the encryption type of your form as
multipart/form-data. Also, just in case, double check your submitted file :)Cheers!
Hi Diego,
I am using the FileType element so the multipart/form-data is added automatically to the form.
Cheers!
Oh, I see, that's even better :)
but then, why it's not working? Are you submitting your form via JS? I may need to see your code, if you can upload it to Github, so I can give it a look
Hello!
I do not have the code on Github. Let me try to give you as much information I can :)
In my controller:
`public function upload(Request $request, UploaderHelper $uploaderHelper, ValidatorInterface $validator)
In the form type:
public function buildForm(FormBuilderInterface $builder, array $options)
` {
In the view:
`{{ form_errors(form) }}
{{ form_start(form) }}
{{ form_end(form) }}`
I also tried to add the constraint about extension in the buildForm function. Same result.
Thx in advance for your help!
Hmm, everything looks good... the only thing I can tell is that you didn't call
{{ form_start(form) }}on your template, if that doesn't fix it, we are in troubles haha. Try clearing the cache, submit another csv file, double check your imports (you may have chosen a wrong one)Cheers!
Hello!
The form_start call is in the template :) When I dump the information about the uploaded file (dd($uploadedfile)), it displayes:
UploadedFile^ {#64 ▼<br /> -test: false<br /> -originalName: "leads_solvary.csv"<br /> -mimeType: "text/csv"<br /> -error: 0<br /> path: "/private/var/folders/c_/t_wbmqbd3dz003yhxr8fgsqw0000gn/T"<br /> filename: "phpHshBYz"<br /> basename: "phpHshBYz"<br /> pathname: "/private/var/folders/c_/t_wbmqbd3dz003yhxr8fgsqw0000gn/T/phpHshBYz"<br /> extension: ""<br /> realPath: "/private/var/folders/c_/t_wbmqbd3dz003yhxr8fgsqw0000gn/T/phpHshBYz"<br /> aTime: 2019-07-18 16:10:23<br /> mTime: 2019-07-18 16:10:23<br /> cTime: 2019-07-18 16:10:23<br /> inode: 8844478793<br /> size: 1889<br /> perms: 0100600<br /> owner: 501<br /> group: 20<br /> type: "file"<br /> writable: true<br /> readable: true<br /> executable: false<br /> file: true<br /> dir: false<br /> link: false<br />}As you can see, the mimeType is "text/csv". But the validation failed saying that I uploaded a "text/plain" file instead of a csv ...
By the way, in the mime types, I have added pdf ("application/pdf", "application/x-pdf") and this is working. So the problem is really with csv.
Any idea?
Hey be_tnt!
Nice just checking into this and dumping the UploadedFile object. When it comes to asking "What is the mime type of this file?" there are *two* places that information can come from. First, when the user submits the form, *their* browser sends information that says "this is text/csv". But, this can't be trusted... as a user could "spoof" this and send anything. So, second, what Symfony can do (and *does* do) is look at the uploaded file's contents and try to guess the mime type. I believe this what you're seeing: the user's browser is saying "Hey! This is text/csv", but then Symfony looks inside of the file and just sees "text/plain"... probably because CSV basically is a text/plain format (or very similar).
To solve this, I would just allow text/plain. If you really wanted to make sure that *only* CSV files (and not just random text files) were uploaded, you could add your own next layer of validation that tried to parse the file's contents as CSV and creates a validation if it fails (that would be a custom validator).
Let me know if this helps!
Cheers!
Thx for your answer. It helps a lot to understand the validation process. I will have to parse the csv file in my project so the latest validation step will be done there :)
Thx again!
"Houston: no signs of life"
Start the conversation!