Saturday, April 10, 2010

Start with URL Rewriting

An Introduction to Rewriting



Readable URLs are nice. A well designed website will have a logical file system layout, with smart folder and file names, and as many implementation details left out as possible. In the most well designed sites, readers can guess at filenames with a high level of success.



However, there are some cases when the best possible information design can’t stop your site’s URLs from being nigh-on impossible to use. For instance, you may be using a Content Management System that serves out URLs that look something like



http://www.example.com/viewcatalog.asp?category=hats&prodID=53



This is a horrible URL, but it and its brethren are becoming increasingly prevalent in these days of dynamically-generated pages. There are a number of problems with an URL of this kind:




  • It exposes the underlying technology of the website (in this case ASP). This can give potential hackers clues as to what type of data they should send along with the query string to perform a ‘front-door’ attack on the site. Information like this shouldn’t be given away if you can help it.



    Even if you’re not overly concerned with the security of your site, the technology you’re using is at best irrelevant — and at worst a source of confusion — to your readers, so it should be hidden from them if possible.



    Also, if at some point in the future you decide to change the language that your site is based on (to » PHP, for instance); all your old URLs will stop working. This is a pretty serious problem, as anyone who has tackled a full-on site rewrite will attest.



  • The URL is littered with awkward punctuation, like the question mark and ampersand. Those & characters, in particular, are problematic because if another webmaster links to this page using that URL, the un-escaped ampersands will mess up their XHTML conformance. They will have to laboriously replace all the ampersands with & character entities, which is often forgotten.


  • Some search engines won’t index pages which they think are generated dynamically. They’ll see that question mark in the URL and just turn their asses around.



Luckily, using rewriting, we can clean up this URL to something far more manageable. For example, we could map it to



http://www.example.com/catalog/hats/53/



Much better. This URL is more logical, readable and memorable, and will be picked up by all search engines. The faux-directories are short and descriptive. Importantly, it looks more permanent.



To use mod_rewrite, you supply it with the link text you want the server to match, and the real URLs that these URLs will be redirected to. The URLs to be matched can be straight file addresses, which will match one file, or they can be regular expressions, which will match many files.



Basic Rewriting



Some servers will not have » mod_rewrite enabled by default. As long as the » module is present in the installation, you can enable it simply by starting a .htaccess file with the command



RewriteEngine on



Put this .htaccess file in your root so that rewriting is enabled throughout your site. You only need to write this line once per .htaccess file.



Basic Redirects



We’ll start off with a straight redirect; as if you had moved a file to a new location and want all links to the old location to be forwarded to the new location. Though you shouldn’t really ever » move a file once it has been placed on the web; at least when you simply have to, you can do your best to stop any old links from breaking.




RewriteEngine on

RewriteRule ^old\.html$ new.html



Though this is the simplest example possible, it may throw a few people off. The structure of the ‘old’ URL is the only difficult part in this RewriteRule. There are three special characters in there.




  • The caret, ^, signifies the start of an URL, under the current directory. This directory is whatever directory the .htaccess file is in. You’ll start almost all matches with a caret.

  • The dollar sign, $, signifies the end of the string to be matched. You should add this in to stop your rules matching the first part of longer URLs.

  • The period or dot before the file extension is a special character in regular expressions, and would mean something special if we didn’t escape it with the backslash, which tells Apache to treat it as a normal character.




So, this rule will make your server transparently redirect from old.html to the new.html page. Your reader will have no idea that it happened, and it’s pretty much instantaneous.



Forcing New Requests



Sometimes you do want your readers to know a redirect has occurred, and can do this by forcing a new HTTP request for the new page. This will make the browser load up the new page as if it was the page originally requested, and the location bar will change to show the URL of the new page. All you need to do is turn on the [R] flag, by appending it to the rule:




RewriteRule ^old\.html$ new.html [R]



Using Regular Expressions



Now we get on to the really useful stuff. The power of mod_rewrite comes at the expense of complexity. If this is your first encounter with regular expressions, you may find them to be a tough nut to crack, but the options they afford you are well worth the slog. I’ll be providing plenty of examples to guide you through the basics here.



