How to copy images to web folder with assetic - php

I can't believe that I'm not able to google this...
So, I have a symfony2 application, and I installed jQuery UI with Composer. That means i have project structure like this:
/app/
/src/
/vendor/components/jqueryui/
/web/
I have assetic set up to copy js/css files from the vendor folder to web. That works fine. Config:
assetic:
assets:
javascripts:
inputs:
- %kernel.root_dir%/../vendor/components/jquery/jquery.js
- %kernel.root_dir%/../vendor/components/jqueryui/ui/jquery-ui.js
- %kernel.root_dir%/../vendor/components/jqueryui/ui/i18n/jquery.ui.datepicker-cs.js
stylesheets:
inputs:
- %kernel.root_dir%/../vendor/components/jqueryui/themes/redmond/jquery-ui.css
filters: cssrewrite
After assetic:dump i have
/web/js
/web/css
cssrewrite rewrites images/image.png to ../images/image.png. I guess that's ok, assumes a /web/images directory with said images.
Now the question is: How do I copy the images from /vendor/components/jqueryui/themes/redmond/images to /web/images?
Or is there another best practice to do that? Excuse me if it's and obvious thing, I'm a .NET guy, just trying out PHP.

My answer probably isn't spot-on because I haven't tried this with vendor files but this is what worked for me:
app/console assets:install
It copies all of your public resources to your web directory.
This answer by user1814739 helped me understand this and may provide additional information for you.
Also consider this advice from the Symfony Blog:
Although developers usually execute the command without any option, most of the time it's better to execute it with the --symlink option. This makes a symbolic link of your assets instead of actually copying their files. This means that any change in the content of the web assets will have immediate effect in the application.

Related

Using webpack with an existing PHP and JS project

