bal2_a
Last Updated: February 25, 2016
·
21.38K
· falsetto
C6636e890e2bebb0f29a2978d21ab502

Use PHP with your Yeoman dev server

Note: I haven't used this stack for a couple of years. Judging by the comments, this protip has gone fairly stale. Take what you can, but just know that YMMV.

Ever needed to use a PHP script in your Yeoman project? It's quite straightforward to do so while keeping all of the goodness that Yeoman brings together for you (particularly live reloading).

The integration is accomplished via a middleware by Felix Gnass named gateway. Gateway enables you to specify CGI handlers for requests matching certain extensions (.php in our case). Mr. Gnass wrote a blog post on this protip's topic, but didn't include step-by-step instructions for the middleware integration, which took me a while to figure out.

Example code

https://github.com/falsetto/php-from-yeoman

Generate an app with Yeoman

$ mkdir php-from-yeoman
$ cd php-from-yeoman
$ yo webapp

Ensure that php-cgi is in your $PATH

$ which php-cgi

If you get php-cgi not found, here's how to install it using Homebrew on OS X (for other OS's, Google is your friend):

brew tap homebrew/dupes
brew tap josegonzalez/homebrew-php
brew install php54

Setup gateway module

$ npm install gateway

Modify Gruntfile.js by adding the following near the top:

var gateway = require('gateway');

Modify the array returned by the function at connect.livereload.options.middleware to look like this:

middleware: function (connect) {
  return [
    lrSnippet,
    gateway(__dirname + '/app', {
      '.php': 'php-cgi'
    }),
    mountFolder(connect, '.tmp'),
    mountFolder(connect, 'app')
  ];
}

Rename app/index.html and test

$ mv app/index.html app/index.php

Add <?php echo "<h1>Hello from PHP!</h1>"; within the body tag of app/index.php.

Then fire up your development server:

$ grunt server

Assuming that your browser launched and loaded http://localhost:9000/, you should see Hello from PHP! on the page.

Make some changes to app/index.php, save the file, and your browser should automatically reload.

Note: due a to naïve conditional in the livereload library, live reloading will only work for PHP files when the URL ends with a '/' (so basically, index.php files).

16 Responses
Add your response

7244
Kong

Great tip, worked like a charm, I was using yeoman with angularjs and needed to bring in some php for server side support and your tip was very helpful and well written.

Cheers!

over 1 year ago ·
7407
C6636e890e2bebb0f29a2978d21ab502

@davidchase03, glad to hear it!

over 1 year ago ·
7905
E9073fcbd61f4b63f9ada3409ba7f8b4

Please provide a date for this article. It is incredibly disorienting to read blogs about cutting edge stuff without knowing if it's up to date or not.

over 1 year ago ·
7906
E9073fcbd61f4b63f9ada3409ba7f8b4

Also, your solution worked perfectly, thank you for this :) Much obliged

over 1 year ago ·
7935
Profile image 3 gray small

Great tip! Do you have any other tips about using a MAMP server to point to a Yeoman generated app? I mean, I don't want to use localhost:9000 anymore. I want my MAMP domain alias to point to /app and still be able to test with livereload. Is that possible?

over 1 year ago ·
7947
C6636e890e2bebb0f29a2978d21ab502

@wjonthomas: Glad it helped!

Unfortunately, I've only investigated the process of getting a node.js server to interpret PHP files using the php-cgi cli. Getting a MAMP server (Apache+PHP) to load and execute node.js code based off of a Gruntfile would be a wholly different thing that I haven't tried.

I'd be very interested to know if you figure out how to do it.

over 1 year ago ·
7955
Profile image 3 gray small

@falsetto I think a lot of people would be interested to see that. I fooled around for a bit. Seems like you can easer use the grunt connect server, or remove all of that convenience and use your own server. You lose a lot of the convenience of just running grunt server and being on your way though. I will definitely report back if I come across any ways to improve the workflow with Grunt/MAMP.

over 1 year ago ·
9005
651b2416c2c0dd1859d6a0ac8007ad41

I created a patch to edit your Gruntfile.js to config the server to run on / directory instead of app/ (useful for legacy project). See: https://gist.github.com/edouard-lopez/6397228