Using regular expressions you can have your rules matching a set of URLs at a time, and mass-redirect them to their actual pages. Take this rule;




RewriteRule ^products/([0-9][0-9])/$ /productinfo.php?prodID=$1



This will match any URLs that start with ‘products/’, followed by any two digits, followed by a forward slash. For example, this rule will match an URL like products/12/ or products/99/, and redirect it to the PHP page.



The parts in square brackets are called ranges. In this case we’re allowing anything in the range 0-9, which is any digit. Other ranges would be [A-Z], which is any uppercase letter; [a-z], any lowercase letter; and [A-Za-z], any letter in either case.



We have encased the regular expression part of the URL in parentheses, because we want to store whatever value was found here for later use. In this case we’re sending this value to a PHP page as an argument. Once we have a value in parentheses we can use it through what’s called a back-reference. Each of the parts you’ve placed in parentheses are given an index, starting with one. So, the first back-reference is $1, the third is $3 etc.



Thus, once the redirect is done, the page loaded in the readers’ browser will be something like productinfo.php?prodID=12 or something similar. Of course, we’re keeping this true URL secret from the reader, because it likely ain’t the prettiest thing they’ll see all day.



Multiple Redirects



If your site visitor had entered something like products/12, the rule above won’t do a redirect, as the slash at the end is missing. To promote good URL writing, we’ll take care of this by doing a direct redirect to the same URL with the slash appended.




RewriteRule ^products/([0-9][0-9])$ /products/$1/ [R]



Multiple redirects in the same .htaccess file can be applied in sequence, which is what we’re doing here. This rule is added before the one we did above, like so:




RewriteRule ^products/([0-9][0-9])$ /products/$1/ [R]

RewriteRule ^products/([0-9][0-9])/$ /productinfo.php?prodID=$1



Thus, if the user types in the URL products/12, our first rule kicks in, rewriting the URL to include the trailing slash, and doing a new request for products/12/ so the user can see that we likes our trailing slashes around here. Then the second rule has something to match, and transparently redirects this URL to productinfo.php?prodID=12. Slick.



Match Modifiers



You can expand your regular expression patterns by adding some modifier characters, which allow you to match URLs with an indefinite number of characters. In our examples above, we were only allowing two numbers after products. This isn’t the most expandable solution, as if the shop ever grew beyond these initial confines of 99 products and created the URL productinfo.php?prodID=100, our rules would cease to match this URL.



So, instead of hard-coding a set number of digits to look for, we’ll work in some room to grow by allowing any number of characters to be entered. The rule below does just that:




RewriteRule ^products/([0-9]+)$ /products/$1/ [R]



Note the plus sign (+) that has snuck in there. This modifier changes whatever comes directly before it, by saying ‘one or more of the preceding character or range.’ In this case it means that the rule will match any URL that starts with products/ and ends with at least one digit. So this’ll match both products/1 and products/1000.



Other match modifiers that can be used in the same way are the asterisk, *, which means ‘zero or more of the preceding character or range’, and the question mark, ?, which means ‘zero or only one of the preceding character or range.’



Adding Guessable URLs



Using these simple commands you can set up a slew of ‘shortcut URLs’ that you think visitors will likely try to enter to get to pages they know exist on your site. For example, I’d imagine a lot of visitors try jumping straight into our stylesheets section by typing the URL http://www.yourhtmlsource.com/css/. We can catch these cases, and hopefully alert the reader to the correct address by updating their location bar once the redirect is done with these lines:




RewriteRule ^css(/)?$ /stylesheets/ [R]



The simple regular expression in this rule allows it to match the css URL with or without a trailing slash. The question mark means ‘zero or one of the preceding character or range’ — in other words either yourhtmlsource.com/css or yourhtmlsource.com/css/ will both be taken care of by this one rule.



This approach means less confusing 404 errors for your readers, and a site that seems to run a whole lot smoother all ’round.

Wednesday, March 3, 2010

iPhone development with PHP and XML

Building the command list



Building the application starts with defining some commands that the iPhone remote
control will present for you to select. You use an XML file to define the
commands. Listing 1 shows this file.



Listing 1. commands.xml
                
<commands>
<command title="Next Song">
tell application "iTunes" to next track
</command>

