It seems you're using an old browser...
We're sorry, but your browser is out of date. In order to view this site correctly, you may want to:
- Upgrade your browser to a newer version of IE.
- Try Mozilla Firefox, is fast, secure, and free!
drupal
Getting Forked
Submitted by tess on Sun, 2012-01-29 17:11Since last weekend, I spent my evenings manually moving content on deninet. It many ways, it was an exhausting process, but it gave me something to do while I suffer through the last two seasons of Star Trek: Voyager. Let me chart how I arrived at this point.
Over vacation time in December, I decided to conduct a little experiment. I would attempt to upgrade the current deninet website from Drupal 6 to Drupal 7. When I had attempted this a year ago, it did not go well. The upgrade process crashed spectactually, leaving me with a lump of a database. Thankfully I was doing this on a local copy, and not the live site. I had speculated that in the interviening year, Drupal would have ironed out a lot of the edge cases I originally ran into. So, I copied off the site and tried again. To my astonishment, it worked.
This created a dilemma. The previous year I had created a new deninet website by manually copying content from the version based on Drupal 6 to the new one based on Drupal 7. When all the features I needed to run the site were available, I'd switch to the new site. I had maintained the D7 fork from time to time, manually importing nodes and to make sure the two sites where in sync. At the time, this seemed the best way to go. I would lose things like comments and break all the URLs, but the end would be a good move.
Except that the new site never seemed to get anywhere.
I had reservations about the URLs and the comments. While I could bury my feelings, claming it was for "the greater good", it still bothered me. There was the bigger issue that I really wasn't getting anywhere with the D7 site. It sat and languished, while I couldn't resolve the issue.
After successfully upgrading the site, I began to wonder if I could take a more fluid approach. I used Pathauto to create URLs that would be the same for both the current D6 site, as well as a D7 site -- upgraded or new. The biggest problem was images.
- tess's blog
- Login to post comments
How does Drupal 7 Work? Part 4: Modules and Menus
Submitted by tess on Wed, 2011-12-21 23:24Understanding how Drupal gets from a page URL to page content is a complex topic involving many moving parts. In previous parts we've covered how Drupal initializes itself, we haven't discussed how a requested URL is routed within the CMS to the code that produces the web page. Handling this is the beating heart of Drupal -- the Menu System. Before we get to that, however, we need discussed modules. We glossed over them in the last part, but here we dive into detail.
Module Loading
It occurred to me after writing the last part of this series, I didn't go into more than high-level detail of drupal_bootstrap(). One of the biggest questions I had when I began this exploration was "How are modules loaded?" Coming from a self-taught C and C++ background, loading external code seemed a black art. Thankfully, PHP makes this very simple.
Apart from very simple applications or sample code, most programming projects are broken up into multiple files. C and C++ have a pre-processing directive called "#include". This isn't actual code, but a command sent to the compiler. What I failed to realize as I moved on to other languages -- especially those like PHP that are interpreted rather than complied -- is that PHP's method is actual code, and that's the key to how Drupal loads modules.
PHP has several ways to include a dependent file, include(), include_once(), require(), and require_once(). The difference between includes and requires is if an error is tossed if the file cannot be included. The *_once's prevent a file from being imported twice, thereby causing definition conflicts. You quickly learn that require_once() is the version you'll use the most. Another astonishing fact to C/C++ devs new to PHP is that all of these statements can accept variables.
How does Drupal load module code? Like this:
include_once($variable_of_module_file_path);
That's the core of it. You'll notice that the include_once() statement is used instead of the require_once(). This is because Drupal does not want to give you a White Screen of Death if a module's files have been misplaced. Drupal does use require_once() when loading other core files like bootstrap.inc or common.inc. After all, if those are missing, you're really in trouble!
It Can't be that Simple
You're right. It's not. While the basic idea of loading module code is an include_once() inside a foreach loop, the actual process is a bit more complicated. As we learned in the last part of this series, drupal_bootstrap() does not load all modules at once but in two distinct steps. During the DRUPAL_BOOTSTRAP_VARIABLES phase, several modules are loaded that are required for the bootstrap process to complete. If you're stepping through a default installation of Drupal, there are three bootstrap modules: devel, dblog, and overlay. The process looks like this:
drupal_bootstrap()
_drupal_bootstrap_variables()
module_load_all($bootstrap = TRUE)
module_list($bootstrap = TRUE)
Loop through list of bootstrap modules (devel, dblog, overlay)
drupal_load($type="module", $name)
We already know the first two, but the third, module_load_all() is new. This function gets a list of modules by calling module_list(). The $bootstrap parameter isn't used by module_load_all(), but is passed to module_list(), instructing it to return only bootstrap modules.
With an array of modules in hand, drupal_load() is called for each element. It checks to see if the file was already loaded, and then gets the module file name. A lot of care is taken in getting this file name and making sure that it's correct, and points to actual PHP code.
The module loading process is the same for non-bootstrap modules (including contrib modules) as it is for bootstrap modules. During the DRUPAL_BOOTSTRAP_FULL phase, a default installation of Drupal will load block, color, comment, contextual, dashboard, dblog[skipped], devel_generate, field, field_sql_storage, field_ui, file, filter, help, image, list, menu, node, number, options, overlay[skipped], path, rdf, search, shortcut, system, taxonomy, text, toolbar, update, user, devel[skipped], and standard.
Notice that in the above list, the bootstrap modules are drawn into the global module loading process. Thankfully, Drupal already knows that these modules have been loaded, and skips the process. The psudocode looks like it did earlier:
drupal_bootstrap()
_drupal_bootstrap_full()
module_load_all()
module_list($bootstrap = FALSE)
Loop through list of contrib modules
drupal_load($type="module", $name)
What about Hooks?
Loading modules isn't the only thing that's seemingly magic about modules. Module developers rely on a huge API of hooks into the Drupal process in order to add features, modify display, perform access restrictions, and so on.
It really comes down to a function called module_invoke(). It takes two parameters, the module name, and the hook to call. How it works its magic to call a function is via the PHP call_user_func_array() statement. This statement doesn't require a pointer or anything fancy to the function to invoke, just the function's name! Drupal modules implement individual hooks by creating functions with the moduleName_hookName() signature. This is very clearly represented in module_invoke():
module_invoke($moduleName, $hookName)
Get any additional unnamed $arguments as an array
If the module implements the hook
return call_user_func_array($moduleName . '_' . $hook, $arguments)
The module_invoke function actually can take more than the two named parameters thanks to PHP. These additional parameters are packaged up as array and passed to call_user_func_array(), which in turns passes the contents of the array as parameters to the hook implementation. This, and the fact that module_invoke() returns the result of the invoked hook, make it a smart function invoker cabable of working across modules.
Often in Drupal core, you do not simply invoke a single hook implementation, but call all the implementations of a hook at a single point. Handling this is a sister function to module_invoke(), module_invoke_all(). It's used the same exact way as module_invoke(), but lacks the $moduleName parameter.
Menu Routing
While modules provide Drupal's extensibility, Menu Routing does the real work of the CMS. At first blush, you may think that the "menu" refers to something like the primary and secondary links, or even the navigation block. After all, all of those are called "menus" in Drupal's own UI!
Repeat after me: Menu Routing has nothing to do with Menus, everything to do with Routing.
Page routing, specifically. The Menu [Routing] System is the core component of Drupal that takes a URL of the requested page and returns a viewable HTML web page. That is, it takes the part of the url after "?q=" in the follow example:
http://example.com/index.php?q=the/requested/page
In the above example, the page part of the URL is "the/requested/page", and this is exactly what the menu system handles. It matches up the page URL with the PHP function needed to generate the web page, and executes the function. When coding a module, the Menu System is often the first thing you'll code after an *.info. file. It's perhaps the most approachable piece of API in the entire project, which is why I bring it up here:
function motleymod_menu(){
$items[my/motley/page] = array(
'page callback' => 'motleymod_my_page',
);
return $items;
}
function motleymod_my_page(){
return "<p>This is my motley page.</p>";
}
The above code would work relatively unchanged as far back as Drupal 5.0. We have two functions, the first implements hook_menu(), and the other generates and returns the page content. You'll notice that the first function defines and returns an array with one element with the key 'my/motley/page'. As you might have guessed, this is the page URL! The content of the element is itself an array containing one element, 'Page Callback'.
The Page Callback parameter instructs Drupal what PHP function to invoke to generate the page. In this case, motleymod_my_page(), which returns raw HTML to display in the body section of the webpage. Drupal takes care of everything else -- headers, blocks, footer, and all.
But That's Not the End of the Story
If you think the above example was a little spare, you're right. Let's look at a more complex example of hook_menu():
function motleymod_menu{
$items[my/motley/page] = array(
'page callback' => 'motleymod_my_page',
);
$items[admin/config/motley] = array(
'title' => "Configure Motley Module!",
'page callback' => 'drupal_get_form',
'page arguments' => array('motleymod_admin_settings'),
'access arguments' => array('administer motleymod'),
'type' => MENU_NORMAL_ITEM,
'file' => 'motleymod.admin.inc'
);
return $items;
}
Whoa! What the heck is all that stuff? We see our original entry for 'my/motley/page', but now there's an additional entry for 'admin/config/motley'. This time, with a lot more parameters than just Page Callback:
- Title is the title of the page to display. It's used both in the <title> tag of the generated page, as well as in the <h1> tag in the body section of the page.
- Page Callback is the the magic parameter. It tells Drupal what function to call!
- Page Arguments specify the arguments to pass to the function specified in the Page Callback parameter.
- Access Arguments specify the access permissions (under admin/people/permissions) the current user must have in order to access the page.
- Type is the kind of menu item this item represents. More on that later.
- File tells Drupal in what file to find the function specified in the Page Callback parameter.
Again, we have a Page Callback, but something seems screwy: It's set to drupal_get_form() -- a function provided by Drupal itself. How the heck does that work? Over the history of Drupal, it was discovered that many module's Page Callbacks returned pages with similar structures. Furthermore, pages started falling into classifications of pages. Content pages usually have a title and a bit of text to display. Settings pages usually have a title and a form with a submit button. Drupal-provided page generators, like drupal_get_form(), handle a lot of rendering work for you, making module developer's lives a little easier. In this case, the function provides a module setting page.
menu_execute_active_handler()
Now that we have a framework, let's tie it back to where we were in our debugger. After drupal_bootstrap(), the last function called in index.php is menu_execute_active_handler(). Without any arguments, the function looks up the page URL, and then digs into the Menu System.
The first thing that it does is check if the site is "offline", that is, in Maintenance Mode. Administrators set this mode under admin/config/development/maintenance, and it temporarily blocks all other visitors save the Admin from accessing the site. This allows the Admin to perform site updates safely. If the site is offline, it doesn't matter what page was requested, all results are sent to _menu_site_is_offline(). This function checks to see if the user is the Admin, if so, normal page routing resumes.
The next thing menu_execute_active_handler() does is check if the Menu System needs to be rebuilt. This is where hook_menu() is invoked. Normally, Drupal 7 stores menu routing information in a database table -- menu_router. It does this because performing a database query is actually faster than searching through all implementations of hook_menu() to find a match. During a rebuild, the contents of menu_router are thrown out. Drupal then locks the database temporarily and recurses through each enabled module and invokes hook_menu(). This results in a huge array of menu items like we saw in the code sample above. This is then committed to the menu_router table.
After that, things get much more straightforward. The appropriate menu item is found, and the function specified in the Page Callback is called passing any Page Arguments as necessary. The result of the Page Callback is then sent to the user's browser for display.
Thirsty Yet?
After all we've covered, it's easy to simply accept that how Drupal is written is the best way it can be written. I know that when I started using Drupal, it was after I tried and failed to create my own content manager. "Let me learn from those more experienced than I!" This, however, blinded me to one of the biggest problems Drupal is facing today.
Drupal is heavy.
It used to be that each time a page was requested, you could assume that the entire page was requested. Graphics, HTML, and all. In the new world of refresh-less web apps, however, use AJAX requests to grab content or save information. Instead of sending the entire page, lighter packages of JSON formatted data are exchanged between the user's browser and the web server. While Drupal can handle these requests, it must still go through the entire initialization and routing process it would for a full web page. Worse yet, it must load all modules into memory with each request -- even if that module is not needed in that request.
I discovered this myself when I attended Crell's presentation during the Twin Cities Drupal Camp introducing the Web Services and Context Core Initiative. The goal of WSCCI (pronounced like the drink) is to ultimately replace the heavy drupal_bootstrap() and menu_router() system with a more agile core. Intead of Drupal being just a first-class CMS, it will be a REST server with a first-class CMS on top.
It's an ambitious but, I believe, necessary evolution of the platform. While targeted for Drupal 8, I have my doubts it will be fully realized until Drupal 9.
Unless we help, that is.
What's Next?
We've reached the end of index.php, but not of our series. There's still a lot more to explore, but the going gets more treacherous from here.
How does Drupal 7 Work, Part 3: drupal_bootstrap()
Submitted by tess on Mon, 2011-12-12 23:25Click here to read Part 1.
Click here to read Part 2.
When looking at Drupal code, it can be hard to know where to start. Dive into any of the directories in a standard installation, and you'll find file after file of PHP code. In the root directory alone, you'll find five files! Where do we start? Determining this is quite simpler than it seems; all you have to do is look at the URL of any Drupal site.
http://example.com/node/1234
The above is a typical URL for a Drupal site. Most Drupal sites use a feature called "Clean URLs". This removes a lot of the nuts and bolts of the address that helps us understand it. Without Clean URLs enabled, the above address looks like this:
http://example.com/?q=node/1234
Okay, that's a little helpful, but it doesn't tell us what we want to know. What file amongst all the files in Drupal do we look at? It turns out that many websites will look for a default file in the site's root directory if one isn't specified in the URL. In the Web 1.0 days, this was "index.html", for modern PHP websites this is "index.php".
Four Lines to Rule Them
When we open of index.php, one might expect a lot of code. Instead (aside from comments) you'll find four lines:
define('DRUPAL_ROOT', getcwd());
require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
menu_execute_active_handler();
The first two lines are very straightforward. The first line defines a constant, DRUPAL_ROOT, containing the file path to the Drupal installation. This constant is then used in the second line, to load bootstrap.inc in the includes/ subdirectory. Despite the file extension, bootstrap.inc contains PHP code. Drupal uses the *.inc extension to prevent files from being executed directly. This way, someone cannot plug in http://example.com/includes/bootstrap.inc and get back a valid page.
That leaves two more lines, and that's where all the fun starts. At this point we've only defined the DRUPAL_ROOT constant and imported an include file. We have yet to execute any real code. Any Drupal page request can be thought of as a two step process (if you're a core dev, insert your groans here): Initialize the Drupal environment, and then handle a page request. The third line of code, drupal_bootstrap() does the initialization -- it forges a connection to the database, loads modules, loads needed data into memory, and prepares everything for the final line of code in index.php.
The menu_execute_active_handler() function handles the page request. This is the part that takes the ?q= half of the URL and produces a web page for the visitor to see. This is actually a new function in Drupal 7. Drupal 6 preferred to bury the request handling within drupal_bootstrap(). Separating the two makes things much, much cleaner.
Making Invocation Easier
In the last article in this series, I mentioned that invoking the debugger was somewhat tricky. Eclipse assumes that any code you're debugging is in a project and not external files. It turns out that the PHP Development Toolkit actuall anticipates this problem and solves it rather easily.
- Create a new PHP project by using the File menu:
File -> New -> PHP Project - In the provided field, enter a Name of your choice that is unique within your workspace.
- Under the Contents box, select the Create Project at existing location (from existing source) radio button.
- Click the Browse button adjacent to the radio button. Select the root of your Drupal install.
- Click Finish.
This creates a new project in Eclipse importing all of Drupal's files. This mode of project creation does not create a copy of the files within the Eclipse workspace, but rather creates references to the actual files on the web server. Thus, any changes you make to the files in the Eclipse UI affect Drupal's actual files. This is great for our purpose of exploration, but can problematic. Remember, don't hack core!
Once the project is created, invoking the debugger is easy, easy, easy. Double-click index.php in the project explorer, then start the debugger with Run -> Debug As -> PHP Web Page.
Booting Up Drupal
Once you've started a new debugging session, we can dig into drupal_bootstrap(). The function looks a little circuitous at first: An array of phases is initialized, and then a while loop begins, iterating through a seven step process in which key subsystems and dependents of those subsystems are initialized in the correct order. Here's how it boils down:
- DRUPAL_BOOTSTRAP_CONFIGURATION -- Do some basic setup and load settings.php.
- DRUPAL_BOOTSTRAP_PAGE_CACHE -- If page caching is enabled, and the request is asking for a cached page, return the page.
- DRUPAL_BOOTSTRAP_DATABASE -- Connect to the database.
- DRUPAL_BOOTSTRAP_VARIABLES -- Load variables and enabled modules required for bootstrap.
- DRUPAL_BOOTSTRAP_SESSION -- Load the user's session from the DB. If the request isn't from a logged in user, return an anonymous user.
- DRUPAL_BOOTSTRAP_PAGE_HEADER -- Invoke hook_boot(), send default HTTP headers.
- DRUPAL_BOOTSTRAP_LANGUAGE -- Initialize the language system for translations.
- DRUPAL_BOOTSTRAP_FULL -- The phase name is better thought as "Last", rather than "full". Load all enabled modules. Invoke hook_init().
Why the added complexity? Why not just use a static series of functions? The initialization process can be very complicated. For example, you may be in the middle of one phase, like DRUPAL_BOOTSTRAP_PAGE_CACHE, and you'll need to load something from the database. The code that's initializing the page cache will invoke drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE). Furthermore, each phase is dependent on each preceding phase -- you cannot do the DRUPAL_BOOTSTRAP_VARIABLES phase without doing DRUPAL_BOOTSTRAP_DATABASE, DRUPAL_BOOTSTRAP_PAGE_CACHE, DRUPAL_BOOTSTRAP_CONFIGURATION. This is used by index.php itself when it calls drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL). Since DRUPAL_BOOTSTRAP_FULL is the last phase in the list, it is dependent on all previous phases.
Each phase of the bootstrap process has a lot of code behind it. While I could write an article for each, there's so much more Drupal to cover. We haven't even served a page yet! That's what we'll do next when we cover menu_execute_active_handler().
- tess's blog
- Login to post comments
How does Drupal 7 Work, Part 2: The Development Environment
Submitted by tess on Tue, 2011-11-22 23:46Click here to read Part 1 of this series.
If your'e going to debug Drupal, or any PHP project, you're going to need tools. There's more than a few options to choose from. The most basic would be instrumenting code with print() or echo() statements. While it would be serviceable, it would mean modifying core itself, and that's generally considered a Very Bad Thing. For professional development, it appears the KomodoIDE is the most popular. It's reputation is that it "just works". If I were looking into professional tools, it might be worth the $300 price tag. Given my open source, Linux using, bent, what is there?
Eclipse
The Eclipse project is a IBM-backed, Open Source Integrated Development Environment (IDE). It provides source file editing, syntax highlighting, code completion, project storage, and it's extendable through plugins. Eclipse was born out the myrad of IDEs and GUI tools that IBM provided to develop and administer their various middleware projects. IBM no longer wanted to maintain all these separate tools, and set out to create One IDE to Rule Them.
Instead of one generic interface, Perspectives provide the appropriate views, editors, and functionality suited to the project at hand. This can be as simple as different programming languages, or a separate development and administration perspectives for the same enterprise product (such as WebSphere Message Broker). While Perspectives are Eclipse's greatest feature, they also cause huge amounts of confusion for new users. IMHO, Eclipse's bad usability reputation is due to a disconnect between an enterprise IT mentality from which Eclipse hails, and the expectations of independent developers that are expecting a domain specific IDE.
This is not to say that Eclipse doesn't have problems. It's a hulking beast of a program. It takes some time to load. And yes, configuration can be weird for some users (I have sadly noted many of those users are also particularly fond of a fruity brand of consumer tech). I'm actually quite comfortable with Eclipse thanks to my background in Middleware. It runs on multiple platforms, and I can easily acquire plugins for other languages.
PHP Developer Toolkit
One of those plugins is the PHP Developer Toolkit (PDT). It extends Eclipse's functionality, providing the IDE the necessary know how to work with PHP code. This includes syntax highlighting and code completion. It's the bit that makes plain Ecplise into a PHP IDE.
There are two options to install PDT into Eclipse. You can download a pre-bundled tarball of Eclipse with PDT already installed. This is easiest for many users. The other option is install a base copy of Eclipse and then use Help -> Install New Software to install all the required modules. I prefer this method on Linux platforms as it allows Eclipse to be installed with the Linux distro's native package manager.
Some users will be shocked at just how many clicks this requires, and it is a lot. You have to select the modules, agree to the license agreement for each module, wait for it to download, then restart the IDE. As enterprise software goes, this is a cakewalk. The record holder for installation time I've worked with was three weeks. And no, you don't want to know what the installer looked like and how many clicks it requires.
XDebug
One component that PDT does not supply, is a debugger. I've never used a debugger with PHP before. Before I started using Drupal -- when I did most of my PHP coding -- they didn't even have debuggers. I needed something that was relatively easy to install, something current, and something open source. XDebug hit the sweet spot.
XDebug also has a bad rap among Drupal developers. It's often thought of too complicated to install, too fritzy, and does not work consistently.
I had XDebug working in 10 minutes flat.
How did I pull this off? XDebug only provides binaries for Windows systems, and source for all other platforms. Given the predominance of fruity computers in Drupal development, it's no surprise to me that attempting to build XDebug from source is a huge hurdle. (Besides, if you can afford one of their systems, why not plunk down $300 for the KomodoIDE?)
Being an FLOSS wackaloon, I use Linux. XDebug doesn't provide binary builds for Linux either, but that's not the end of the story. Many distros of Linux will provide a build of XDebug in their package manager. The distro I'm currently fond of is Arch, a rolling-release distro that does not even provide a graphical installer. Arch provides a build of XDebug in the Arch User Repository (AUR). I needed to only run the AUR wrapper script to install XDebug.
Getting XDebug and Eclipse PDT to Play Nice
XDebug is actually an Apache 2 module. You configure it as you would any other Apache module. When initiating a debug session, a $_GET variable is passed containing the debug session key. The PDT knows how to issue that key, so all you need to do is configure Eclipse to use XDebug.
First of all, you will need to configure Apache to use XDebug correctly. When I tried this, it turned out that AUR did all the work for me. However, you can hit up this page for a solid reference for getting XDebug up on Arch. Once configured, restart Apache.
Now Eclipse needs to be configured. This is best described as clumsy.
- Go to Window -> Preferences to open the Preference window.
- Expand the tree view on the left and select PHP -> Debug.
- Select the PHP Debugger as XDebug. If this option is not available, click the Configure link to the right of the pop-up menu and add the configuration. The default port of XDebug is 9000.
- Click the PHP Servers link. Add your server (localhost is OK!). Select your new server in the Servers popup menu.
- Click the PHP Executables link. Add a new PHP executable configuration with the following options:
- Set the Executable Path to /usr/bin/php. This is the default for Arch. Your distro may vary.
- Set the PHP ini file to /etc/php/php.ini. This is the default for Arch.
- Select the SAPI type to CLI.
- Select the PHP Debugger as XDebug.
- Return to the Preferences window. Click OK.
Initiating a Debug Session
I admit this one is more fussy than I had wanted, mostly because for this project I'm not developing any code. Eclipse PDT assumes that you have created a project with code to debug. When initiating a debug session, the expected workflow is to open the source file you intend to debug. Then select Run -> Debug As -> PHP Web Server. This switches Eclipse to the PHP Debug Perspective, and loads the file path you entered in step 4 above, passing the all important debug session key.
Currently, I have a project set up for a patch to Organic Groups. When I invoke Debug as PHP Web Server, it attempts to load the project file path, og-rules-patch/og.module, on the webserver, http://localhost/og-rules-patch/og.module. This would obivously result in a 404, but that's all that we need to start exploring!
Once we drop into the debugger, we can start stepping through Drupal code. Our first stop is how Drupal initializes -- drupal_bootstrap(). That's where we'll pick up next time.
- tess's blog
- Login to post comments
How does Drupal 7 Work, Part 1: Who? Why? How?
Submitted by tess on Sat, 2011-11-19 21:56Overview
This post is intended to be the beginning of a series of regular blog entries exploring the innermost guts of the Drupal CMS. We'll take a copy of Drupal, a mocked up website, and a debugger, and step through initialization and requests. We'll get to the heart of how it really, really works.
Introduction
Drupal powers millions of sites around the web. It's a flexible, extenable open source content managment system you can run on multiple platforms. Drupal site admins can select modules from the some 13000+ available on Drupal.org. With Drupal, you can build the kind of site you need, from personal web pages to sprawling enterprise information portals.
Like so many people, I've spent much more time using drupal, than exploring it's API, or even digging into how the thing actually works. I switched to drupal sometime in 2006 after running my own, homebrew CMS for years. I had a new job in the Enterprise Middleware industry, and I found my time for software development decidedly spare. Drupal was a time saver, often to excess.
Sometimes I'd need a particular feature for deninet, and often, "there's a module for [it]". I'd need only to download the appropriate code and configure it as I saw fit. For those times no module did exist, I wouldn't need to wait long. Every time after I started writing a module, life would interveine, and upon returning weeks later someone else had already created the same thing. One might think this was wonderful, but I found it profoundly frustrating. I believe in open source; it's not about free stuff. It's about pooling our expertise to build great solutions for everyone to use.
And I wanted to contribute.
For years, however, something hampered me that I could only describe recently. While my spare free time is always a factor, what really bothered me is that I don't "own" the code. When I was writing my own CMS, I understood it from the bottom up. I knew every class, interface, and design decision. It was my code, and I knew how to extend it. While that attitude works great when you're working alone, but not with a developer community as large as Drupal. No one person owns the project in a possessive sense (not even Dries). Nevertheless, no matter how many module development books I read, or API docs I committed to memory, I did not feel grounded. I did not feel I "owned" the code, and I was always nervous about my lack of understanding. That feeling, more than anything, put me off any sort of contribution.
When I realized my fundemental hangup, what I needed to do became clear. "Obviously," I thought, "I need to 'own' the code. I need to know how Drupal works." Not just conceptually, not just the pale description of a hook in the Module Dev guide. I need to know where that hook is, how it's invoked, and why it's written that way.
Who are you?
Before anyone gets ideas about just what my knowledge or experience is with reguards to Drupal, let's set the record straight:
- I am not a core maintainer.
- I have not written core patches.
- I have not written any modules (although I tried!).
- I have contributed module patches -- 2.
- I have written code in C, C++, C#, PHP, and Python on more than half a dozen platforms.
- I have written my own CMS, but I don't use it anymore, and no one else ever has.
- I was a middleware consultant and enterprise software trainer.
- I am a award winning enterprise software courseware developer.
Why do this?
In addition to simple curiousity, I feel I can learn a great deal from how Drupal is written. There are some very sharp people working on this project, but the list of core maintainers has dwindled as the complexity of Drupal shot up over the last few versions. Soon, the project will be facing a crisis of too many feature requests, and not enough maintainers.
I want to work in open source. As I said earlier, I believe in open soruce and rely on it where I can. While I've built my career thusfar in the proprietary space, I'd love to contribute back to the community from which I have benefitted. If I can make a modest living from that, I'd consider myself extraordinarily fortunate. Drupal is the project with which I have the most familiarity.
While I intended to do this just for myself, it occurred to me that others would benefit from my explorations. I write software training materials for my day job, after all. Furthermore, it would serve as a reference for myself.
How are you going to do this?
I have a copy of Drupal running on a LAMP stack. I will use the Eclipse Project with PDT as development toolkit, and XDebug as a PHP debugger. I'll do all of this from a laptop running Arch Linux 64-bit. Configuration was simpler than I expected thanks to the Arch User Repository (AUR). Beyond that, I have the API website and my wits.
Latest Images
- 1 of 318
- ››
Recent Activity
- 1 of 183
- ››





Recent comments
7 weeks 1 day ago
7 weeks 6 days ago
13 weeks 1 day ago
20 weeks 4 days ago
29 weeks 1 day ago
45 weeks 1 day ago
46 weeks 1 day ago
1 year 27 weeks ago
1 year 31 weeks ago
1 year 32 weeks ago