PhpMode

Overview

Major mode for editing PHP files.

There is a long standing wish to develop a new and better PHP mode that can be included in Emacs. Unfortunately the current php-mode.el can not be used as a basis for this since not all contributors have been willing to sign papers for Emacs. Refer to the Emacs developer mailing list for more details.

Contributions to a new php-mode are very welcome!

Download

(autoload 'php-mode "php-mode" "Major mode for editing PHP code." t)
(add-to-list 'auto-mode-alist '("\\.php$" . php-mode))
(add-to-list 'auto-mode-alist '("\\.inc$" . php-mode))

php-mode comparison

(2010-05-26) After comparing the php-mode that comes with nxhtml vs. php-mode-improved vs. php-mode-new (included in Mewde Project), I found the following:

I may take the template functions from the Mewde variant and maintain them in a separate “add-on” for the nXHTML mode, but I would suggest that most people use the nXHTML variant.

Related modes

Beside those php-mode there are the following possibilities to mix them with better HTML support. See also MultipleModes.

For example; I don’t use any multiple major mode for PHP; I put all yasnipet HTML snippets to inside PHP snippets; and I use with new php-mode for complex php-html code pages.

Multiple modes with MuMaMo

It has built-in support for toggling between html-mode/nxhtml-mode and php-mode. See MultipleModes.

I am including a very slightly modified version of Aaron’s php-mode version in nXhtml.

Multiple modes using mmm-mode.el

https://github.com/purcell/mmm-mode

The PHP mode by FredYankowski explains how to do this in the commentary. For those of you using other PHP modes, add the following to your ~/.emacs:

(require 'mmm-mode)
(setq mmm-global-mode 'maybe)
(mmm-add-mode-ext-class nil "\\.php3?\\'" 'html-php)
(mmm-add-classes
 '((html-php
    :submode php-mode
    :front "<\\?\\(php\\)?"
    :back "\\?>")))
(autoload 'php-mode "php-mode" "PHP editing mode" t)
(add-to-list 'auto-mode-alist '("\\.php3?\\'" . sgml-html-mode))

If you’d like to know how you can use mmm-mode to combine psgml-mode, php-mode, and css-mode to get a really fancy web authoring environment, take a look at HtmlModeDeluxe.

Another approach is to narrow the buffer of an HTML file to show just the PHP block and switch to PHP-mode. This is the approach taken by HtmlHelperMode.

Using two-mode-mode

I found the following in the wayback machine from the site listed above. This mode seems to work quite well is a very light-weight. I had to edit two-mode-mode.el to use ‘php-mode’ for PHP files rather then C++ mode but other then that, it cooks just fine.

(setq auto-mode-alist
      (append '(
		("\\.html$" . two-mode-mode)
		("\\.php$" . two-mode-mode)
		("\\.php3$" . two-mode-mode) )
	      auto-mode-alist) )

- JamesKnight

Easy Toggling between PHP & HTML modes

I use the following lisp in my JonathanArnoldDotEmacs files:

;; Toggle between PHP & HTML Helper mode.  Useful when working on
;; php files, that can been intertwined with HTML code
(defun toggle-php-html-mode ()
  (interactive)
  "Toggle mode between PHP & HTML Helper modes"
  (cond ((string= mode-name "HTML helper")
         (php-mode))
        ((string= mode-name "PHP")
         (html-helper-mode))))

(global-set-key [f5] 'toggle-php-html-mode)

Now I can quickly toggle between PHP & HTML mode, depending on what I’m mostly going to be editing.

- JonathanArnold

Alternatively to the method above, I use the following snippet for switching between php-mode and html-mode. Add these two lines to your Emacs configuration file:

(define-key php-mode-map [f5] 'html-mode)
(define-key html-mode-map [f5] 'php-mode)

These will use the ‘f5’ key to switch between PHP and HTML mode. The difference to Jonathan’s above is that these keys are only used if php-mode or html-mode is the current major mode in the buffer you’re in, rather than defining a global key.

- CodyReichert

ac-php: great auto-complete for PHP

;; auto-complete for PHP https://github.com/xcwen/ac-php

for system class ,system function ,and user define.

https://raw.githubusercontent.com/xcwen/ac-php/master/images/ac-php.gif

Debugging

GEBEN is a basic debug package that I just discovered and am in the process of trying out. It is a DBGp client (i.e. Emacs debug mode using XDebug). -M

I think this project is dead (and also doesn’t work properly) - my posts to the mailing list have met with a deafening silence (a month now, with no activity on the list except my posts). I recommend removing mention of it from emascwiki.

Perhaps it is, but I have got a bug report for nXhtml from someone using it. And the latest release (version 0.26) was done 2010-03-30.

I’m using it occasionally and lack a better alternative for Emacs, so I recommend keeping it. – EngelkeEschner

I agree with EngelkeEschner. I’ve just started using it, but so far it works smoothly. I’ve also updated the link. – MattFlaschen

GEBEN is still the only option for an Emacs xdebug. Actually I found it to be easy to set-up and it worked nicely. The project has been migrated from code.google.com to github. Multiple times it seems! Someone has been quite active on this fork (untested by me).

I would be interested in a way to inspect values. I can hit e and then enter a variable name, and then I get a lispish representation of that value in the echo area. But if it’s a deeply nested object, this representation is hard to understand.

Improved Imenu by Class

php-imenu.el organizes the imenu for php-mode a little differently. Instead of listing all classes separate from all functions, it lists functions within a class, like most other IDEs do.

This wasn’t included in the recent release of php-mode (2008-11-04), since it was more of a bug-fix release. However, it is indeed worth investigating in a later release. – AaronHawley

Simplest grammar for the Semantic Bovinator

semantic-php-simplest-grammar.by

Quick documentation lookup

I didn’t see such a feature in the php-mode I use so I whipped up a quick solution. If you press F1 when standing on a symbol you can quickly look up its online documentation. Here it is:

(add-hook 'php-mode-hook 'my-php-mode-stuff)

(defun my-php-mode-stuff ()
  (local-set-key (kbd "<f1>") 'my-php-symbol-lookup))


(defun my-php-symbol-lookup ()
  (interactive)
  (let ((symbol (symbol-at-point)))
    (if (not symbol)
        (message "No symbol at point.")

      (browse-url (concat "http://php.net/manual-lookup.php?pattern="
                          (symbol-name symbol))))))

Quick documentation lookup with popup help

Here’s a variation of my quick documentation lookup above. It shows short help for the function under the cursor in the echo area if you press F1. It fetches the info from the official PHP site and it works for standard functions which documentation is properly tagged. You can press C-F1 for the same behavior as above if quick lookup failed or you want to read more about the function.

(add-hook 'php-mode-hook 'my-php-mode-stuff)

(defun my-php-mode-stuff ()
  (local-set-key (kbd "<f1>") 'my-php-function-lookup)
  (local-set-key (kbd "C-<f1>") 'my-php-symbol-lookup))


(defun my-php-symbol-lookup ()
  (interactive)
  (let ((symbol (symbol-at-point)))
    (if (not symbol)
        (message "No symbol at point.")

      (browse-url (concat "http://php.net/manual-lookup.php?pattern="
                          (symbol-name symbol))))))


(defun my-php-function-lookup ()
  (interactive)
  (let* ((function (symbol-name (or (symbol-at-point)
                                    (error "No function at point."))))
         (buf (url-retrieve-synchronously (concat "http://php.net/manual-lookup.php?pattern=" function))))
    (with-current-buffer buf
      (goto-char (point-min))
        (let (desc)
          (when (re-search-forward "<div class=\"methodsynopsis dc-description\">\\(\\(.\\|\n\\)*?\\)</div>" nil t)
            (setq desc
              (replace-regexp-in-string
                " +" " "
                (replace-regexp-in-string
                  "\n" ""
                  (replace-regexp-in-string "<.*?>" "" (match-string-no-properties 1)))))

            (when (re-search-forward "<p class=\"para rdfs-comment\">\\(\\(.\\|\n\\)*?\\)</p>" nil t)
              (setq desc
                    (concat desc "\n\n"
                            (replace-regexp-in-string
                             " +" " "
                             (replace-regexp-in-string
                              "\n" ""
                              (replace-regexp-in-string "<.*?>" "" (match-string-no-properties 1))))))))

          (if desc
              (message desc)
            (message "Could not extract function info. Press C-F1 to go the description."))))
    (kill-buffer buf)))

Collecting all functions for completion

This code fetches all PHP function names from the net and stores it in a list. It can be used for completion with a completion frontend.

(defun my-fetch-php-completions ()
  (if (and (boundp 'my-php-symbol-list)
           my-php-symbol-list)
      my-php-symbol-list

    (message "Fetching completion list...")

    (with-current-buffer
        (url-retrieve-synchronously "http://www.php.net/manual/en/indexes.functions.php")

      (goto-char (point-min))

      (message "Collecting function names...")

      (setq my-php-symbol-list nil)
      (while (re-search-forward "<a[^>]*class=\"index\"[^>]*>\\([^<]+\\)</a>" nil t)
        (push (match-string-no-properties 1) my-php-symbol-list))

      my-php-symbol-list)))


Completion with Company

See CompanyModeBackends#PhpCompletion

Automatic help with Eldoc

See ElDoc#Phpdoc

Indentation of arrays

The php-mode indentation for array is not good, It will indent like this:

$post=Post::model()->find(array(
                              'select'=>'title',
                              'condition'=>'postID=:postID',
                              'params'=>array(':postID'=>10),
                              ));

The better indentation is like:

$post=Post::model()->find(array(
    'select'=>'title',
    'condition'=>'postID=:postID',
    'params'=>array(':postID'=>10),
));

Add this to php-mode-hook:

(add-hook 'php-mode-hook (lambda ()
    (defun ywb-php-lineup-arglist-intro (langelem)
      (save-excursion
        (goto-char (cdr langelem))
        (vector (+ (current-column) c-basic-offset))))
    (defun ywb-php-lineup-arglist-close (langelem)
      (save-excursion
        (goto-char (cdr langelem))
        (vector (current-column))))
    (c-set-offset 'arglist-intro 'ywb-php-lineup-arglist-intro)
    (c-set-offset 'arglist-close 'ywb-php-lineup-arglist-close)))

Closures

Php 5.4 introduce anonymous function and indent for those is wrong, here is a patch (kind of hack):

(defun unindent-closure ()
  "Fix php-mode indent for closures"
  (let ((syntax (mapcar 'car c-syntactic-context)))
    (if (and (member 'arglist-cont-nonempty syntax)
             (or
              (member 'statement-block-intro syntax)
              (member 'brace-list-intro syntax)
              (member 'brace-list-close syntax)
              (member 'block-close syntax)))
       (save-excursion
          (beginning-of-line)
          (delete-char (* (count 'arglist-cont-nonempty syntax)
                          c-basic-offset))) )))

(add-hook 'php-mode-hook
          (lambda ()
            (add-hook 'c-special-indent-hook 'unindent-closure)))

Multimode Indentation

As I wasn’t able to find anything that would handle indentation of multilingual code properly, I wrote the Web Mixed Indentation.

It indents PHP/JavaScript/CSS/XHTML, and you can download it from

https://github.com/sabof/web-mixed-indentation-mode

It’s a minor mode, and does just that - you can use it in conjunction with any major mode.

- sabof

Try also this new indenting/coloring/syntax detection multi-mode (otherwise using std php-mode, js-mode, css-mode, etc.)

https://github.com/traceypooh/php-htm-mode

Discussion

I would like comments on both the single and multiple mode choices above. What strengths and weaknesses does the different versions have? Can they be merged? – LennartBorgman

For myself, I find that most PHP programming I do does not mix HTML and PHP code. Multiple modes are almost always a mistake … imho. – MarkAHershberger

Thanks for the comments, Mark. Multiple major modes are often not the best, but there are a lot of files that uses them.

The files don’t use multiple modes, the programmers do. I find it’s usually less of a hassle to do M-x html-mode, M-x javascript-mode, M-x php-mode etc.

How could I use c++ style comment as ‘//’ instead of the old c style ‘/* */’ to comment my codes?

How do I make a file for etags? I tried a file with all of the functions on separate lines, but it only made a TAGS file with one function.

Install exuberant-ctags, then use something like:

   etags --language-force=php `find . -name "*.php" -or -name "*.inc" -or -name "*.module" -or -name "*.theme" -or -name \
   "*.engine" -or -name "*.ini"` --language-force=JavaScript `find . -name "*.js" -and -not -name "*.min.js" -and -not -name \
   "*.pack.js" -and -not -name "*_pack.js" -and -not -name "*_stripped.js" -and -not -name "*_mini.js" -and -not -name \
   "swfobject.js" -and -not -name "cal.js" -and -not -path "*/tinymce/jscripts/*" -and -not -name "ext-*.js" -and -not -path \
   "*/files/*" -and -not -path "*/editors/jce/*" -and -not -path "*/libraries/*" -and -not -path \
   "*/modules/ckeditor/ckeditor/*" -and -not -path "*/modules/fckeditor/fckeditor/*" -and -not \
  -path "*/com_virtuemart/js/*"  -and -not -path "*/media/system/js/*" -and -not -path "misc/jquery.js"`

Can we get instructions for semantic-php-simplest-grammar.by? I’ve found lots of related info but can’t identify what is/isn’t relevant! This shows promise but only explains how to start a new language not how to use/activate them in ECB. Naturally there is a page already here on the wiki but this page is pretty much identical to CEDET’s pages referring to reading “further” in the manual.

apparently, heredoc/newdoc syntax is not recognized and auto-indentation fails badly (tab/spaces before doc-string ending, which is not allowed)


CategoryModes