<command title="Previous Song">
tell application "iTunes" to back track
</command>
</commands>


The file is a list of <command> tags. Each tag has
a title attribute that defines a human readable title for the command. And the
content of the <command> tag is the AppleScript
code to execute when the command is requested. Because of XML encodings, if you
want to put in any AppleScript code that has angle bracket (< or >) or
ampersand (&) characters, you must encode those as <,
>, and &, respectively.



To wrap this XML file, I wrote a PHP V5 Command class
that reads the file, returns the command names, and runs the commands using the
Mac OS X osascript command. The code for this class is
shown in Listing 2.



Listing 2. commands.php
                
<?php
class Commands
{
private $_commands;

function __construct()
{
$this->_commands = array();

$doc = new DOMDocument();
$doc->load('commands.xml');
$cmds = $doc->getElementsByTagName( 'command' );
foreach( $cmds as $cmd )
{
$this->_commands []= array(
'title' => $cmd->getAttribute('title'),
'command' => $cmd->firstChild->nodeValue
);
}
}

function getCommands()
{
$cmds = array();
foreach( $this->_commands as $cmd )
{
$cmds []= $cmd['title'];
}
return $cmds;
}

function runCommand( $id )
{
$ph = popen( "osascript", "w" );
fwrite( $ph, $this->_commands[$id]['command'] );
fclose( $ph );
}
}
?>




The class starts by loading up the commands.xml file. It reads in the file using the
DomDocument PHP class. Then, it finds all the command
arguments using getElementsByTagName. When it has the
<command> tags as an array, the class loads the
_commands member variable with the titles and
AppleScript commands.


Two additional methods are defined:




  • The getCommands() method, which simply returns a list of the names

  • The runCommand() method, which given an index runs that command using the osascript command-line AppleScript executor.




Building the interface


With the commands XML file and Commands PHP class written,
it's time to add an interface. Just to make sure everything is
working properly, I'll put a fairly rudimentary interface on it. This interface is
shown in Listing 3.



Listing 3. Simple interface script
                

<html><body>
<?php
require_once('commands.php');
$cmds = new Commands();
?>
<?php
$id = 0;
foreach( $cmds->getCommands() as $cmd ) {
?>
<a href="do.php?id=<?php echo($id);?>"><?php echo( $cmd ); ?></a><br/>
<?php $id++; } ?>

</body></html>


The script first gets the Command class, and then asks it
for the lists of commands using the getCommands() method.
Then, the script builds a set of links to the do.php page using the command index
number and the name of the command that the Commands
class returned.



When I navigate to the page in the Safari browser, I see something like
Figure 1.




Figure 1. The rudimentary interface

The rudimentary interface



I could use this as my iPhone interface and it would work. But it wouldn't feel like
the iPhone. So, the next thing to do is use the iUI toolkit to extend the interface.
Listing 4 shows the code for doing so.




Listing 4. index.php
                
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<title>Mac Controller</title>
<meta name="viewport"
content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=no;"/>
<style type="text/css" media="screen">@import "iui/iui.css";</style>

<script type="application/x-javascript" src="iui/iui.js"></script>
</head>
<body>
<div class="toolbar">
<h1 id="pageTitle"></h1>
<a id="backButton" class="button" href="#"></a>

</div>
<?php
require_once('commands.php');
$cmds = new Commands();
?>
<ul title="Commands" selected="true">
<?php
$id = 0;
foreach( $cmds->getCommands() as $cmd ) {
?>
<li>
<a href="do.php?id=<?php echo($id);?>"><?php echo( $cmd ); ?></a>

</li>
<?php $id++; } ?>
</ul>
</body></html>



At the top of the file, you include the iUI CSS file that has all the styles that
give the page its iPhone look. Then, you include the iUI JavaScript file that
handles all the interactivity. After that, you use the Commands
class to get the list of commands. With that list, you build an unordered list
(<ul>) with list item elements for each item
(<li>). No, it's not as ugly as it sounds. In
fact, you can look at it in Safari, and you'll get exactly the same look as you
would on the iPhone, as shown in Figure 2.





Figure 2. The index.php page as rendered in Safari

The index.php page as rendered in Safari



