Blogs

Where to find me

You can

Quick guide to wildcard Apache vhosts

[Edit: Added wildcard DNS section at the end]

After my Debugging Drupal talk at Copenhagen today a lot of people wanted to know how to use a wildcard virtualhost, so I promised a quick writeup.

The purpose here is to be able to deploy new virtualhost-style Drupal sites on your localhost without doing any apache configuration (or /etc/hosts, if you deploy a nameserver).

Most of the time Drupal works better (and more like your production site) if you run it as a production site. If I have a site like debugging_example.com, I run it locally as debugging_example.l. That's way better than localhost/debugging_example, because all the URLs work right, and it's clean URLs.

The basic idea of what you have to do:

  • Enable mod_vhost_alias in Apache
  • Configure a catchall virtualhost
  • Tweak your .htaccess by uncommenting one line
  • Make an entry in your /etc/hosts

Here's the quick version of how to do it:

  1. Enable the mod_vhost_alias Apache module with sudo a2enmod mod_vhost_alias (on Debian/Ubuntu, or however on your environment).
  2. /etc/init.d/apache2 restart
  3. Configure your httpd.conf or apache2.conf or whatever to provide a catchall. I use Debian/Ubuntu, and this is done with:
    • Create the file /etc/apache2/sites-available/catchall. Here is my catchall. You'll note you have to change the base path.
    • a2ensite catchall
    • /etc/init.d/apache2/reload
  4. Make an entry in your hosts file for the virtualhost you want to use.
  5. In your drupal .htaccess, uncomment the line that says
    # RewriteBase /
    so it says instead:
    RewriteBase /
  6. And if you are ambitious and don't like adding each entry to /etc/hosts, here's a crude recipe for running bind9 (debian/ubuntu) to automatically resolve anything. I use *.l:

    • /etc/bind/named.conf.local, add
      zone "l" {
              type master;
              file "/etc/bind/db.l";
              notify no;
      };
    • Add the file /etc/bind/db.l, adjusted for your use:
      $ttl 38400
      @ IN SOA l.l. admin.l. (
      2009091700
      10800
      3600
      604800
      38400 )
      l. IN NS localhost.
      *.l. IN CNAME localhost
    • Change your computer to use localhost to resolve names. You can do this in the network config applet.

Cygwin Quickstart for Drupal Users

Cygwin is a great set of Unix/Linux utilities for Windows. Here are quickstart instructions for using it in a Drupal context (for patch, cvs, git, or whatever)

  • Grab the small setup.exe from http://cygwin.com
  • Run it. If you're on Windows Vista or later, you'll want to run the setup with administrative privileges (Right click on setup.exe and "Run as administrator")
  • Take all the defaults - we'll end up with an install in c:\cygwin
  • When you get to the package selection screen, select at least: openssh, cvs, git, rxvt, patch, patchutils, unzip, nano, vim, wget. Then let it download and install.
  • Run "Rxvt Native" from the start menu. (If on Vista or later, you need to run it as administrator this time because we'll be setting up links in a privileged directory). The first time you do this it will install default profile files for you.
  • In rxvt we'll now set up symbolic links to the Windows filesystem. Do this for each drive you have... I'm showing the C: and D: drives here:
    cd /
    ln -s /cygdrive/c
    ln -s /cygdrive/d
  • Now you can navigate into the Windows filesystem to wherever your Drupal install is. /c is the root of the C: drive; /d is the root of the D: drive. For example, if you have Acquia's DAMP installed, it might be in /c/Users/rfay/Documents/Sites/acquia-drupal or something like that.
  • Using cvs, you could check out the Examples project, for example:
    export CVSROOT=:pserver:anonymous@cvs.drupal.org:/cvs/drupal-contrib
    cvs login (your password is 'anonymous')
    cvs -z6 checkout -d examples-HEAD contributions/modules/examples

    and now you have a HEAD version of Examples.
  • Using git you could get Examples from git.drupalfr.org:
    git clone git://git.drupalfr.org/git/contributions-new-date/examples.git
  • Or apply a patch using patch.... or create a patch using git diff --no-prefix...

The world is your oyster. You have the easy-to-use editor nano if you want to edit within Cygwin, but you can just use the Windows editor of your choice as well.

You may also want to watch the Lullabot video on installing Cygwin, which is old, but still useful and valid.

What's wrong with Mollom?

So Mollom absolutely stinks, as far as I'm concerned.

I just posted this comment on a site that is not mine, but is a Drupal site running Mollom: http://www.istos.it/blog/drupal-training/open-sourcing-drupal-training:

The Examples for Developers project is an open-source training initiative. I'm trying to get it used for developer training and to have books on Drupal development use it for examples instead of rolling their own (which invariably get out-of-date and can't be maintained.)

I encourage you in this (vast) initiative.

And what did I get?

Your submission has triggered the spam filter and will not be accepted.

That's about the fourth time I've taken the time to write a comment on a Drupal Mollom-enabled site, and gotten that kind of a response. How many comments are being rejected inappropriately on sites that use Mollom? Who will ever know?

