Chapters
21 Chapters
|
2:10:39
|
Login to bookmark this video
-
Course Code
Login or register to download the code!Compatible PHP versions: ^7.1.3
Login or register to download the code!Compatible PHP versions: ^7.1.3
-
This Video
Login or register to download the video!
Login or register to download the video!
-
Subtitles
Login or register to download the subtitles!
Login or register to download the subtitles!
-
Course Script
Login or register to download the script!
Login or register to download the script!
10.
Copying Files
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!
This tutorial works great with Symfony5!
What PHP libraries does this tutorial use?
// composer.json
{
"require": {
"php": "^7.1.3",
"ext-iconv": "*",
"aws/aws-sdk-php": "^3.87", // 3.91.4
"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.3.1
"stof/doctrine-extensions-bundle": "^1.3", // v1.3.0
"symfony/asset": "^4.0", // v4.2.5
"symfony/console": "^4.0", // v4.2.5
"symfony/flex": "^1.9", // v1.21.6
"symfony/form": "^4.0", // v4.2.5
"symfony/framework-bundle": "^4.0", // v4.2.5
"symfony/property-access": "4.2.*", // v4.2.5
"symfony/property-info": "4.2.*", // v4.2.5
"symfony/security-bundle": "^4.0", // v4.2.5
"symfony/serializer": "4.2.*", // v4.2.5
"symfony/twig-bundle": "^4.0", // v4.2.5
"symfony/validator": "^4.0", // v4.2.5
"symfony/web-server-bundle": "^4.0", // v4.2.5
"symfony/webpack-encore-bundle": "^1.4", // v1.5.0
"symfony/yaml": "^4.0", // v4.2.5
"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.5
"symfony/dotenv": "^4.0", // v4.2.5
"symfony/maker-bundle": "^1.0", // v1.11.5
"symfony/monolog-bundle": "^3.0", // v3.3.1
"symfony/phpunit-bridge": "^3.3|^4.0", // v4.2.5
"symfony/stopwatch": "4.2.*", // v4.2.5
"symfony/var-dumper": "^3.3|^4.0", // v4.2.5
"symfony/web-profiler-bundle": "4.2.*" // v4.2.5
}
}
What JavaScript libraries does this tutorial use?
// package.json
{
"devDependencies": {
"@symfony/webpack-encore": "^0.27.0", // 0.27.0
"autocomplete.js": "^0.36.0",
"autoprefixer": "^9.5.1", // 9.5.1
"bootstrap": "^4.3.1", // 4.3.1
"core-js": "^3.0.0", // 3.0.1
"dropzone": "^5.5.1", // 5.5.1
"font-awesome": "^4.7.0", // 4.7.0
"jquery": "^3.4.0", // 3.4.0
"popper.js": "^1.15.0",
"postcss-loader": "^3.0.0", // 3.0.0
"sass": "^1.29.0", // 1.29.0
"sass-loader": "^7.0.1", // 7.3.1
"sortablejs": "^1.8.4", // 1.8.4
"webpack-notifier": "^1.6.0" // 1.7.0
}
}
42 Comments
Nice lesson. In regards to setting paths to images out of the build directory, is there anything similar we can do when linking images from style-sheets? Many thanks!
Hey Kensley,
Yes, actually you can point any image at any directory in your css or scss files. You can use whether relative or absolute path - the only requirement is that the path should be valid. Then Encore will notice it and copy to your build directory, and also will *rewrite* the paths in your css/scss files for you. So, make sure you're using correct paths to images, and it just should work :)
Cheers!
For some reason the (image)files referenced in my templates <img>-Tags are not getting copied. Files referenced in CSS work just fine. My img-tags are looking like this:
<img src="{{ asset('build/images/filename.ext') }}" alt="...">I'm not a 100% sure if I somehow changed the basepath for the Twig asset-function. But there ist nothing showing in framework.yaml or twig.yaml.
The resulting path is
https://localhost/build/images/correct_path/filename.extand that is fine aswell. Only the images used in the templates are not getting copied from my (encore) assets folder to build.Hey Eric!
Yea... this is the "expected" behavior 🙃. Encore parses your CSS files to know which images it needs to copy. But it does not parse your Twig templates to know that it should copy these files. The two solutions for this are:
A) Use
copyFiles()from Encore. Then you should be able to reference those. If you're trying to figure out exactly which path to use inasset(), look atpublic/build/manifest.json, find the file, and use the "key".B) Randomly import the file you want to reference from a JS file... then don't use the value. Importing it will be enough to make that file be copied. Then, use the same trick about
manifest.json.Let me know if that helps!
Cheers!
Hey Ryan, thanks for the reply. I had added
copyFiles(), that's why I was so confused. I missed to mention that in my question. I also missed to restart Encore obviously. Now it all works just fine... :DHey Eric!
Ah, I'm just happy you've got it working 😎.
Cheers!
I got an
Error: Install file-loader to use copyFiles(), but luckily it suggested a fixyarn add file-loader@^6.0.0 --devwhich worked. Easy peasy! I guess it got changed at some point.Hey Javier Quintana!
Thanks for sharing that - we'll add a note! When Encore went 1.0, we changed how assets are imported, which means that file-loader doesn't come automatically anymore (hence, you need to install it). But I love that the error was so clear!
Cheers!
Hello SF! Fantastic tutorial
I just didnt get the point of getting hash on my picture's names :(
Could you briefly explain it ?
Hey Akavir S.
The whole point of using a hash as part of the file name is just for caching purposes. If you didn't change your image, then its name will be the same but whenever you change it, it will get a new name as soon as you compile your assets, so then, a browser will think it's a new image and will download it (and actually it is a new image)
Cheers!
Cool! Can we do the same (add hash to the final name of the file) with CSS and JS files?
Hey Anton Bagdatyev
Great question! Of course we can, and you will learn it at the end of this course! So keep learning!
Cheers!
Cool! Thank you!
Hi @all
I have the next problem. A CSS file with:
When I use the copyFiles funcionality in the next way
It works changing the CSS:
I want to use versioning for that:
But then from CSS I don't know where the asset version file was created
How can I fix it?
Thanks
Hey Francisco C.
I think you just have to point to the "from" path, e.g.
./assets/admin/media/bgand Webpack should take care of the rest. Let me know if it worked :)Cheers!
Hey MolloKhan
It doesnt work.
My from path is already set to from: './assets/admin/media/bg' pero the CSS file points to bg-default.jpg
Inside the "to" folder 'build/admin/media/bg/' the file is bg-default.XXXXXXXX.jpg
Any ideas?
Ah ok, let's try something. In your CSS class, point directly to the "from" path. e.g.
I think, if you do that, Webpack will take care of the rest. Oh, but I think you have to be using SASS instead of CSS files
Hi again!
So, now I have a different problem...In one part of my app, I'm creating a portion of a page using a php template (an idea I got from your "JavaScript for PHP Geeks" tutorial"), which includes image tags from my static image directory. Unfortunately, I can't get the images to render.
The code looks something like this:
Before adding the hash to my static images, data.image was "/build/static/image1.png". That doesn't work now, so I figured a relative path was needed. I tried paths relative to the php app and templates relative to the php function called by the Ajax call, but neither worked. I'm sure there is a way to do this, I just can't figure it out.
Can you show me the way?
Hey Dan_M!
Cool question :). The answer... depends a bit about the nature of these images. This
get_imageendpoint... is it returning an image path to some dynamic (e.g. uploaded?) icon image? Or is it literally just returning the path to some "static" asset that's committed to your repository? I think it's the second (because you mentioned the path is/build/static/image1.png). If so, follow-up question: does thisget_imageendpoint always return the exact same icon path? Or is this... dynamic (?) based on the user login or something different?And, in case you have the simplest situation (where you just want to get the image path to a static, committed image in your project), i'll give you the answer :). Let's assume the source, committed image (before Encore copies it) is
assets/images/image1.pngand you're JavaScript file lives atassets/js/app.js. In that case, the solution is this:Let me know if this helps... or if you have a more complex situation :).
Cheers!
Hey Ryan,
Thanks for that answer, but my situation is a little more complicated than that. Based on user input, the get_image endpoint returns the path to one of five "static" assets that are committed to my repository. Because the jquery app does not know at compile time which image path will be returned, I can't import and display the image as directly as you showed.
So...I can't wait for the more complex answer!
Cheers!
Hey Dan_M!
Ah... ok! In that case, the trick to getting this right will all be in the controller for that
get_imageAJAX call: it needs to return the full, final URL to the image so that your JavaScript can "dumbly" just print it. It will probably be something like this:There are two keys here:
1) That
Packagesservice is basically the way that you call theasset()function (the one you normally use in Twig) from inside a controller. That's important because, assuming your app is setup correctly, the asset() function is smart enough to look in the Encore manifest.json file to get the final path to the image (including a version hash if you enable versioning).2) Am I assuming correctly that these static files are copied via
copyFiles()? The second key is what string to pass to thegetUrl()function. The easiest way to see what path you should pass here is to open uppublic/build/manifest.jsonand find the "image1.png" item in there and use whatever its "key" is. You should find something that looks something like"static/image1.png": "/build/static/image1.png". Whatever the key on the left is, that's what you should pass togetUrl().Let me know how that goes!
Cheers!
Ryan,
That was the missing link! I had no idea there was an asset() function that I could use outside of Twig. It works like a charm now.
Thanks!
The new Webpack Encore is AWESOME! Reducing my build time from 6 minutes to 10 seconds makes my work so much easier. Thanks!
I have a slight problem with hashed static files. They work great with Twig's asset() function, but I have one file that I call as a background by css:
<br />#container {<br /> min-height:100vh;<br /> position:relative;<br /> background: black url('/build/static/background.jpg') center top no-repeat;<br />}<br />How can I reference a static file from css?
Thanks!
Hey Dan,
That sounds very cool! About your problem - the easy fix! You just need to specify a relative path to the image in your CSS file - Webpack will automatically rewrite the relative path to the proper path with hash from the build/ directory. So, for example if you have this structure:
Then, you just need to specify path like "../images/static/background.jpg", i.e.:
Cheers!
Thanks for the explanation Victor!
I see now that the issue was discussed two chapters back. I guess I missed it!
Hey Dan,
Thanks for your feedback! Glad it works for you now.
Cheers!
I have small issue with font awesome, I have pro version and I do not understand how it is, that when I use free version installed from npm it works (fonts are copied) and when I use my own then it doesn't work (fonts are not copied...). How does it work?
Hey Krzysztof K.
Why you don't use Font awesome PRO from npm? In oficial fontawesome docs there are section how to instal PRO version with your personal token.
Cheers!
Thanks Vladimir, I will check it. But I am really curious, why this works like that, I have checked npm folder for that package, but there wasn't anything special.
Difficult to say, it depends on how you are including you font-awesome version. Are you using compiled css or it's scss version? probably your fonts files are placed in wrong directory, or you misconfigured fonts directory var, Fonts should be copied automatically.
Cheers.
Hello guys,
Is there a way to make phpstorm not be angry about the
{{ asset('build/images/alien-profile.png') }}?Is there a webpack plugin or something to fix it?
Here is the kludge that I am using for the dev environment. I modified the
webpack.config.jslike this:`
const Encore = require('@symfony/webpack-encore');
const assetDestinationProd = '[name].[hash:8].[ext]';
const assetDestinationDev = '[name].[ext]';
const destinationFilename = Encore.isProduction() ? assetDestinationProd : assetDestinationDev;
Encore
...
...
`
I got this idea from https://github.com/Haehnchen/idea-php-symfony2-plugin/issues/1020
Hey Scottie,
Thanks for sharing this example, but it really looks complicated. I just donwloaded the course code of this tutorial, went to the finish/ directory, ran "yarn install" & "yarn watch" and when "ls -l public/build" - I didn't see any hash in files, here's my output:
I only see hashes when build assets for production, i.e run "yarn build". So, probably some misconfiguration on your side.
Cheers!
The hash files in this case are in the images folder.
Hey Scottie,
Ah, sorry, now I see! Totally makes sense, thanks for clarification and shared solution ;)
Cheers!
Cool, thanks for sharing it!
Hey Scottie,
Yes, there's a trick with it... Well, actually, not with asset() function in particular but with paths to files. First of all you need to install and *enable* Symfony Plugin. In its preferences, specify "public" (or the public directory for your Symfony project - it's web for old Symfony versions). And it should help IIRC. You can find how to do it in our free course about PhpStorm: https://symfonycasts.com/sc... .
Another trick is right click on your public/ folder and in context menu choose "Mark directory as" -> "Resource route". After this PhpStorm will check all paths relative to the public folder and if it found a file - it won't highlight it.
Cheers!
Thank you for the reply. But the problem is that I am using the image source to filename-with-hash conversion provided by the manifest.json. The link specified does not actually have a file. For example, using this tutorial, in the show.html.twig file, you will find
{{ asset('build/images/alien-profile.png') }}. But the actual file isbuild/images/alien-profile.da9d186f.png. The manifest.json has the mapping for this conversion. And, because the file does not exist, phpstorm is "angry". I was hoping there might be a plugin to read the manifest.json to resolve this.Hey Scottie,
Actually, you can enable versioning for production only and disable it for development, then you won't have this problem. Check the last chapter: https://symfonycasts.com/sc... - see ".enableVersioning(Encore.isProduction())" option. It should fix the problem you have :)
Cheers!
Hey Scottie,
Ah, now I see! It wasn't clear enough in your first comment :) Unfortunately, I don't know any plugin that would help with it. :/ Probably a good idea to suggest such improvement to Symfony Plugin.
Cheers!
Hi, about this mapping between project filename's path and build filename's path can cause a overhead? I mean, it become slower? Or accessing manifest.json from file system are fast enough to use this approach?
Hey Marcel D.
It may cause an overhead but just at build time. Another thing to consider is that you will have duplicate images on your system, so if your production server is very low on disk space it might be a problem but I would not worry too much.
Cheers!
"Houston: no signs of life"
Start the conversation!