If you use Windows, don't worry: Safari now runs on both Windows and Mac. Of
course, the PHP that runs this code must be on a Mac to run the
osascript command and the AppleScript code. But you
could use system commands if you want to run this on DOS or UNIX® systems.



The final step is to create the do.php file that index.php references to run the
actual commands. This class is shown in Listing 5.




Listing 5. do.php
                
<?php
require_once('commands.php');

$cmds = new Commands();
$cmds->runCommand( $_GET['id'] );
?>


Now, you can use Safari to browse to the page locally and just click the links to
check whether the application works. If everything is in order, iTunes
will go to the next or previous song depending on what you select.


One thing I did have to change on my installation was to edit the /etc/httpd/httpd.conf
file, change the User setting to my user name, and change the Group

setting to staff. I then rebooted my Apache server by running this command
line:


% apachectl graceful


With that done, my iTunes interface flipped back and forth between tracks when I
clicked the links. I can then turn on my iPhone and use the Safari browser to go
to my local machine by IP address and access the application, as long as my laptop
and my iPhone are on the same Wi-Fi network.



Telekenesis



As I did the research for this article, I found that someone had already taken
this whole concept of a Mac-driven remote for the iPhone to a new level. The project
is called telekinesis, and it's
hosted on the Google Code site. The application is called iPhone Remote, and
it runs as a graphical user interface (GUI) application in Mac OS X.



When I launch iPhone Remote, it opens Safari to a page that shows what it will look
like on the iPhone. This is shown in Figure 3.




Figure 3. The iPhone Remote interface

The iPhone Remote interface


From here, I can navigate to my applications and open them, browse my documents, use
an iTunes remote, even navigate around the screen and run command lines—all
from my iPhone.


The iPhone Remote does prompt you for a user name and password so that not just
anyone can use your Mac after you've installed and run it. So, it's possible to
use the iPhone as a secure virtual network computing (VNC) device for your Mac
remotely.




Conclusion






Developing for the iPhone is a breeze. The ads say that the iPhone gives you access
to the Internet as is rather than some mobile version of it, and the ads are right:
You can browse to your normal pages just as you would on your Mac or PC. But
toolkits like the iUI interface builder help give the application a more genuine
iPhone look and feel—handy with applications like this XML
and PHP-driven iPhone remote.

Thursday, February 25, 2010

Easy steps to install smarty for your application


This is a simple guide to get Smarty setup and running quickly. The online
documentation includes a very thorough explanation of a Smarty installation.
This guide is meant to be a quick and painless way of getting Smarty working,
and nothing more. The guide assumes you are familiar with the UNIX system
environment. Windows users will need to make adjustments where necessary.

INSTALL SMARTY LIBRARY FILES

Copy the Smarty library files to your system. In our example, we place them in
/usr/local/lib/php/Smarty/

