Why to have "build/" folder with PHP project and phing - php

What is a benefit of having "build/" folder where all the sources will be placed and "built"?
Maybe it's a silly question, but I'm trying to understand Continuous Integration with PHP. Any example of build.xml for phing uses such build/ folder, but what's a sense in that for PHP where a checked out project doesn't require a compilation, only a basic configuration. Copying it all into build/ will just complicate the things, because you'll have doubled files and +1 folder to the web root path (if you'd like to have web UI to run selenium tests on)
Particularly I need phing for two cases:
1) let new user setup his first installation (or update old), right on a working copy
2) run unit/func-tests, phpcc, phpcs, phpdoc etc (all that usually on CI server)
Should I have "build/" for the second task? What is the best practice for PHP?

There are several good reasons to have a build directory (i.e., deployment to multiple environments, performing some text replacement, minimizing and combining CSS and JS, optimizing images, handling of config files etc.)
However, these may not apply in your use cases. There is no rule saying you need this directory. Depending on your thinking on testing in production, a build directory may be a good reason to keep this directory.

Related

Clean application deployment when using Composer

I have started to use Composer for a new PHP application (it uses a few frameworks and APIs such as Laravel, Smarty etc.) and all is good with it in development.
However, I am not too sure about how do I go about deploying this on a live production server. The sub-directories of the respective modules under the /vendor directory seem to include a lot of stuff which I would not normally include with an app, (such as Demo files, installation readmes, documentation etc.). Is this normal, or is it that the creators of those packages got the wrong idea of how to create a Composer package?
Is there a standard approach to create a clean app deployment that only includes the necessary distribution files and not the rest of the stuff which is not related and should not even be there (even for security reasons)?
I am asking about the most common workflow used, or maybe a specific command or configuration in composer.json I should be looking at to achieve this.
There are two recommendations I'd make which cover most of your worries.
1)
Use composer update --no-dev to prune out any dependencies for development only from your lock file. Or tweak your requirements in composer.json to achieve the same.
In theory the package developers should keep the production version cleaner, (e.g. not including all the phpunit tests). However yes it's pretty normal to have a lot of 'cruft' in the vendor library, mostly because the concept of build is relatively uncommon in PHP, therefore "sources" and "targets" are intermingled.
Demos and readme's are still a necessary part of the 'distribution' version of a component so will still be there if you specify no-dev, which is just to say "I'm not developing this package, I'm just consuming it".
It does feel like there's a missing composer feature: one level above this which is indeed a super-clean deployment minified package.
2)
Keep your vendor library above the web root.
This prevents any unwanted browsing into the vendor library, and removes any security issues of site visitors exploring your libraries (if that's what you were rightfully worried about).
e.g. I typically use
domain
/api
/etc
/vendor
/www
/js
/css
/images
/index.php
/foo
/bar.php
Where www is the virtual-host web root.
All entry-level scripts are in your web root as normal and path to the autoload at ../vendor/autoload.php
Or of course www/ could be the laravel root folder if you're using Laravel for your website as well as api.
api can host a separate vhost for your laravel APIs if they're done separately from a 'flat' website.
(I keep other folders above the web root build, docs, src for SASS, JS, Grunt etc, etc can securely store any config, passwords, keys etc.).
3)
If you're still not happy with the baggage, then as the other commenter suggests, you'd want to look at a build process which cleans things up. This can get complex though and difficult to maintain!
e.g. you could build to a local www deployment folder (i.e. composer update, plus any grunt tasks, bower installs, laravel/artisan publishing etc), then prune it back (custom scripts you'd have to engineer), and commit that into a separate repository representing a published, flattened deployment target. This is what you would deploy to your website.
This would have to be automated or you'd stop doing if after about the third time :)
But... you have to ask why else you'd want to prune back the vendor libs. Disk space? They're not that big. General tidiness? Consider the folders as black boxes and just read the API docs. i.e. don't look :)

The point of Yii2 environments folder

I am trying to work what the point of the environments folder is.
Originally I had the idea that you could point the webserver to the different dev and prod folders in the environment folder but after reading up a bit I realise this is not the case.
In Yii 1 you would solve this by just having multiple index.php's i.e.:
index.php
index-local.php
So the question is what benefit does this new environment structure actually give me over the old way?
I've found environments very useful in allowing me to keep a common code base for multiple client projects (based on Yii App Advanced) and setting up a different environment for each specific client, keeping their custom code private and separate.
To do this I store the environments folder in a separate git repo from the rest of the code and pull down the relevant folder on a client/project basis.
This lets me use a base common code for all projects and add/override any file for a specific client or project whilst still allowing separate dev/prod config settings. If the client uses other developers too, they are also catered for. In this way, only common code I choose will be shared amongst clients and custom code will be kept private.
I've also moved the composer.json file into the environments folder so I can pull in different extensions per client/project keeping those private too.
That init command can be a very powerful tool and you don't have to limit yourself to the template provided by the core developers.
If you don't need environments, then don't use them, but I assure you some people will find it very useful.
Yii2 documentation in WIP, but you should read this :
https://github.com/yiisoft/yii2/blob/master/docs/guide/apps-advanced.md#configuration-and-environments
You need to use yii init command to switch between these environments.
EDIT :
This new environment feature is more than just use different config file. You can use different folder structure, different entry script...etc
Personnaly I won't use this feature, I don't need it (I will use a different entry script as with Yii 1), but I think this is not useless.
I think you didn't get the real purpose of environments introduced in Yii2.
I'll try to explain what was the main purpose of adding environments to yii from the developers point of view on an example and hope you will really appreciate its usefulness.
Let's suppose for a moment that you are a team of developers (e.g. 5-7 person) working on mid-to-large project implemented in Yii. To effectively work on that project your team decides to use some CVS or SVN (e.g. GIT) and keep all the files of the project in repository in cloud for the whole team. That's de facto standard while working on mid-to-large projects in teams and nobody will resist that it's the only comfortable and easy way.
Ok, now let's suppose you use Yii 1.x or Yii2 with the approach of different entry scripts to differentiate between local (development) and production environments to connect to db or set some other environment specific configs. Everything is ok and working. But suppose your team members implemented something new on the project and you check out repository to work on updated version and you suddenly find out that your local config file (in this case entry script with config) is overwritten with other team member's file who pulled the changes to repository (because each of you is using your local machine db with other database name or OS, or config, or simply because your team uses one local development server db, but you are on vacation and can't use anything except your local machine).
So generally Yii2 environment adds more flexibility for using different environments each with it's own specific configurations while using also general (common) configs when working in teams on mid-to-large projects hence why the example in guide is given on advanced app project.
Surely you can overcome everything stated above with some solutions or .gitignore which is used by default to overcome the problem stated in Yii2 with environments. But:
Why bother if everything is already done?
and
It was just one little example of usefulness of Yii2 environments. More depends on the project and your imagination.
Overall Yii2 is great product. Not only it adds many new features to already great framework, but it also is more robust and flexible than Yii 1.x (despite the fact that Yii 1.x was already very robust).
As for Laravel or any other PHP framework, it really depends... Everyone will find his/her own favorite.
For those who are tired of copying files around, I created a useful script that you can run in background to keep the files in sync on your dev environment:
File sync-env-files.sh
#!/bin/bash
ENVIRONMENT_DIR="/var/www/example.com/environments/dev/"
DIR="/var/www/example.com/"
while [ true ]; do
for envFile in `find $ENVIRONMENT_DIR -type f`
do
file=${envFile/$ENVIRONMENT_DIR/$DIR}
if [ `stat -c "%Y" $file` -gt `stat -c "%Y" $envFile` ]; then
#echo "copying modified file $file to $envFile"
/bin/cp -f $file $envFile
fi
done
sleep 2
done
Then run the script in background or add to cron with flock
nohup server/sync-env-files.sh >/dev/null 2>&1 &
I would like to mention in addition to #AngelCoding, since this question still gets seen, that I use the environments folder lots now and definitely see the point of it.
The very first things I do in any open source project is create one project for the code base on GitHub and then another, private, one on Bitbucket for the configuration, in other words the environments folder.
Having this folder has made it a lot easier for me to separate my configuration into a private repository.
So the environments folder has a lot of uses and really helps to separate configuration for easier usage even if it does not seem like it initially.

In a web project, what is the difference between a dist and build directory (traditionally)?

Am I correct in thinking, a dist directory and a build directory are both production directories that contain the files that need to be deployed to the web server.
Which to use?
A dist directory could have both files that are used during development (.php, etc), and files that are generated from a build script (.min.js, etc).
A build directory, however is entirely made up of files from a build script, and no development should take place within the build directory.
So, are these assumptions correct? Also, I realize that if you are using a framework, you'd use their conventions. I am just wondering, what these naming conventions are generally, if you were to create say a php project from scratch.
In a generic sense - a dist dir is for distribution. It is prod ready and can be distributed to other users who want to try it for beta testing, production use, whatever. A build dir is when you have ran you pre-deployment script manually or automatically and created a resource that can now be deployed (usually not distributed) into one or multiple production servers. This could contain sometimes just a tarball which can then be un-tarred and installed on the server.
Annoying naming practices..varies from people to people and organization to organization and technology to technology

sharing libraries across web projects

I have 3 PHP projects using the CodeIgniter framework which share some exact same files such as models libraries and controllers. What's the best way I could share these files across without having to keep in sync and update the same files across?
In linux I thought of using dynamic links and extract these files to a central place but that kind of breaks our version control and would create portability issues.
Another way perhaps to use unison on these files across projects
I'm assuming that's a common problem, what are common approaches?
Separate them into a module, and use something like composer.
http://getcomposer.org/
Or just put them in a separate SCM.
One thing you can do:
Put all the shared code in libraries, helpers and models and place this in a separate folder. Then use:
$this->load->add_package_path('shared location');
Also take a look here: http://codeigniter.com/user_guide/libraries/loader.html , under application packages.
This works for most of the stuff, except controllers.
Use version control! In svn you can use externals, git has submodules or subtrees.
You don't want to use hardlinks, you'll run into weird issues like updating one project influences another project ("that I haven't touched in weeks").
The code can be in two physical places but shared under version control. There will always be only one authorative copy, namely the one in your version system. All physical copies are derivatives. It's important to see that you have control over when you update the code of a specific project, so a change at one point doesn't immediately break another project in case you made a mistake.
If you do want to catch these kinds of errors, set up a proper regression testing environment.
Sharing a development environment with another developer is also a big no. You don't want to have to wait till your colleague fixes a parse error that breaks the entire program. Each developer should have their own copy (checkout!) of a project and similarly each project should have their own copy (externaled) of shared code.
Seperate them into folders outside your project, then configure or include them in your projects.
Usually we will rewrite "autoloader" method for the project to find files in our new folders.

CollabNet Subversion Edge Ignore Files

I am brand new at sub-versioning, so please bear with me.
I use CollabNet's Subversion Edge to manage a repository for a PHP/ActionScript based project I am building in the Eclipse IDE. In my project's root folder, Eclipse included several configuration files that aren't directly related to the project. How can I set up my repository to ignore these files/folders via CollabNet? Would it be through the "Repository Access Rules"?
Thank you for your time.
The "Chapter 3. Advanced Topics 'Ignoring Unversioned Items'" seems appropriate for your setup:
Extract:
[...] But these not-to-be-versioned files and directories can cause some annoyance for Subversion users.
For example, because the svn add and svn import commands act recursively by default, and don't know which files in a given tree you do and don't wish to version, it's easy to accidentally add stuff to version control that you didn't mean to.
And because svn status reports, by default, every item of interest in a working copy–including unversioned files and directories–its output can get quite noisy where many of these things exist.
So Subversion provides two ways for telling it which files you would prefer that it simply disregard.
One of the ways involves the use of Subversion's runtime configuration system (see the section called “Runtime Configuration Area”), and therefore applies to all the Subversion operations which make use of that runtime configuration, generally those performed on a particular computer, or by a particular user of a computer.
The other way makes use of Subversion's directory property support, is more tightly bound to the versioned tree itself, and therefore affects everyone who has a working copy of that tree. Both of the mechanisms use file patterns.
The Subversion runtime configuration system provides an option, global-ignores, whose value is a whitespace-delimited collection of file patterns (also known as globs).
The Subversion client checks these patterns against the names of the files which are candidates for addition to version control, as well as to unversioned files which the svn status command notices.
If any file's name matches one of the patterns, Subversion will basically act as if the file didn't exist at all.
This is really useful for the kinds of files that you almost never want to version, such as editor backup files like Emacs' *~ and .*~ files

Categories