over 1 year ago ·
9190
86d454eb9aa5d041cce6ac15c4970d70

Thanks!! Time saver!

over 1 year ago ·
10744
48d74e69c570096b6d40ea72b9fcf921 normal

I'm interested in streamlining things like that as well. I think, though, that using pow might be a good option. This could give you the hostname flexibility, and also the convenience of firing things up with a single grunt watch command. I'll report back if I find success, but wanted to put the idea out there for someone to find if I wander off course :)

over 1 year ago ·
14354
Bc5bf3604a3c547a326cd79132a1349b

Sounds like what I was looking for. I am extremely interested for the workflow with Grunt/MAMP.

Thank you!

over 1 year ago ·
15794
B6390af4cef2791c4ad039e351771aea

There's no definition of lrSnippet anywhere so I got the following warning:

Running "connect:livereload" (connect) task
Warning: lrSnippet is not defined Use --force to continue.

I added the following at the top of Gruntfile.js:

var lrSnippet = require('grunt-contrib-livereload/lib/utils').livereloadSnippet;

and installed grunt-contrib-livereload and saved to package.json with the following from the terminal:

npm install --save-dev grunt-contrib-livereload

Then I discovered I was missing other dependencies and added the following to Gruntfile:

var path = require('path');

var mountFolder = function folderMount(connect, point) {
return connect.static(path.resolve(point));
};

At this point I see an Internal Server Error 500. After some fiddling I found that changing the following:

gateway(__dirname + '/app', {
'.php': 'php-cgi'
}),

to:

gateway('<%= config.app %>', {
'.php': 'php-cgi'
}),

finally got everything in order and grunt serve ran successfully without a 500 error, although my browser only says: Cannot Get / Here's a gist of my gruntfile: https://gist.github.com/anthonygreco/a92333ed5e3ffe4dd1a9 any idea what's missing here? Also this is the feedback from grunt:

Running "connect:livereload" (connect) task
Verifying property connect.livereload exists in config...OK
File: [no files]
Options: protocol="http", port=9000, hostname="localhost", base=".", directory=null, keepalive=false, debug=false, livereload=35729, open, useAvailablePort=false, middleware=undefined
Started connect web server on http://localhost:9000

Not sure why it says middleware undefined either. :\ Really wish I could easily spin up a PHP webapp that's not just php served from one "api" folder and instead the entire app. Any assistance here is greatly appreciated.

over 1 year ago ·
18057
5c7db2312f94e5339dcdeac5125d8de4

Doesn't work with latest yeoman webapp

lrSnippet is not defined

mountFolder is not defined

// Chris D. 14-Jan-2015

over 1 year ago ·
18321
9988b8bc96b4ab386fad51df509f75ff normal

Yesterday worked like a charm, today not. For some reason the app doesn't find bower components anymore. If I change my php file back to html and then Grunftile back to original, it all works.

This leaves me wondering: this can't be the easiest way to develop with php on 2015?

EDIT:

I also get "connect: res.headerSent: use standard res.headersSent" when I run grunt serve

EDIT EDIT:

Oh, I'm so incredibly noob. I 'm pretty new with this stuff so most of the time I just copy/paste the rows to various places not really understanding the process. I didn't realise that I'm not supposed to replace "connect.livereload.options.middleware" with

return [
lrSnippet,
gateway(__dirname + '/app', {
'.php': 'php-cgi'
}),
mountFolder(connect, '.tmp'),
mountFolder(connect, 'app')
];

but leave the lines

connect.static('.tmp'),
connect().use('/bowercomponents', connect.static('./bowercomponents')),
connect.static(config.app),

there.

Now it works again. However, there is a weird behavior: the browser downloads index.php on every livereload.

Any ideas?

over 1 year ago ·
24981
None

I don't find "connect.livereload.options.middleware"
Where is this ?

over 1 year ago ·
24993
C6636e890e2bebb0f29a2978d21ab502

Hey @abumalick, here's the line from the finished file: https://github.com/falsetto/php-from-yeoman/blob/master/Gruntfile.js#L58

I haven't used this dev environment for a couple years now, so YMMV.

Good luck!

-Jedidiah

over 1 year ago ·