6104 comments
2357 subscribers
6264 on Twitter
Subscribe! Feed reader E-mail

Emacs and PHP: On-the-fly syntax checking with Flymake

The dreaded white screen of nothingness usually means that I’ve misplaced a quotation mark or brace somewhere in my PHP code. On-the-fly syntax checking in Eclipse helped me find those errors quickly because I could scan the right scrollbar for areas marked with red. I knew that shifting to Emacs wouldn’t automatically cure me of the propensity to mismatch my parentheses. If I could get on-the-fly syntax checking working in Emacs, I’d save myself a lot of time.

It took me a while to sort out various configuration problems. Most were due to the fact that PHP didn’t report parse errors with my original configuration, even though I had uncommented the line after “Show only errors”. As it turned out, the error_reporting option in php.ini needs to include E_PARSE in order for php to report parsing error details. Here’s the value I’m currently using in /etc/php.ini:

error_reporting = E_ERROR|E_COMPILE_ERROR|E_CORE_ERROR|E_PARSE

Flymake is the package responsible for on-the-fly syntax checking in Emacs. Out of the box, it supports C, C++, XML, XHTML, Perl, Java, TeX, and IDL. To load Flymake and add support for PHP, add the following to your ~/.emacs:

(require 'flymake)

(defun flymake-php-init ()
  "Use php to check the syntax of the current file."
  (let* ((temp (flymake-init-create-temp-buffer-copy 'flymake-create-temp-inplace))
	 (local (file-relative-name temp (file-name-directory buffer-file-name))))
    (list "php" (list "-f" local "-l"))))

(add-to-list 'flymake-err-line-patterns 
  '("\\(Parse\\|Fatal\\) error: +\\(.*?\\) in \\(.*?\\) on line \\([0-9]+\\)$" 3 4 nil 2))

(add-to-list 'flymake-allowed-file-name-masks '("\\.php$" flymake-php-init))

;; Drupal-type extensions
(add-to-list 'flymake-allowed-file-name-masks '("\\.module$" flymake-php-init))
(add-to-list 'flymake-allowed-file-name-masks '("\\.install$" flymake-php-init))
(add-to-list 'flymake-allowed-file-name-masks '("\\.inc$" flymake-php-init))
(add-to-list 'flymake-allowed-file-name-masks '("\\.engine$" flymake-php-init))

(add-hook 'php-mode-hook (lambda () (flymake-mode 1)))
(define-key php-mode-map '[M-S-up] 'flymake-goto-prev-error)
(define-key php-mode-map '[M-S-down] 'flymake-goto-next-error)

Evaluate that code, open one of your PHP files, and intentionally break it. The syntax error should be highlighted. To change the highlighting, move your point to the error and type M-x customize-face. Accept the default (flymake-errline), then customize it as desired. Don’t forget to save your customizations for future sessions.

If your syntax errors are not highlighted and you get a message like this:

Configuration error occured while running (php -f test_flymake.php -l). flymake will be switched OFF

double-check your /etc/php.ini to make sure that E_PARSE is included as one of the options for error_reporting. You can check the output by running php -f yourfile.php -l. You should see the line number of the parse error. Make sure that this matches the regular expression added to flymake-err-line-patterns in your ~/.emacs. If your PHP returns a slightly different message, modify your flymake-err-line-patterns accordingly.

Flymake can save you a lot of programmer frustration for the cost of a little CPU time. Use it to check for errors before you save files or commit them to your source code control repository, and you and other developers will be much happier.

(UPDATE: Fixed typo in flymake-php-init)

Short URL: http://sachachua.com/blog/p/5021
  • Graham

    Thanks for the tip! However, I get the following error when using your suggested configuration:

    let*: Symbol’s value as variable is void: temp-file

    I tracked it down to a typo in the let* expression. I think the first part of the expression should be:

    (let* ((temp-file (flymake-init-create-temp-buffer-copy ‘flymake-create-temp-inplace))

    • http://sachachua.com Sacha Chua

      Oops, good catch. =) That’s what happens when I try to modify code in WordPress instead of Emacs… =)

  • http://atomized.org/ Ian Eure

    I’d recommend changing your error_reporting value to E_ALL at least, and shooting for E_STRICT is a good thing.

    I have a similar setup, but using compile-mode. It’s a little more concise:

    (load-library "compile.el")
    (pushnew '(php "syntax error.* in \\(.*\\) on line \\([0-9]+\\)$" 1 2)
             compilation-error-regexp-alist-alist)
    
    (setq compilation-error-regexp-alist
          (append (list 'php) compilation-error-regexp-alist))
    
    (defun php-lint ()
      "Performs a PHP lint-check on the current file."
      (interactive)
      (compile (concat "php -l -f \"" (buffer-file-name) "\"")))
    
    (define-key php-mode-map "\C-c\C-l" 'php-lint)
    (define-key osx-key-mode-map "\C-x~" 'previous-error)
    

    You get the same C-x ` binding to take you to the next error as the normal compile-mode, and C-x ~ takes you to the previous.

    • http://sachachua.com Sacha Chua

      I would change to E_ALL or E_STRICT, but we’re using a lot of third-party modules I’d probably need to modify, and I might not know each of them well enough to make changes without introducing new bugs. =) I’ll give it a try, though!

      Do you find that making php-lint a separate step in your process works out well for you? I might shift to that, because I really don’t need flymake running all the time when I know I’m writing partial code. (“I’m not done typing the function definition in yet! Stop complaining about the braces…”) =)

  • http://20y.hu/ slink

    There is syntax checking for PHP in flymake.el shipped with Emacs 23.

  • Pingback: Weekly review - week ending Aug 1-ish | sacha chua :: enterprise 2.0 consultant, storyteller, geek

  • Jake

    Emacs 23′s flymake now includes support for php. You should be able to get the proper effect with:

    (require ‘flymake)
    (add-hook ‘php-mode-hook (lambda() (flymake-mode 1)))
    (define-key php-mode-map ‘[M-S-up] ‘flymake-goto-prev-error)
    (define-key php-mode-map ‘[M-S-down] ‘flymake-goto-next-error)

  • Jason Murray

    Nice post, this was one of the missing features that prevented me from moving from Eclipse PDT to Emacs full time for development.

  • http://www.dave-cohen.com Dave Cohen

    Sacha,

    Thanks for sharing. While the comments are correct that flymake-php-init is already defined in my version of emacs. I still copied your Drupal-type file extensions and that’s what I needed to get it working for my drupal files.

    Now on my wish list is to run Drupal’s coder module in emacs’ compile mode. Is there an elisp expert out there who can tackle that?

    -Dave

  • slink

    @Dave: how do you invoke the Coder module? Do you run it via drush? Typing `M-x compile` allows you to specify the compile command to run that can be any drush command as well.

  • Pingback: ECAE — Shopex电子商务云的梦想空间 » [Denny] Emacs — fundanmental features

  • Pingback: ECAE — Shopex电子商务云的梦想空间 » [Denny] Emacs — fundanmental features

On This Day...

  • 2012: Slowly figuring out how to use my tablet — Blogging will be a little slower for me over the next few… days? weeks? I’ve been making myself use the [...]
  • 2011: Weekly review: Week ending July 31, 2011 — I thought I’d feel guilty about being on holiday while other people on my team – clients and IBMers in [...]
  • 2011: Software and making pots — This is what software feels like. It’s squishy and floppy, and it falls over from time to time while you’re [...]
  • 2010: Cool mornings — 2010-07-31 Sat 08:00 Fall doesn’t officially start until late September, but these mornings and evenings are pajama-cool, duvet-cool, [...]
  • 2009: Improv 101 class 2: Scenes, objects, and environments — It takes time to build an imaginary world that other people can see, and I’m looking forward to being able [...]
  • 2008: Kaizen: Moving time around — I recently (re)discovered that writing is much easier and more enjoyable in the early morning when I’m fresh and focused [...]
  • 2006: Planning — Here’s what I need to do: I need to come up with a list of calls for papers for conferences related to [...]
  • 2006: Focus — My research manager told me that I’ve been conditionally approved for VPN access, which would allow me to access IBM resources [...]
  • 2006: Business development — Stayed up late chatting with Jijo Sevilla of QSR, a Philippine-based Linux solutions company. Simon Rowland had mentioned an interest [...]
  • 2005: Being Filipino — Saturday night’s barbecue with Sol Laforteza was _the_ best evening I’ve had in Canada so far, and I owe so very [...]
  • 2004: Don Bosco Pugad — Japanese training program in Don Bosco Makati
  • 2004: Software Partnership International Japan — Promoting outsourcing to the Philippines in Japan - Common framework and quality - Promoting Japanese language proficiency: Toshiba ASP to introduce employees [...]
  • 2003: Mozilla — Pfft. I want all extensions to be installable by normal users. I also wish that Mozilla paid attention to http_proxy and [...]
  • 2003: State of OSS in the Philippines — This paper provides an overview of the state of adoption of Open Source software in the Philippines as well as the [...]
  • 2003: The Little World of Dan Camillo — Dominique Cimafranca said: Memory is a very funny thing: all of a sudden it occurred to me to look up some web [...]
  • 2003: Roden’s MP3 encoder — Roden has designed an MP3 encoder – given a text file, it will convert it into an MP3 or WAV [...]

Get the highlights as a PDF!

Stories from my Twenties: Highlights from a Decade of Blogging

Free sample!