控制PHP项目的多个版本

I've stumbled upon the following problem and can't figure out a decent solution. I make websites in PHP for various clients. Like all clients, some will find bugs that need fixing, some will request updates to live sites after a few months and some do both.

When working on updates for clients, I like to preview them to the clients before putting them live.

I've used a couple of different solutions in the past, but none I'm happy with. What I've done so far:

  • Define VERSIONs and CURRENT_VERSION in the index. Visitors see the approved version. I send the client a specific link that sets a $_SESSION variable, which lets them see the new version. In the code I work with if's and switches to show new things depending on CURRENT_VERSION. This works, keeps all the code in one place and easily allows bugfixing, but riddles the code with stupid if(CURRENT_VERSION >= V2) statements. I also can't use this in CSS files.
  • Put all files in a "build1" folder, when starting on big updates that need previewing, I copy everything to a "build2" folder. I upload the "build2" folder for the client and password protect it. This works pretty well, however, if I have to bugfix build1 while working on build2, I have to make sure I copy fixes from build1 to build2.
  • Use a development server (some clients can provide this) this works the best so far, as the dev server is separate from the live site. It works much the same as the second solution, where I have to make a copy of the project, but it feels cleaner to me.

I am however looking for a better way to manage my code, possibly with the use of Git/SVN, but do not know enough about these things if they could help me.

A fairly typical paradigm these days is Development/Staging/Production. You don't need an entire development server for this approach either, VirtualHosts/nginx equivalent will suffice.

I'd suggest that the first thing you need to do is get your projects into Git, the quicker the better!

Disclaimer: This is my workflow, there are many like it, but this one is mine.

Here's an example of my current work flow.

GitHub

A separate repository for every project I've taken on

Development Server

Bare Git Repositories, replicating my GitHub (I'll explain this shortly)

/opt/git-bare

VirtualHosts of all my projects

/var/www/vhosts

Local Machine

I clone my bare repositories, as I need, for quick editing and commits. I'm not worrying about FTP'ing files back and forth or mounting anything locally on to my machine. I find this the BEST way to work on a project. When I am ready to check out some code on my development server, I simply commit and push my work to the bare repository, where I have a post hook that then tells my development VirtualHost to update itself.

This means that within seconds of commiting/pushing my work, from my local machine, I can see it on my development server through my browser.

When I am happy with what I have seen on my development server, I then push my bare repository up to GitHub. Git is a wonderful tool and all my local commits are also available within the logs on GitHub.

Staging

This is a clone, from GitHub, of my master branch on GitHub. This is what I use for showing to clients and getting changes signed off.

Production

My production server is a clone of a tag from GitHub. No matter what I do within my master branch, production will never be effected and should anything ever go wrong with one of my servers I have this tag easily available for rebuilds.

If you have any questions about this, please just fire away.

Before my long answer: if you're looking for a host that would kind of do this for you, stackable supports the concept of multiple 'enviroments'. I'm sure other hosting platforms offer similar features that allow essentially the same thing (AWS Elastic Beanstalk for example), but I don't know of one that is as core to the offering. Note: I don't have any connection to stackable, I'm not even a customer.


Define VERSIONs and CURRENT_VERSION in the index...but riddles the code with stupid if(CURRENT_VERSION >= V2) statements. I also can't use this in CSS files.

If I recall correctly, this is actually similar to how Facebook rolls out changes. You're right, it adds that additional logic; however there's an advantage as you're able to 'preview' the changes to more than a single user (say, all users that are admins, or all users in a specific geographic location).

And of course, the preview uses the same data - which means the user previewing the site will use it like they normally do (instead of odd interaction with contrived data).

While you're right as to the disadvantage, there are cases where this is a useful way to test new features.

Put all files in a "build1" folder, when starting on big updates that need previewing...however, if I have to bugfix build1 while working on build2, I have to make sure I copy fixes from build1 to build2.

Here you're essentially deploying two versions of the project to the same server. In the example you give, you're putting the second copy under the original webroot - but depending on hosting, you could just assign a subdomain and work from two different web roots.

The advantage is similar to the first, as both installs could easily share the same data, and if all requests pass through some kind of front controller you can add logic to only show changes to select users (or use some kind of Basic Auth as you describe).

In this case putting your project into version control (as I see it, git would be better than SVG for this) can make this much easier. On your development system simply switch between branches to work between the existing version and the new version.

If you fix a bug in the old version, you should be able to easily (or more easily than your current workflow) merge that fix into the new version with a few commands. If you fix a bug in the new version which was also in the old version, doing a cherry-pick can allow you to just merge that single change back into the old version.

Deploying your code can be as basic as logging into your web server and doing a git pull, or you could use tools to automate the deployment. Essentially your deploy of the old version would be based on the 'master' branch of your repository (or something similar to that), and the new version would be based off whatever you've called that branch.

Use a development server (some clients can provide this) this works the best so far, as the dev server is separate from the live site. It works much the same as the second solution, where I have to make a copy of the project, but it feels cleaner to me.

As this is very similar to your second method, adding version control will certainly make this easier as well.

There are plenty of resources explaining how to deploy from various version control systems to various hosting platforms, but hopefully this illustrates how that will fit into what you're already doing and make things easier for you.