I have an existing PHP project with jquery and bootstrap, not using any front-end framework.
I am trying to use webpack module bundler in order to create a single entry point for my project resources, manage js dependencies with node js package manager, run tasks as minify js css, image re-size...etc. And improve the browser loading time required to load a single page.
I came across the webpack tutorials and got to install it and install its dev-server, but the problem is that I am not able to understand how I will convert all my current js scripts and css links in the project (where I have a lot of jquery and CSS libraries used to provide multiple features in the project) to use webpack.
Do I have to rewrite all my JS and CSS files in a way that suits webpack? How do I make a successful migration?
Besides, I am not able to run my current php application on the webpack dev-server, is it meant to run there in the first place? It is only listing the directories of the project in the meantime.
I have created a test index.js file and used the following webpack configuration:
var path = require('path');
var webpack = require('webpack');
module.exports =
{
entry: [
'./public/js/index.js',
'webpack/hot/dev-server',
'webpack-dev-server/client?http://localhost:8080'
],
plugins: [
new webpack.HotModuleReplacementPlugin()
],
output: {
path: path.join(__dirname, "public/dist/js"),
publicPath : "http://localhost:8080/my_proj/public/dist/js",
filename: "bundle.js"
}
};
I added the bundle.js to my script loads just for testing as follows hoping that the application will run on the webpack dev-server:
<script type="text/javascript" src="public/dist/js/bundle.js"></script>
<script type="text/javascript" src="public/js/jquery.min.js"></script>
<script type="text/javascript" src="public/js/jquery.migrate.js"></script>
<script type="text/javascript" src="public/js/jquery.bxslider.min.js"></script>
<script type="text/javascript" src="public/js/jquery.appear.js"></script>
<script type="text/javascript" src="public/js/jquery.countTo.js"></script>
<script type="text/javascript" src="public/js/bootstrap.js"></script>
Please help me understand the concept here and how can I make this migration successfully?
First, to answer your smaller questions:
No, you're not supposed to run your PHP application through a webpack dev server. Explained in the Live Reloading section below.
No, you won't have to rewrite your assets. Probably. See the CSS and Edge Cases sections below.
Disclaimer: I'll only take on a small fraction of your question. Its scope is just way too broad to be packed into just one StackOverflow answer.
I will only get in touch with
setting up a development and a production environment for webpack
bundling your first JavaScript
which should give you a foundation to build on.
I'll also mention some things you may want to add and link according resources to read through.
So, let's go.
Requirements
I assume you have Node.js and npm installed on your machine and roughly know how to use them.
I also assume you have webpack and webpack-cli installed as (dev) dependencies of your project (not just globally):
npm install --save-dev webpack webpack-cli
Update: Earlier versions of this answer did not require installing webpack-cli. As of version 4 (February 2018), webpack's CLI resides in its own package, hence the additional required package.
Set up development and a production workflow
You usually want to do stuff differently in development than in production (minifying in production, live-reloading in development, ...)
To achieve that, we'll want to split up our configuration files.
Prepare the directory structure
Let's agree to ignore the webpack config from your question. We'll start all over, we'd have to change almost everything anyway.
First, create a build folder inside your project root. Build-related stuff will go there, since we don't want to pollute your project's root folder with config files. (You're free to name this folder differently, but keep track of that during this tutorial.)
Create a config.base.js, a config.production.js and a config.development.js file inside that folder.
Great, we have config files for two build chains now. The configurations are still empty though, so let's now fill them with some basic logic.
Install webpack-merge
But first, we'll need to install webpack-merge.
npm install --save-dev webpack-merge
This package allows us to deeply merge multiple webpack configurations. We want to use it to create webpack configurations depending on our current environment.
Adjust your configuration
Now adjust your build/config.base.js:
module.exports = {
// We'll place webpack configuration for all environments here
}
The file does obviously just export an empty object right now, but we'll need that for the following steps.
Put this code in your build/config.production.js:
const { merge } = require('webpack-merge')
module.exports = merge(require('./config.base.js'), {
mode: 'production'
// We'll place webpack configuration for production environment here
})
And almost the same code goes into your build/config.development.js:
const { merge } = require('webpack-merge')
module.exports = merge(require('./config.base.js'), {
mode: 'development',
watch: true
// All webpack configuration for development environment will go here
})
I guess it's pretty intuitive what this does:
Using webpack with the config.development.js configuration will fetch the common configuration and merge its own config declaration in.
Update: The mode option in the above config files was added in webpack 4 (released February 2018). It sets a bunch of sensible defaults for development and production bundles.
Now running the process would look like this from the command line:
npx webpack --config build/config.development.js
# If the above doesn't work, you probably have an older version of npm (< 5.1) installed
# While npx is a really great tool, you can of course still call the path of the webpack executable manually:
node_modules/.bin/webpack --config build/config.development.js
...and vice versa for the production environment.
That command is rather clunky to use, but no worries, we'll address that later.
Make some helper files
There are information we'll be wanting to centralize to make them easily exchangeable. File paths are such a thing. So let's extract them.
Create a paths.js in your build folder and have it export some paths we'll want to use later:
const path = require('path')
// I'm really just guessing your project's folder structure from reading your question,
// you might want to adjust this whole section
module.exports = {
// The base path of your source files, especially of your index.js
SRC: path.resolve(__dirname, '..', 'public'),
// The path to put the generated bundle(s)
DIST: path.resolve(__dirname, '..', 'public', 'dist'),
/*
This is your public path.
If you're running your app at http://example.com and I got your DIST folder right,
it'll simply be "/dist".
But if you're running it locally at http://localhost/my/app, it will be "/my/app/dist".
That means you should probably *not* hardcode that path here but write it to a
machine-related config file. (If you don't already have something like that,
google for "dotenv" or something similar.)
*/
ASSETS: '/dist'
}
Create aliases
As mentioned above, we could technically run our build chain in development mode like this:
npx webpack --config build/config.development.js
That's an uncomfortably verbose command though, so let's change that.
It's way more convenient to run your build process via npm scripts. Add one script per environment to your package.json like this:
{
"scripts": {
"dev": "webpack --config build/config.development.js",
"prod": "webpack --config build/config.production.js"
}
}
Now you can run your build chains with npm run dev resp. npm run prod – which is much easier to memorize and faster to type.
...as soon as there'es anything to build, of course.
Bundle JavaScript
Okay, that was actually a fair amount of work without achieving too much so far.
So let's start with something more exciting: We'll define a JavaScript entry point.
Define an entry point
Put the following code into your build/config.base.js (replacing the existing code entirely):
const path = require('path')
const { SRC, DIST, ASSETS } = require('./paths')
module.exports = {
entry: {
scripts: path.resolve(SRC, 'js', 'index.js')
},
output: {
// Put all the bundled stuff in your dist folder
path: DIST,
// Our single entry point from above will be named "scripts.js"
filename: '[name].js',
// The output path as seen from the domain we're visiting in the browser
publicPath: ASSETS
}
}
Create the JavaScript file
The above configuration expects an index.js to live in your SRC/js folder (as defined in the build/paths.js).
Let's create that file with the following content:
import './jquery.min.js'
import './jquery.migrate.js'
import './jquery.bxslider.min.js'
import './jquery.appear.js'
import './jquery.countTo.js'
import './bootstrap.js'
As you can see, the index.js just imports all of the files you want to use.
If you now run
npm run prod
from your terminal, a scripts.js file will be created in your DIST folder. You can include that into your markup with a plain ol' <script> tag.
Congratulations, you've got a working webpack setup!
Dive deeper
This mini-tutorial really just scraped the surface of what you can do with webpack. It gives you a pretty solid foundation for your configuration which you now can fill with whatever you need. And that will actually be quite a lot of stuff.
I'll list a few more things you may want to enhance, with some links to read through.
webpack Concepts
If you want to use webpack, it can be hard to do so if you don't know about its underlying concepts. Juho Vepsäläinen created a great guide on getting started with webpack which helped me a whole lot. He's also a webpack core contributor so you can be sure he knows what he's talking about.
Especially loaders are a concept you'll really need to know.
Many of the hints on this list are also explained there.
Read more: SurviveJS – webpack tutorial
Code Splitting
It does what the name's saying: You might not want to pack all your JavaScript into one bulky output file.
It's a job webpack does for you to split off parts of your bundle which you only need on certain pages of your application.
Also, depending on how frequently you're working on your project's JavaScript, it might be a good idea to split off third party code from your bundle for caching purposes.
Read more: webpack Documentation – Code Splitting
Caching
You may want to enhance your site's caching behaviour by adding a hash to your bundled file names which depends on their content. This will create (for example) a script.31aa1d3cad014475a618.js instead of a scripts.js.
That file can then be cached indefinitely because as soon as its contents change, the file name will change as well.
Your PHP code might then use the webpack-manifest-plugin to gain access to the generated file names.
Read more:
Immutable Caching on how to cache your bundles forever
webpack Documentation – chunkhash on how to enrich your bundle file names with hashes
webpack-manifest-plugin on how to generate a manifest.json containing the file names of your current bundle
Transpiling
In case you want to use modern ES2015 code in your site's JavaScript (and are targeting non-evergreen browsers), you'll want to transpile them down to regular ES5. (If the term "ES2015" does not make any sense to you, you're most likely not using it and can ignore this paragraph.)
Read more: babel-loader – A loader that runs Babel on your scripts
CSS
There are webpack loaders for CSS. And Sass. And PostCSS. Whatever you need.
And since you're probably not planning to include your CSS via <script> tags, get to know the Extract Text Plugin to generate actual .css files.
Update: The Extract Text Plugin is very established. However, it's actually a kind of hack: It generates .css files even though webpack only knows JavaScript as its target language.
However, this is no longer true as of webpack 4. There's now a system to define arbitrary module types, including CSS.
Long story short: Expect native CSS support in webpack to replace Extract Text Plugin some time soon.
Hint: Paths
I'll mention this because this was a real pain point for me until I realized how webpack works here:
Be aware that webpack will recognize your url(...) statements and try to resolve them relative to your source files.
This means, your source file public/css/main.css:
body {
background: url('../img/bg.jpg');
}
if your output path is public/dist/css/bundle.css, will be transformed to:
body {
background: url('../../img/bg.jpg');
}
Read more:
style-loader and css-loader – you'll hands down need those.
extract-text-webpack-plugin
Minifying
Update: Since webpack 4 was released in February 2018, this section is rather obsolete. Setting the new mode option to "production" now automatically applies JavaScript minification.
There is a Terser plugin for webpack to minify your JavaScript. Minifying CSS is a feature already builtin to the css-loader plugin mentioned above.
Read more: Terser webpack Plugin
Image Optimization
webpack is a bundler, not a task runner. Thus, image optimization is not a genuine webpack task. You'd probably be better off using an actual task runner or just defining some npm scripts for this.
This does not mean webpack is not capable of doing this. There are plugins for pretty much everything.
Read more:
imagemin can minify images pretty nicely on its own.
imagemin-webpack-plugin will integrate that process into your webpack build chain.
Live Reloading
Your problems with live reloading have a pretty simple cause: a webpack dev server is just a simple Node.js server serving only static files.
For you're case, webpack-dev-server probably is the wrong tool at all. Try webpack-livereload-plugin instead for a live reloader that you can just include via <script> tag.
Read more: webpack-livereload-plugin
Source Maps
Update: As of webpack 4 (released in February 2018), source maps are automatically generated when the new mode option is set to "development".
By all means, use source maps. They'll make your work with bundles so much easier you'll want to cry.
Read more: webpack Documentation – Source Maps
Edge Cases
Usually, all your existing scripts you'll process with webpack should be running just fine.
The only exception that comes to my mind right now would be regarding global entities.
Look at the following code:
function myFunc () {
console.log('I exist!')
}
This code in a plain JavaScript file would make myFunc available everywhere in your JS code. But since webpack bundle code is wrapped inside callback functions (and thus leaving the global scope), there won't be any access to that function anymore.
Third party libraries should not be a problem there, they usually assign their globals to the window object directly, but if you've already written JS code in your project, you should be aware of that.
Automate!
You'll want to automate as much of your workflow as possible.
Consider running npm run prod via a git hook before pushing / after pulling.
Based on the existing vue-templates and and the answer from #Loilo I made a vue template you can install with vue-cli. This template jumpstarts you for a vue application you can extend with or integrate in you existing environment.
npm install -g vue-cli
vue init delcon/webpack-simple my-project
cd my-project
npm install
devwatch:
This template has an additional run devwatch option that watches for filechanges instead of using the webpack-dev-server. This makes it usable for any existing webserver enviroment.
npm run devwatch
dev:
to run it with the default webpack-dev-server, remove <script src="http://localhost:35729/livereload.js"></script> in index.html:
npm run dev
build:
to build your project for production:
npm run build

Setup a local configuration file in Codeigniter

Probably my English is not the best,i will try to re-explain.
SERVER ROOT
—> global_application_folder
-> global_system_folder
—> app_1
- index.php
- local_config_file.php
- local_database_file.php
-> app_2
- index.php
- local_config_file.php
- local_database_file.php
-> app_3
- index.php
- local_config_file.php
- local_database_file.php
In any folder app_N i have "index.php" that takes care to say where to find the application and system folders.
"local_config_file", it should serve to change some settings in "config/config.php" like: $config['base_url'], $config['sess_cookie_name'], etc, etc.
"local_database_file", it should serve to change some settings in "config/database.php".
Everything works, now i have to find a good way to override the configurations i need to change for each app.
In the previous link: http://caseymclaughlin.com/articles/setup-a-local-configuration-file-in-codeigniter, (which explains what I need ), it describes a way but it does not work, perhaps because dated.
Doing various tests, the only working way i've found is to add, for example, at the end of the "config/config.php"
include_once(FCPATH . 'local_config_file.php');
including the file (in this case "local_config_file.php"), that is not found in the "global_appliacation_folder/config" folder, but within the various folders app_N, that's why FCPATH in the path of inclusion.
So if i will be app_1, the included file ("local_config_file.php"), will be inside the folder app_1
I would advise to make it all separate repositories and use and dependency manager. eg. composer for php.
With that approach get better control of individual applications, with easy way how to distribute changes in the core.
This way you can also leave old apps - to depend on older version of the core fixed at a specific version
You can have
core repo
test app 1 repo
depends on core repo
test app 2 repo
depends on core repo and some other repo
test app 3 repo
depends on core repo legacy version

Symfony2 moving to demo bundle over to production

I am going thorough the quick start for Symfony 2 and I'm getting quite confused. I have the following directory structure after unpacking Symfony2 (As in the documentation):
/var/www/ <- web root directory
Symfony/ <- unpacked archive
app/
cache/
config/
logs/
Resources/
bin/
src/
Acme/
DemoBundle/
Controller/
Resources/
...
vendor/
symfony/
doctrine/
...
web/
app.php
...
I've got the demo working at <host>/Symfony2/web/app_dev.php/demo/welcome/James. So far so good.
I know I can't use apache's mod_rewrite with app_dev.php so I was wondering if someone could give me a step by step to:
Moving the DemoBundle over to using app.php (because <host>/Symfony2/web/app.php/demo/hello/James is not working. It's throwing up a Symfony error. I swear I haven't touched a thing. I'm at the bottom of the first page of the tutorial)
Keeping the development toolbar when using app.php (do I just cut web_profiler: from config/config_dev.yml?)
Setting up Symfony2 outside of the web route (best thing for security I presume?!?) (Should I have to have a soft link /var/www/index.php pointing to /home/<name>/Symfony2/web/app.php?)
Now I'm on the production version will I be able to go to <host>/demo/welcome/James, if not, why not? (I have apache's mod_rewrite installed) (I'd really like to get this bit working)
(I had the same problem learning django, just to much information to absorb at first.)
The demo is not meant to be run in production. However, if you wish to do so for learning purposes, simply move the routes _demo and _demo_secured from app/config/routing_dev.yml to app/config/routing.yml.
Using the web profiler in production is again not sensible. Site visitors must not get access to such information. This is the reason why there are two separate front controllers (app.php and app_dev.php). They've both set up for different purposes.
The best practice in setting up the web server would be to have the web root point to ./web.

Where do you place all your files for Zend Framework?

I completed the quickstart tutorial, but I feel really unclear on a few things. I started the guide initially expecting everything to be on my remote server, but it actually seems to be a guide for a local setup. I have everything on my server, and I have the hosts file on my local computer routing to the server, for ex. this is the entry in my hosts file server-ip quickstart.local.
1) Currently, I have everything beneath public_html. Where should I put all the Zend files (bin, demos, incubator, etc..)? www/public_html/[zend-files],www/public_html/quickstart/
2) Where do I put the quickstart (project) folder? Am I supposed to create an index.php that routes to the public folder in the project folder? At the moment, it is at public_html/quickstart/.
I feel silly and embarrassed for asking, because I feel like this is something really obvious.
Actually, you'll need only the Zend folder, which is the library itself.
On the public_html you need to put only the files located in the public folder of your project.
Folders like application and library should stay out of public_html.
For example
/home/my_project/public_html (public folder from zend)
/home/my_project/private (the other files, like application and library)
Instead of put the Zend library inside your project library folder, you can put it on the php include_path.
The second option, maybe the best, is to configure your virtual hosts and set the public folder (application public folder) as the root folder for your domain quickstart-local
So, you will end up with /home/my_project/public as your root folder and /home/my_project/application as your private folder.
You'll need to setup your index.php and application.ini with the appropriated paths.
As soon as you work with more than one framework version at a time, using symlinks becomes a good option. It is also much better for development than using the include path because you automatically have code assist for ZF code. We organize our projects as follows:
/application
/httpdocs
/library
/Project
/Zend (->symlink to the Zend folder of the needed version)
/ZendX (->dito)
/tests
And now, if you're about to say that 'symlinks' don't work on Windows, don't say it. It's utter rubish. It works perfectly well.

Hosting PHP Zend Framework application on shared cPanel server

I'm trying to deploy an PHP application which is written with Zend Framework to a shared cPanel server.
There are not many tutorials available on this area online, however, I followed several of them. It is successful to run the test page which proves the zend framework is installed correctly.
However, since cPanel server has a default root directory called public_html/, it is impossible to simply rename it to the Zend Server's default public/.
As a result, I had two options in mind: (Say the project name is AAA)
1) upload my projects under the /public_html/ directory, then the project will be like /public_html/AAA/public, and etc.
However, this one simply fails to work.
My thought would be something wrong here with the baseUrl setting, however, no matter I comment ( which is to remove the baseUrl) or set to the root page, ( in this case /public_html/AAA) both failed.
2) I tried to follow the way listed in this article: http://blog.motane.lu/2009/11/24/zend-framework-and-web-hosting-services/. Still failed.
Can anyone suggest how to do it?
Really appreciate your help!
Just symlink it:
ln -s public public_html
then this structure will work:
htdocs/
myvhost.com/
public/
application/
library/
public_html # this is actually a symlink pointing to public
Whatever you do, dont just throw everything in the publicly accessible area... its just bad form :-)
I don't think ZF cares what you name your "public" directory. It's just the convention that's typically used.
I can't think of any ZF component or common use case where anything explicitly points at "public/...".
A project structure like this should work:
myproject/
application/
library/
public_html/ # this used to be public until you renamed it.

Categories