Emacs and PHP tutorial: php-mode
php-mode is responsible for syntax highlighting, indentation, and other major PHP-specific modifications to your editing environment. There are a number of PHP modes available for Emacs. In this project, you'll learn how to set up the php-mode available from http://sourceforge.net/projects/php-mode/ . At the time of this writing, the current version is 1.4.0 and the maintainer is Aaron Hawley.
Download the latest php-mode.el from http://php-mode.sourceforge.net/ and save it to a directory in your load-path. I like to organize my Emacs Lisp files in a directory called ~/elisp. To add PHP support to your Emacs, add the following lines to your ~/.emacs:
(add-to-list 'load-path "~/elisp")
(require 'php-mode)
This configures Emacs to automatically recognize files ending in ".php", ".phps", ".php3", ".php4", ".phtml", and ".inc" as PHP files. To associate more extensions with PHP files, add lines like this example to your ~/.emacs:
(add-to-list 'auto-mode-alist '("\\.module$" . php-mode))
(add-to-list 'auto-mode-alist '("\\.inc$" . php-mode))
(add-to-list 'auto-mode-alist '("\\.install$" . php-mode))
(add-to-list 'auto-mode-alist '("\\.engine$" . php-mode))
This associates php-mode with the extensions used by Drupal, a PHP framework. When you open a file with the specified extension, it should be highlighted according to PHP syntax.
Here are some useful commands:
| TAB | c-indent-command | Indent the current line |
| M-; | comment-dwim | Add a line comment, comments or uncomments the currently-selected region, or does other smart comment-related actions |
| C-c C-f | php-search-documentation | Search the online PHP manual for the current word |
| C-c RET | php-browse-manual | View the online PHP manual |
| C-c . | c-set-style | Change coding style |
| C-M-a, C-M-e | c-beginning-of-defun, c-end-of-defun | Go to the beginning or end of the current function |
| C-M-h | c-mark-function | Select the current function |
| M-a, M-e | c-beginning-of-statement, c-end-of-statement | Go to the beginning or end of the current statement |
Here are some variables you may wish to customize:
| indent-tabs-mode | Set this to nil if you want to insert spaces instead of tabs |
| case-fold-search | Set this to t if you want case-insensitive search. |
| c-basic-offset | Set your tab size or number of spaces used as a basis for indentation |
You can either customize these variables globally with M-x customize or set them for php-mode. Here's an example that sets up a buffer with the coding style recommended for Drupal:
(defun wicked/php-mode-init ()
"Set some buffer-local variables."
(setq case-fold-search t)
(setq indent-tabs-mode nil)
(setq fill-column 78)
(setq c-basic-offset 2)
(c-set-offset 'arglist-cont 0)
(c-set-offset 'arglist-intro '+)
(c-set-offset 'case-label 2)
(c-set-offset 'arglist-close 0))
(add-hook 'php-mode-hook 'wicked/php-mode-init)
You can further customize the indentation by moving the point to where the indentation needs improvement and typing C-c C-o (c-set-offset).
To try automatic indentation, press C-j (newline-and-indent). If you like that behavior, you can make it the default in php-mode by adding the following line in ~/.emacs:
(define-key php-mode-map (kbd "RET") 'newline-and-indent)
You may also be interested in M-x show-paren-mode, which shows the matching parenthesis, bracket or brace for the character at point. You can enable it automatically by adding the following line to your ~/.emacs:
(setq show-paren-mode t)
It's a good idea to separate PHP and HTML code. This is not only better coding practice, but it also makes developing in Emacs much easier. php-mode focuses on PHP-specific behavior and does not have special support for HTML. Emacs has a number of packages that allow you to work with multiple modes like php-mode and html-helper-mode in a single buffer, but they don't always work, and indentation can be confusing. If you must work with large segments of both PHP and HTML in the same file, check out MultipleModes (http://www.emacswiki.org/cgi-bin/wiki/MultipleModes) for tips.
Save to - del.icio.us - Digg it - reddit - StumbleUpon
php-mode is decent, but it has plenty of issues.
C-M-h, for example, doesn't understand OOP code. If you use it to mark a method in a class, it marks the entire class. Same goes for any of the other commands for dealing with functions, like beginning-of-defun & friends.
I have a few custom functions and bindings:
(defun terminate-line ()
"Terminate the line with a semicolon, and prepare to start typing on the next line. A second semicolon will not be inserted if one is already present.
If the line begins with `case,' a colon will be inserted insead."
(interactive)
(back-to-indentation)
(if (looking-at "case")
(setq eol-char ":")
(setq eol-char ";"))
(end-of-line)
(if (not (looking-back eol-char))
(insert eol-char))
(reindent-then-newline-and-indent))
(defun open-line-indent (n)
"Insert a newline and leave point before it.
If there is a fill prefix and/or a `left-margin', insert them
on the new line if the line would have been blank.
Indent following line afterwards.
With arg n, insert n newlines."
(interactive "*p")
(save-excursion
(open-line n)
(next-line n)
(indent-according-to-mode)))
(define-key php-mode-map "\r" 'reindent-then-newline-and-indent)
(define-key php-mode-map "\C-c\C-c" 'comment-or-uncomment-region-or-line)
(define-key php-mode-map "\M-;" 'terminate-line)
(define-key php-mode-map "\C-o" 'open-line-indent)
I turn php-mode-force-pear on, since I contribute to PEAR and follow their CS in all my code.
I've added your terminate-line to my config. Thanks! =)
For open-line-indent - open-line doesn't seem to do things like add the * prefix for block comments. When do you tend to use it?
In other news, I so have to figure out how to turn off smart quotes in Wordpress…