$> cd YOUR_DOWNLOAD_DIRECTORY
$> gtar -zxvf Smarty-2.6.7.tar.gz
$> mkdir /usr/local/lib/php/Smarty
$> cp -r Smarty-2.6.7/libs/* /usr/local/lib/php/Smarty

You should now have the following file structure:

/usr/local/lib/php/Smarty/
Config_File.class.php
debug.tpl
internals/
plugins/
Smarty.class.php
Smarty_Compiler.class.php


SETUP SMARTY DIRECTORIES

You will need four directories setup for Smarty to work. These files are for
templates, compiled templates, cached templates and config files. You may or
may not use caching or config files, but it is a good idea to set them up
anyways. It is also recommended to place them outside of the web server
document root. The web server PHP user will need write access to the cache and
compile directories as well.

In our example, the document root is /web/www.domain.com/docs and the
web server username is "nobody". We will keep our Smarty files under
/web/www.domain.com/smarty

$> cd /web/www.domain.com
$> mkdir smarty
$> mkdir smarty/templates
$> mkdir smarty/templates_c
$> mkdir smarty/cache
$> mkdir smarty/configs
$> chown nobody:nobody smarty/templates_c
$> chown nobody:nobody smarty/cache
$> chmod 775 smarty/templates_c
$> chmod 775 smarty/cache


SETUP SMARTY PHP SCRIPTS

Now we setup our application in the document root:

$> cd /web/www.domain.com/docs
$> mkdir myapp
$> cd myapp
$> vi index.php

Edit the index.php file to look like the following:


// put full path to Smarty.class.php
require('/usr/local/lib/php/Smarty/Smarty.class.php');
$smarty = new Smarty();

$smarty->template_dir = '/web/www.domain.com/smarty/templates';
$smarty->compile_dir = '/web/www.domain.com/smarty/templates_c';
$smarty->cache_dir = '/web/www.domain.com/smarty/cache';
$smarty->config_dir = '/web/www.domain.com/smarty/configs';

$smarty->assign('name', 'Ned');
$smarty->display('index.tpl');

?>


SETUP SMARTY TEMPLATE

$> vi /web/www.domain.com/smarty/templates/index.tpl

Edit the index.tpl file with the following:



Smarty


Hello, {$name}!





Now go to your new application through the web browser,
http://www.domain.com/myapp/index.php in our example. You should see the text
"Hello Ned!" in your browser.

Once you get this far, you can continue on to the Smarty Crash Course to learn
a few more simple things, or on to the documentation to learn it all.

Friday, January 1, 2010

How to Create a Joomla! Plugin

Introduction


Joomla! plugins serve a variety of purposes.  As modules enhance the presentation of the final output of the Web site, plugins enhance the data and can also provide additional, installable functionality.


This tutorial looks at the general principles used to design and build a plugin.





Plugin Types


While the number of possible types of plugins is almost limitless, there are a number of core plugin types that are used by Joomla!.  These core types are grouped into directories under /plugins/.  They are:




  • authentication

  • content

  • editors

  • editors-xtd

  • search

  • system


  • user

  • xmlrpc


Authentication plugins allow you to authenticate (to allow you to login) against different sources.  By default you will authenticate against the Joomla! user database when you try to login.  However, there are other methods available such as by OpenID, by a Google account, LDAP, and many others.  Wherever a source has a public API, you can write an authentication plugin to verify the login credentials against this source.  For example, you could write a plugin to authenticate against Twitter accounts because they have a public API.



Content plugins modify and add features to displayed content.  For example, content plugins can cloak email address or can convert URL's into SEF format.  Content plugins can also look for markers in content and replace them with other text or HTML.  For example, the Load Module plugin will take {*loadmodule banner1*} (you would remove the *'s in practice.  They are included to actually prevent the plugin from working in this article), load all the modules in the banner1 position and replace the marker with that output.


Editor plugins allow you to add new content editors (usually WYSIYWG).


Editor-XTD (extended) plugins allow you to add additional buttons to the editors.  For example, the Image, Pagebreak and Read more buttons below the default editor are actually plugins.



Search plugins allow you to search different content from different components.  For example, search plugins for Articles, Contacts and Weblinks are already provided in Joomla!.


System plugins allow you to perform actions at various points in the execution of the PHP code that runs a Joomla! Web site.


User plugins allow you to perform actions at different times with respect to users.  Such times include logging in and out and also saving a user.  User plugins are typically user to "bridge" between web applications (such as creating a Joomla! to phpBB bridge).



XML-RPC plugins allow you to provide additional XML-RPC web services for your site.  When your Web site exposes web services, it gives you the ability to interact remotely, possibly from a desktop application.  Web services are a fairly advanced topic and will not be covered in much detail here.


The Basic Files


While a plugin can have any number of files, there are two you need as a minimum and there are specific naming conventions you must follow.  Before we look at the files, we must decide what sort of plugin we are going to create.  It must either fall under one of the built-in types (authentication, content, editors, editors-xtd, search, system, user or xmlrpc) or your can create your own type by adding a new folder under /plugins/.  So, files for an authentication plugin will be saved under /plugins/authentication/, files for a system plugin will be saved under /plugins/system/, and so on.



Let's look at an example creating the basic skeleton for a system plugin called "Test".  There is no restriction on the file name for the plugin (although we recommend sticking with alpha-numeric characters and underscores only), but once you decide on the file name, it will set the naming convention for other parts of the plugin.


For this plugin you will need to create a PHP file, test.php, which is the file actually loaded by Joomla! and an XML file, text.xml, which contains meta and installation information for the plugin as well as the definition of the plugin parameters.


test.php


The skeleton test.php has the following source:



<?php
// no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );

jimport( 'joomla.plugin.plugin' );

/**
* Example system plugin
*/
class plgSystemTest extends JPlugin
{
/**
* Constructor
*
* For php4 compatibility we must not use the __constructor as a constructor for plugins
* because func_get_args ( void ) returns a copy of all passed arguments NOT references.
* This causes problems with cross-referencing necessary for the observer design pattern.
*
* @access protected
* @param object $subject The object to observe
* @param array $config An array that holds the plugin configuration
* @since 1.0
*/
function plgSystemTest( &$subject, $config )
{
parent::__construct( $subject, $config );

// Do some extra initialisation in this constructor if required
}

/**
* Do something onAfterInitialise
*/
function onAfterInitialise()
{
// Perform some action
}
}