At the same time, the only site that I have Mollom on, http://hobobiker.com, gets has spam comments approved daily. In fact, it never gets anything *but* spam comments, and Mollom seems OK with that.

What's up with Mollom? This is not good.

Eclipse Debugging with Zend Debugging Extension for PHP 5.3: New location for downloads

New URL for Zend debugging plugin (now called Studio Web Debugger)

If you're a user of Eclipse with the Zend Debugging Extension and you've tried to use PHP 5.3, you may have noticed that the traditional download location doesn't have it.

The new location for downloading the Zend debugging extension is http://www.zend.com/products/studio/downloads. Get the "Studio Web Debugger" for your platform and architecture (requires registration). (Note that the old location for this was http://downloads.zend.com/pdt/server-debugger/, which is still referred to on many places on the web. This old location has libraries only up through PHP 5.2, but if that's all you need, will work fine.)

Basic debugging with Eclipse Galileo is covered in http://drupal.org/node/157609.

That was the main news. But to make sure it actually worked I did a quick runthrough of installing Eclipse Galileo on Ubuntu 10.04 Lucid Lynx from scratch. This is essentially the same as what's in http://drupal.org/node/157609, but with less detail.

Bonus: Quick install of Eclipse Galileo with debugger on Debian/Ubuntu

  1. Install the Zend debugging extension obtained above by downloading the correct package for your system and architecture. Follow the instructions in the installation file to install on your architecture. More details are at http://drupal.org/node/157609. Verify that phpinfo shows the "Zend Debugger".
  2. apt-get install eclipse
  3. In Eclipse, go to Help->Install New Software
  4. Type "Galileo" and choose the Galileo update site
  5. Expand "Web, XML, and Java EE development to get to "PHP Development Tools (PDT)" and install it.
  6. Now, add the Drupal PHP extensions (at least *.module, *.theme, *.test) to the PHP content type in Window->Preferences->General->Content Types.

Now set up a project in an Eclipse workspace:

(For examples in the below: I let Eclipse create the default ~/workspace, then I installed Drupal in ~/workspace/d7git, and made a virtualhost http://d7git.l that points to it.)

When you run Eclipse, it asks where you want the workspace. Just let it have its way and put it in ~/workspace.

Put the project you want to debug in the workspace (I created a Drupal install in ~/workspace/d7git)

Create a new project with File->New Project->PHP Project and give it the name of the directory of your project in ~/workspace. (I created the project "d7git", which absorbed my existing code.)

Debug Button -> Debug Configurations, Create a new "PHP Web Page" configuration.

  1. Give it a name (I called it d7git)
  2. For Server Debugger, choose Zend
  3. If you use virtualhosts like I do, you need to create a new PHP server at this point. Click new, and give it the URL. For example, I created a new PHP server called d7git and used the URL http://d7git.l and pressed "Finish".
  4. For the file, choose index.php
  5. Uncheck "Auto Generate" for the URL and change the URL to http:/// (I changed it to http://d7git.l)
  6. Click "Debug" and if you have succeeded, it will stop on the first line of index.php.

Pointers to key pages on debugging with Eclipse

Form API Changes for Drupal 7, Part 1: $form_state changes

You may know that lots of delicious things have happened to Drupal's Form API in Drupal 7. (Only a geek can say "delicious" and "Form API" in the same sentence. Try it!) The finest minds in the business have been working on it, I can assure you. Give effulgentsia, fago, frando, and chx a big hug when you see them, because Form API is much improved. (Sorry to those of you I forgot to name, but THANKS!)

I'm going to do a series covering Form API changes, starting with this one. I won't attempt to cover the deep details, just the things that ordinary developers might use:

  1. $form_state changes and form builder function signature changes
  2. AJAX Forms changes
  3. New properties (#attached and many friends)

Let me know if you have other topics to suggest.

OK, to business. This article is mostly parroted from the api.drupal.org topic: Form Generation. Thanks to Alex Bronstein (effulgentsia) for his reviews and contributions to that doc.

Don't forget that the form builder function signature changed!

In Drupal 6 the form builder function looked like this:

function my_module_funky_form(&$form_state) { ... }

but in Drupal 7 it's
function my_module_funky_form($form, &$form_state, ... ) { ... }

$form_state in Drupal 7

Mostly the members of the $form_state array are the same ones you know and love from Drupal 6:

  • $form_state['values']: An associative array of values that have been submitted to the form. The validation and submit functions use this array for nearly all their decisionmaking. (Note that #tree determines whether the values are a flat array or an array whose structure parallels the $form array.) This is nearly the same as it was in D6.
  • $form_state['rebuild']: If the submit handler sets $form_state['rebuild'] to TRUE, submission is not completed and instead the form is rebuilt using any information that the submit function has made available to the form builder function via $form_state. This is commonly used for wizard-style multi-step forms, add-more buttons, and the like. For further information see drupal_build_form(). This is the same as D6.
  • $form_state['redirect']: a URL that will be used to redirect the form on submission. See drupal_redirect_form() for complete information. This should always be used instead of drupal_goto() in a forms context. Note that $form['#redirect'] went away in Drupal 7 and no longer has any effect.
  • $form_state['storage']: $form_state['storage'] is no more! It used to be the place for application-specific values, but now it has no specific meaning. Now nearly all $form_state keys persist in a multi-step form, so the recommended approach is to use $form_state['your_module']['whatever']. ($form_state['storage'] still works for persistent storage, just like $form_state['timbuktu'] works.)
  • $form_state['triggering_element': (read-only) The form element that triggered submission. This is the same as the deprecated $form_state['clicked_button']. It is the element that caused submission, which may or may not be a button (in the case of AJAX forms.) This is often used to distinguish between various buttons in a submit handler, and is also used in AJAX handlers.
  • $form_state['cache']: The typical form workflow involves two page requests. During the first page request, a form is built and returned for the user to fill in. Then the user fills the form in and submits it, triggering a second page request in which the form must be built and processed. By default, $form and $form_state are built from scratch during each of these page requests. In some special use-cases, it is necessary or desired to persist the $form and $form_state variables from the initial page request to the one that processes the submission. A form builder function can set 'cache' to TRUE to do this. One example where this is needed is to handle AJAX submissions, so ajax_process_form() sets this for all forms that include an element with a #ajax property. (In AJAX, the handler has no way to build the form itself, so must rely on the cached version created on each page load, so it's a classic example of this use case.) Note that the persistence of $form and $form_state across successive submissions of a multi-step form happens automatically regardless of the value for 'cache'. You probably won't need to use $form_state['cache']. And note that $form['#cache'] is gone in D7 and now has no effect on anything.
  • $form_state['input']: The array of values as they were submitted by the user. These are raw and unvalidated, so should not be used without a thorough understanding of security implications. In almost all cases, code should use the data in the 'values' array exclusively. The most common use of this key is for multi-step forms that need to clear some of the user input when setting 'rebuild'.

Drupal 7 FAPI Resources:

Next time: Part 2: AJAX forms changes. See AJAX Forms in Drupal 7 if you're in a hurry.

Translatable Regions Module: For user-contributed content in many languages

Drupal is *great* at handling multilingual situations, but how do you make user-contributed content in multiple languages accessible to those who can't read them?

The Translatable Regions module tackles this by using the automated Google AJAX Language API via the jquery-translate plugin.

What do you have to do?

  • Install the module.
  • Decide what selectors you want to have translation buttons.
  • Configure the selectors at admin/settings/translatableregions.

Whenever those selectors appear on the page, a button is added offering to translate to many languages, the default being the browser language.

Here's an example of the use on user profiles on http://warmshowers.org.

To see live user-generated content translation, to go The Portuguese-language forums on Warmshowers.org.

New Queue and Menu Examples for Examples Project

The Examples for Developers Project aims to provide high-quality, well-documented API examples for a broad range of Drupal core functionality. You can download the code from the project page, view it on api.drupal.org, or experience it (for several of them) at drupalexamples.info.

Recently, we've added two new example suites:

Examples for Developers is a community project. Contributions are encouraged (just use the issue queue). If you find a problem, please submit an issue. If you want to fix a problem you find, please submit a patch. It will never be perfect, but if we tend it as a community resource, it should get better all the time.

PHP 5.2 on Ubuntu 10.04 Lucid Lynx

Lots of us are starting to run Drupal on Ubuntu 10.04 Lucid Lynx, and of course, Lucid comes with PHP 5.3, for which Drupal 6 is not yet ready.

I've seen a couple of fine recipes, but here's mine, with the files you need attached.

Update: You'll probably want to look at Khalid's more extensive discussion of various ways to do this.

Essentially, all you have to do is tell the apt system where to find Karmic packages and then tell it that you want it to use Karmic's PHP packages.

So put the attached karmic.list in /etc/apt/sources.list.d and the attached "php" into /etc/apt/preferences.d.

Then:

sudo apt-get update
sudo apt-get remove php5 libapache2-mod-php5 php5-xsl php5-gd php-pear php5-mysql php5-curl php5-memcache
sudo apt-get install php5 libapache2-mod-php5 php5-xsl php5-gd php-pear php5-mysql php5-curl php5-memcache

If you had not already installed apache, php, and mysql, you can do that with the above files in place and get the right versions without removing anything:

sudo apt-get install apache2 mysql-server php5 libapache2-mod-php5 php5-xsl php5-gd php-pear libapache2-mod-auth-mysql php5-mysql php5-curl php5-memcache

Examples Project Code Sprint

Tomorrow (Thursday, 22 April) we'll be working 9-5 US Pacific time on the Examples Project. A list of tasks is posted on groups.drupal.org and there's plenty of fun for everybody. We'd love to have you join us wherever you are in the world, or physically at the Drupalcon sprint location.

Syndicate content