Let's look at this file in detail.  Please note that the usual Docblock (the comment block you normally see at the top of most PHP files) has been omitted for clarity.


The file starts with the normal check for defined( '_JEXEC' ) which ensures that the file will fail to execute if access directly via the URL.  This is a very important security feature and the line must be placed before any other executable PHP in the file (it's fine to go after all the initial comment though).  The importance of having this check your PHP files cannot be overemphasised.


Next we use the jimport function to load the library file with the definition of the JPlugin class.



You will notice that a plugin is simply a class derived from JPlugin (this differs from previous versions of Joomla!).  The naming convention of this class is very important.  The formula for this name is:


plg + Proper case name of the plugin directory + Proper case name of the plugin file without the extension.


Proper case simply means that we capitalise the first letter of the name.  When we join them altogether it's then referred to as "Camel Case".  The case is not that important as PHP classes are not case-sensitive but it's the convention Joomla! uses and generally makes the code a little more readable.



For our test system plugin, the formula gives us a class name of:


plg + System + Test = plgSystemTest


Let's move on to the methods in the class.


The first method, which is called the constructor, is completely optional.  You only require this is you want to do some work when the plugin is actually loaded by Joomla!.  This happens with a call to the helper method JPluginHelper::importPlugin( <plugin_type> ).  This means that you even if the plugin is never triggered, for whatever reason, you still have an opportunity to execute code if you need to in the constructor.



In PHP 4 the name of the constructor method is the same as the name of the class.  If you were designing only for PHP 5 you could replace this with the name of __constructor instead.


The remaining methods will take on the name of "events" that are trigger throughout the execution of the Joomla! code.  In the example, we know there is an event called onAfterInitialise which is the first event called after the Joomla! application sets itself up for work.  For more information on when some events are triggered, see the API Execution Order page on the Documentation Wiki.



The naming rule here is simple: the name of the method must be the same as the event on which you want it triggered.  The Joomla! Framework will auto-register all the methods in the class for you.


That's the basics of the plugin PHP file.  It's location, name and methods will depend on what you want to use the plugin for.  One thing to note about system plugins is that they are not limited to handling just system events.  Because the system plugins are always loaded on each run of the Joomla! PHP, you can include any triggered event in a system plugin.


The events triggered in Joomla! are:


Authentication




  • onAuthenticate


Content



  • onPrepareContent

  • onAfterDisplayTitle

  • onBeforeDisplayContent

  • onBeforeContentSave (new in 1.5.4)


  • onAfterContentSave (new in 1.5.4)


Editors



  • onInit

  • onGetContent

  • onSetContent

  • onSave


  • onDisplay

  • onGetInsertMethod


Editors XTD (Extended)



  • onDisplay


Seach




  • onSearch

  • onSearchAreas


System



  • onAfterInitialise

  • onAfterRoute

  • onAfterDispatch


  • onAfterRender


User



  • onLoginUser

  • onLoginFailure

  • onLogoutUser

  • onLogoutFailure


  • onBeforeStoreUser

  • onAfterStoreUser

  • onBeforeDeleteUser

  • onAfterDeleteUser


XML-RPC



  • onGetWebServices



For more detailed information on how to create specific plugins, visit the Plugins Category on the Documentation Wiki.


text.xml


The skeleton test.xml has the following source:


<?xml version="1.0" encoding="utf-8"?>
<install version="1.5.2" type="plugin" group="system" method="upgrade">

<name>System - Test</name>
<author>Author</author>
<creationDate>Month 2008</creationDate>
<copyright>Copyright (C) 2008 Holder. All rights reserved.</copyright>

<license>GNU General Public License</license>
<authorEmail>email</authorEmail>
<authorUrl>url</authorUrl>
<version>1.0.1</version>

<description>A test system plugin</description>
<files>
<filename plugin="example">example.php</filename>
</files>
<params>

<param name="example"
type="text"
default=""
label="Example"
description="An example text parameter" />
</params>
</install>

This is a very typcial format for most meta XML files (sometimes called manifests).  Let's go through some of the most important tags:


INSTALL


The install tag has several key attributes.  The type must be "plugin" and you must specify the group.  The group attribute is required and is the name of the directory you saved your files in (for example, system, content, etc).  We use the method="upgrade" attribute to allow us to install the extension without uninstalling.  In other words, if you are sharing this plugin with other, they can just install the new version over the top of the old one.



NAME


We usually start the name with the type of plugin this is.  Our example is a system plugin and it has some some nebulous test purpose.  So we have named the plugin "System - Test".  You can name the plugins in any way, but this is a common format.


FILES


The files tag includes all of the files that will will be installed with the plugin.  Plugins can also support be installed with subdirectories.  To specify these just all a FOLDER tag, <folder>test</folder>.  It is common practice to have only one subdirectory and name it the same as the plugin PHP file (without the extension of course).



PARAMS


Any number of parameters can be specified for a plugin.  Please note there is no "advanced" group for plugins as there is in modules and components.


Packaging Plugins


Packaging a plugin is easy.  If you only have the two files (the PHP file and the XML file), just "zip" them up into a compressed archive file.  If your plugin uses a subdirectory then simply include that in the archive as well. 


How To Create A Module in Magento

This is a brief listing of the steps I have taken to test a sample module in Magento



Make folder app/code/local/Schogini <——— this name can be your company’s name, this make a new name space so that your classes will not interfere with other classes of the same name.


Inside the above folder make a folder called Example app/code/local/Schogini/Example <—- here Example is the name of the module we will create


Now add the module xml file at app/etc/modules/Schogini_All.xml <— here this can be Schogini_example.xml but I will use Schogini_All.xml so that all my test module definitions can be added to the same file instead of cluttering the etc/modules folder with many files.


<?xml version=”1.0″?>

<config>

  <modules>


    <Schogini_Example>

      <active>true</active>

      <codePool>local</codePool>

    </Schogini_Example>


  </modules>

</config>


Now create two folders app/code/local/Schogini/Example/etc and app/code/local/Schogini/Example/Block


In the app/code/local/Schogini/Example/etc folder make a file like this


<?xml version=”1.0″ encoding=”UTF-8″?>

<config>


  <modules>

    <Schogini_Example>

      <version>0.1.0</version>

    </Schogini_Example>


  </modules>

  <global>

    <blocks>

      <example>

        <class>Schogini_Example_Block</class>


      </example>

    </blocks>

  </global>

</config>


And now create the block php class file at app/code/local/Schogini/Example/Block/Myview.php



<?php

class Schogini_Example_Block_Myview extends Mage_Core_Block_Template {

 public function myFunction(){

  returnHello World!“;


 }

}

?>


Now make the view folder at app/design/frontend/default/default/template/example <– here you should figure out the correct template folder of your Magento store.


Inside this create the view file for the module block app/design/frontend/default/default/template/example/myview.phtml


<p>Schogini example:</p>


<?php

  echo $this->myFunction();

?>


We can enable or disable this module at Admin -> System -> Advanced



image


Module creation is over at this point.


Now! Edit any page where you will want this module to show its output!


I have tested the above module in the home page by Admin -> CMS -> Manage Pages -> Home and edited to add these lines somewhere at the bottom


{{block type="example/myview" template="example/myview.phtml"}}


Please not the name space “schogini” is not required in the above line..



Reload the Magento home to see your module in action!