<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Nettuts+ &#187; Other</title>
	<atom:link href="http://net.tutsplus.com/category/tutorials/other/feed/" rel="self" type="application/rss+xml" />
	<link>http://net.tutsplus.com</link>
	<description>Web Development &#38; Design Tutorials</description>
	<lastBuildDate>Fri, 20 Nov 2009 19:56:34 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Easy Version Control with Git</title>
		<link>http://net.tutsplus.com/tutorials/other/easy-version-control-with-git/</link>
		<comments>http://net.tutsplus.com/tutorials/other/easy-version-control-with-git/#comments</comments>
		<pubDate>Wed, 28 Oct 2009 19:06:41 +0000</pubDate>
		<dc:creator>Andrew Burgess</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[version control]]></category>

		<guid isPermaLink="false">http://net.tutsplus.com/?p=7449</guid>
		<description><![CDATA[<img src="http://nettuts.s3.amazonaws.com/476_git/200.jpg" alt="Easy Version Control with Git" />]]></description>
			<content:encoded><![CDATA[<p>Have you ever worked on a project that was so unwieldy, you were scared to update a file or add a feature? Maybe the problem was that you weren&#8217;t using a version control system. In today&#8217;s tutorial, we&#8217;ll learn the basics of what might possibly be the best VCS in the world: <a href="http://git-scm.com/">Git</a>.</p>
<p><span id="more-7449"></span></p>
<h3 id='what_is_git'>What is Git?</h3>
<p><a href="http://git-scm.com/">Git</a> is a open-source code managemen tool; it was created by Linus Torvalds when he was building the Linux kernel. Because of those roots, it needed to be really fast; that it is, and easy to get the hang of as well. Git allows you to work on your code with the peace of mind that everything you do is reversible. It makes it easy to experiment with new ideas in a project and not worry about breaking anything. <a href='http://tom.preston-werner.com/2009/05/19/the-git-parable.html' title='The Git Parable'>The Git Parable</a>, by Tom Preston-Werner, is a great introduction to the terms and ideas behind Git.</p>
<h3 id='why_should_i_use_git'>Why Should I use Git?</h3>
<p>You should definitely use a revision control system; as we already said, this gives you the freedom to do whatever you want with your code and not worry about breaking it. So if you&#8217;ve realized the benefits of using a revision control system, why should you use git? Why not SVN or Perforce or another one? To be honest, I haven&#8217;t studied the differences too closely; check out <a href="http://whygitisbetterthanx.com/">WhyGitIsBetterThanX.com</a> for some helpful info.</p>
<h3 id='how_do_i_get_set_up'>How do I Get Set Up?</h3>
<p>Git is pretty easy to get: on a Mac, it&#8217;s probably easiest to use the <a href='http://code.google.com/p/git-osx-installer/' title='Install Git on OS X'>git-osx-installer</a>. If you have <a href='http://macports.org/install.php'>MacPorts</a> installed, you may want to get Git through it; you can find <a href='http://help.github.com/mac-git-installation/' title='Git Installation for Mac'>instructions on the GitHub help site</a>. (And yes, we&#8217;ll talk about GitHub). On Windows, the simplest way to start rolling is to use the <a href='http://code.google.com/p/msysgit/' title='msysgit on Google Code'>msysgit installer</a>. However, if you&#8217;ve got <a href='http://cygwin.com' title='Cygwin: Linux Environment for Windows'>Cygwin</a>, you can git Git through there as well.</p>
<h3 id='how_do_i_use_git'>How do I use Git?</h3>
<p>By now you should have Git installed; if you&#8217;re on a Mac, open up a terminal; if you&#8217;re on Windows open the Git Bash (from msysgit) or your Cygwin prompt. From here on, there shouldn&#8217;t be any OS differences.</p>
<h4 id='configuration'>Configuration</h4>
<p>We&#8217;ll start by doing a bit of configuration. Every commit you make will have your name and email address to identify the &#8216;owner&#8217; of the commit, so you should start by giving it those values. To do so, run these commands:</p>
<pre name='code' class='html'>
git config --global user.name "Your Name"
git config --global user.email "your@email.com"
</pre>
<p>It&#8217;s also nice to enable some text coloring, just for easier reading in the terminal. </p>
<pre class="html" name="code">
git config --global color.diff auto
git config --global color.status auto
git config --global color.branch auto
</pre>
<h4 id='git_init'>git init</h4>
<p>Now that Git knows who you are, let&#8217;s imagine we&#8217;re creating a simple PHP web app. (Of course, the bigger the project, the brighter Git shines, but we&#8217;re just learning the tools, right?) We&#8217;ve got an empty directory called &#8216;mySite.&#8217; First focus on that directory (using the cd command). To get started with Git, you need to run the git init command; as you might guess, this initializes a Git repository in that folder, adding a .git folder within it. A repository is kind of like a code history book. It will hold all the past versions of your code, as well as the current one.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/476_git/gitinit.jpg" alt="Git Init" /></div>
<p>Notice that your terminal path is appended with (master). That&#8217;s the branch you&#8217;re currently working on. Branch? Think of your project as a tree; you can create different features on different branches, and everything will stay separate and safe.</p>
<h4 id='git_add'>git add</h4>
<p>We&#8217;ve started working on our application.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/476_git/files.jpg" alt="Files" /></div>
<p>Before we go any further, we should make our first commit. A commit is simply a pointer to a spot on your code history. Before we can do that, however, we need to move any files we want to be a part of this commit to the staging area. The staging area is a spot to hold files for your next commit; maybe you don&#8217;t want to commit all your current changes, so you put some in the staging area. We can do that by using the add command</p>
<pre name='code' class='html'>
git add .
</pre>
<p>The . simply means to add everything. You could be more specific if you wanted.</p>
<pre name='code' class='html'>
git add *.js
git add index.php
</pre>
<h4 id='git_commit'>git commit</h4>
<p>Now that we&#8217;ve staged our files, let&#8217;s commit them. This is done with the command</p>
<pre name='code' class='html'>
git commit
</pre>
<p>This takes all the files in our staging area and marks that code as a point in our project&#8217;s history. If you don&#8217;t add any options to the command above, you&#8217;ll get something like this.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/476_git/vim.jpg" alt="vim" /></div>
<p>Each commit should have an accompanying message, so you know why that code was committed. This editor allows you to write your message, as well as see what is in this commit. From the image above, you can see that this commit is comprised of four new files. The editor you&#8217;re using to write the message is Vim; if you&#8217;re not familiar with vim, know that you&#8217;ll need to press i (for Insert) before you can type your message. In the shot above, I&#8217;ve added the message &#8220;Initial Commit.&#8221; After you write your message, hit escape and type :wq (to save and exit). You&#8217;ll then see you&#8217;re commit take place.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/476_git/commit.jpg" alt="Commit Aftermath" /></div>
<p>You can use a few options to make commits more quickly. Firstly, -m allows you to add your message in-line. </p>
<pre name='code' class='html'>
git commit -m "initial commit"
</pre>
<p>Then, -a allows you to skip the staging area; well, not really. Git will automatically stage and commit all modified files when you use this option. (remember, it won&#8217;t add any new files). Together, you could use these commands like this: </p>
<pre name='code' class='html'>
git commit -am 'update to index.php'
</pre>
<p>So how does Git tell commits apart? Instead of numbering them, Git uses the code contents of the commit to create a 40 character SHA1 hash. The neat part about this is that, since it&#8217;s using the code to create the hash, no two hashes in your project will be the same unless the code in the commits is identical.</p>
<h4 id='git_status'>git status</h4>
<p>The <em>git status</em> command allows you to see the current state of your code. We&#8217;ve just done a commit, so <em>git status</em> will show us that there&#8217;s nothing new.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/476_git/status_clean.jpg" alt="status, clean" /></div>
<p>If we continue working on our imaginary project, you&#8217;ll see that our status changes. I&#8217;m going to edit our index.php and add another file. Now, running <em>git status</em> gives us this:</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/476_git/status_not_clean.jpg" alt="Status, not clean" /></div>
<p>The update is divided into two categories: &#8220;changed but not updated,&#8221; and &#8220;untracked files.&#8221; If we run </p>
<pre name='code' class='html'>
git add userAuthentication.php
git status
</pre>
<p>you&#8217;ll see that we now have a &#8220;changes to be committed&#8221; section. This lists files added to the staging area. I&#8217;m going to commit these changes with this:
</p>
<pre name='code' class='html'>
git commit -am 'user authentication code added'
</pre>
<p>Now running <em>git status</em> shows us a clean working directory.</p>
<h4 id='git_branch__git_checkout'>git branch / git checkout</h4>
<p>Here&#8217;s a scenario: we&#8217;re working happily on our project when suddenly we have a grand idea. This idea is so revolutionary, it will change our project drastically. We&#8217;ve got to give it a try, but we don&#8217;t want to throw this insecure, first-draft code in with our tested and true code. What to do? This is where <em>git branch</em> will be immensely helpful. Let&#8217;s branch our project so that if our big idea doesn&#8217;t work out, there&#8217;s no harm done.</p>
<pre name='code' class='html'>
git branch
</pre>
</p>
<p> Just running the branch command <em>sans</em> options will list our branches; right now, we&#8217;ve only got the master branch, which is what any git repository starts with. To actually create a new branch, add the name of your new branch after the command.</p>
<pre name='code' class='html'>
git branch bigIdea
</pre>
<p>When you create a new branch, you aren&#8217;t switched to it automatically. Notice that our terminal still says (master). This is where we use branches comrade command <em>git checkout</em>.</p>
<pre name='code' class='html'>
git checkout bigIdea
</pre>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/476_git/branch.jpg" alt="Git Branch" /></div>
<p>(Tip: you can create a branch and switch to it in one fell swoop with this command: <em>git checkout -b <span>branch name</span></em>.) As you can see, we&#8217;re now on the bigIdea branch. Let&#8217;s code up a storm. <em>Git status</em> will show our work.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/476_git/status_amazing.jpg" alt="2 new files" /></div>
<p>Let&#8217;s commit our changes:
<pre name='code' class='html'>
git add .
git commit -m 'The Kiler Feature added'
</pre>
</p>
<p>All right, enough of this feature for now; let&#8217;s go back to our master branch; but before we do, I want to show you our current project folder.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/476_git/files_amazing.jpg" alt="Files, branch bigIdea" /></div>
<p>Now, switch back to the master branch; you know how:<em>git checkout master</em>. Look at our project folder again.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/476_git/files_not_amazing.jpg" alt="Files, branch master" /></div>
<p>No, I didn&#8217;t do anything; those two files are only part of the bigIdea branch, so we don&#8217;t even know they exist from the master branch. This not only works for complete files, but also for even the smallest changes within files.</p>
<h4 id='git_merge'>git merge</h4>
<p>Ok, so we&#8217;ve been working hard on that bigIdea branch in our spare time. In fact, after another commit, it&#8217;s looking so sweet we&#8217;ve decided it&#8217;s good enough to join the master branch. So how do we do it?</p>
<p>The <em>git merge</em> command is made for exactly this purpose. While on the master branch, give this a try:</p>
<pre name='code' class='html'>
git merge bigIdea
</pre>
<p>It&#8217;s that easy; now, everything on the bigIdea branch is a part of the master branch. You can get rid of the bigIdea branch now, if you want. </p>
<pre class="html" name="code">
git branch -d bigIdea
</pre>
<p> I should mention that if you haven&#8217;t merged a branch, Git won&#8217;t let you delete it with this command; you&#8217;ll need to use an uppercase D in the option. This is just a safety measure.</p>
<h4 id='git_log__gitk'>git log / gitk</h4>
<p>You&#8217;ll probably want to look at your commit history at some point during your project. This can easily be done with the log command. </p>
<pre name='code' class='html'>
git log
</pre>
<p>This will output a list of all the commits you&#8217;ve made in a project, showing them in reverse order. You can get at quite a tidy chunk of info here:</p>
<ul>
<li>the commit author</li>
<li>the commit hash</li>
<li>the date and time</li>
<li>the message</li>
</ul>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/476_git/log.jpg" alt="git log" style="width: 600px;" /></div>
<p>Definitely informative, but rather dry, no? We can brighten things a bit with the graph option.</p>
<pre name='code' class='html'>
git log --graph
</pre>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/476_git/log_graph.jpg" alt="git log --graph" /></div>
<p>Now we can see the tree structure, sort of. Although we don&#8217;t get their names, we can see each of the branches and which commits were made on them. If you&#8217;re used to working in a terminal, you might be fine with this. However, if (previous to this experience) the word <em>terminal</em> strikes you first as something deadly, breathe easy: there&#8217;s an app for that. Try this: </p>
<pre name='code' class='html'>
gitk --all
</pre>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/476_git/gitk.jpg" alt="gitk" /></div>
<p>This is the graphical repository browser. You can browse around your commits, see exactly what was changed in each file during a commit, and so much more. (You&#8217;ll notice I added a few commits before merging, just to make the tree structure more recognizable.)</p>
<h4 id='github'>GitHub</h4>
<p>Now that you&#8217;ve got a reasonable knowledge of Git under your belt, let&#8217;s look at some of the collaborative parts of Git. Git is a great way to share code with others and work on projects together. There are a number of Git repository hosting sites. We&#8217;ll just look at one: <a href='http://www.github.com' title='GitHub'>GitHub</a>.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/476_git/github.jpg" alt="GitHub Home Page" /></div>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/476_git/github_sign_up.jpg" alt="GitHub Sign Up" /></div>
<p>Head over to the GitHub sign-up page and create an account. You&#8217;ll need an SSH public key, so let&#8217;s create that right now! (Note: you don&#8217;t need the key while signing up; you can add it later.)</p>
<p>Open up your terminal and type this: </p>
<pre name='code' class='html'>
ssh-keygen -t rsa -C "your@email.com"
</pre>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/476_git/ssh.jpg" alt="ssh" /></div>
<p>The t option assigns a type, and the C option adds a comment, traditionally your email address. You&#8217;ll then be asked where to save the key; just hitting enter will do (that saves the file to the default location). Then, enter a pass-phrase, twice. Now you have a key; let&#8217;s give it to GitHub.</p>
<p>First, get your key from the file; the terminal will have told you where the key was stored; open the file, copy the key (be careful not to add any newlines or white-space). Open your GitHub account page, scroll to SSH Public Keys, and click &#8220;Add another public key.&#8221; Paste in your key and save it. You&#8217;re good to go! You can test your authentication by running this: </p>
<pre name='code' class='html'>
ssh git@github.com
</pre>
<p>You&#8217;ll be prompted for your pass-phrase; to avoid having to type this every time you connect to GitHub, you can automate this. I could tell you how to do this, but I&#8217;d probably inadvertently plagiarize: the <a href='http://help.github.com/working-with-key-pass-phrases/'>GitHub Help has a plain-english article on how to do it</a>.</p>
<h3 id='git_clone'>Git Clone</h3>
<p>So now you&#8217;re set up with GitHub; let&#8217;s grab a project. How about jQuery? If you go to the <a href='http://github.com/jquery/jquery'>jQuery GitHub project</a>, you&#8217;ll find the git clone URL. Run this: </p>
<pre name='code' class='html'>
git clone git://github.com/jquery/jquery.git
</pre>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/476_git/clone.jpg" alt="git clone" /></div>
<p>This creates a jquery folder and copies the whole jquery repository to your computer. Now you have a complete history of the project; check it out with <em>gitk &#8211;all</em>.</p>
<h4 id='git_push'>git push</h4>
<p>So let&#8217;s say you&#8217;ve been working on a project, managing it with git locally. Now you want to share it with a friend, or the world. Log into GitHub and create a new repository. GitHub will give you a public clone URL (for others wanting to download your project) and a personal clone URL (for yourself).</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/476_git/push.jpg" alt="Create New Repository" /></div>
<p>Then, come back to your project in the terminal and give this a whirl:</p>
<pre name='code' class='html'>
git remote add origin git@github.com:andrew8088/Shazam.git
</pre>
<p> A remote is a project repository in a remote location. In this case, we&#8217;re giving this remote a name of origin, and handing it our private clone URL. (Obviously, you will have to substitute my URL for your own.) Now that the project knows where it&#8217;s going . . .</p>
<pre name='code' class='html'>
git push origin master
</pre>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/476_git/push2.jpg" alt="Git push" /></div>
<p>This pushes the master branch to the origin remote. Now you&#8217;re project is available to the world! Head back to your project page and see your project.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/476_git/origin.jpg" alt="GitHub Project" /></div>
<h4 id='git_pull'>git pull</h4>
<p>You might be on the other end of a project: you&#8217;re a contributor instead of the owner. When the owner pushes a new commit to the repository, you can use <em>git pull</em> to get the updates. <em>Git pull</em> is actually a combo tool: it runs <em>git fetch</em> (getting the changes) and <em>git merge</em> (merging them with your current copy).
<pre name='code' class='html'>
git pull
</pre>
</p>
<h3 id='youre_set'>You&#8217;re Set!</h3>
<p>Well, there&#8217;s so much more you can learn about Git; hopefully you&#8217;ve learned enough commands to help you manage your next project more smartly. But don&#8217;t stop here; check out these resources to become a Git master!</p>
<ul>
<li><a href='http://developer.yahoo.com/yui/theater/video.php?v=prestonwerner-github'>Git, GitHub, and Social Coding (YUI Theater)</a></li>
<li><a href='http://learn.github.com'>GitHub Learning Center</a></li>
<li><a href="http://www.gitcasts.com">Gitcasts.com: screencasts on Git</a></li>
<li><a href='http://git-scm.com/'>The Git site</a></li>
<li><a href='http://www.evernote.com/pub/andrew_burgess/git'>My public Git Evernote-book</a></li>
</ul>
<ul class="webroundup">
<li>Follow us on <a href="http://www.twitter.com/nettuts">Twitter</a>, or subscribe to the <a href="http://feeds.feedburner.com/nettuts" title="Nettuts+ RSS Feed">Nettuts+ RSS Feed</a> for the best web development tutorials on the web.</li>
</ul>
<p>
<script type="text/javascript"><!--digg_url = "post permalink (not digg url)"; // -->
</script><br />
<script src="http://digg.com/tools/diggthis.js" type="text/javascript"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/other/easy-version-control-with-git/feed/</wfw:commentRss>
		<slash:comments>50</slash:comments>
		</item>
		<item>
		<title>Feeds 101</title>
		<link>http://net.tutsplus.com/tutorials/other/feeds-101/</link>
		<comments>http://net.tutsplus.com/tutorials/other/feeds-101/#comments</comments>
		<pubDate>Tue, 27 Oct 2009 19:23:29 +0000</pubDate>
		<dc:creator>Siddharth</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[atom]]></category>
		<category><![CDATA[feed]]></category>
		<category><![CDATA[rss]]></category>

		<guid isPermaLink="false">http://net.tutsplus.com/?p=7414</guid>
		<description><![CDATA[<img src="http://nettuts.s3.amazonaws.com/474_feed/feeds101.jpg" alt="Feeds 101" />]]></description>
			<content:encoded><![CDATA[<p>Feeds. RSS. Atom. Syndication. Subscribers. These are some of the keywords floating around the web and have gained notorious prominence over the years. In this guide, we&#8217;ll take a look at a number of things including what feeds are, why you need to have a feed for your site, how to set up one and then publish it.
</p>
<p><span id="more-7414"></span></p>
<h3>What are Feeds?</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/474_feed/images/overview.jpg" alt="Feed image" border="0" /></div>
<p>In this digital age, users no longer have the luxury of time to check for new content manually each time or more importantly remember each site they want to get information from. Web feeds, news feeds or feeds helps the user simplify this process drastically.  </p>
<p>Feeds, to put it simply, are a way to publish frequently updated content. Your feed is a XML formatted document which lets you share content with other users on the web. Users, subscribers in this lingo, can use your feed to read updated information on your site if and when it is posted.</p>
<h3>Why you Should Publish Feeds</h3>
<p>From a web developer&#8217;s perspective, one of the main reason for publishing a feed is user convenience. With a feed for users to subscribe to, they don&#8217;t have to check for new content manually each time. They can just subscribe to your feed and get notified new content is posted. No hassles! If you fear you&#8217;ll lose your advertisement revenues in this process, you can just as easily include ads in the feed. </p>
<p>Publishing a feed also means that it is easier for third party content providers to syndicate your content thus gaining more exposure and traffic in the process. </p>
<h3>Feed Formats</h3>
<p>As with any hot technology, there are a few well established, competing protocols for creating web feeds. </p>
<h4>RSS</h4>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/474_feed/images/rsslogo.jpg" alt="Feed image" border="0" /></div>
<p>RSS is the dominant format for publishing web feeds and stands for Really Simple Syndication. RSS has a number of variants each branching out from RSS 1.x and RSS 2.x versions. A lot of services, including WordPress use RSS for creating its feeds.</p>
<p>Despite it&#8217;s massive user base, RSS does suffer from some drawbacks, some significant, the most important one being its inability to handle HTML. Nevertheless, we&#8217;ll be creating our feed today in the RSS format.</p>
<h4>Atom</h4>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/474_feed/images/atomlogo.png" alt="Atom logo" border="0" /></div>
<p>Atom was created in order to mitigate a lot of RSS&#8217; drawbacks including the ability to include properly formatted XML or XHTML in your feeds. But since RSS has almost become synonymous with feeds, Atom has always been the much more feature rich and flexible little brother.  </p>
<h3>RSS&#8217;s Format</h3>
<p>In the interest of keeping it simple, we&#8217;ll just stick with RSS today instead of trying out each format out there.</p>
<p>Each and every RSS feed out there follows this general format:</p>
<h4>Defining the version and encoding</h4>
<p>RSS is a subset of XML which means we need to make sure it is marked so appropriately. </p>
<pre name="code" class="xml">&lt;?xml version="1.0" encoding="utf-8"?>
&lt;rss version="2.0">
..
&lt;/rss>
</pre>
<p>The first line is the XML declaration. We define the version so that it validates correctly as XML. The encoding part is purely optional. </p>
<p>The second line defines the version of RSS we are going to use today. We are going to use RSS 2 today.</p>
<p>Each feed need to be inside a channel so that goes inside the markup. Thus far our feed looks like so.</p>
<pre class="xml" name="code">&lt;?xml version="1.0" encoding="utf-8"?>
&lt;rss version="2.0">
&lt;channel>
..
&lt;/channel>
&lt;/rss>
</pre>
<h4>Filling in the feed&#8217;s source information</h4>
<p>This is where you fill in all the important details like the name of the feed, the URL and a description of the site. </p>
<pre class="xml" name="code">&lt;title>My feed&lt;/title>
 &lt;link>http://www.somesite.com&lt;/link>
 &lt;description>Random ravings <img src='http://net.tutsplus.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> &lt;/description>
</pre>
<p>You aren&#8217;t limited to these fields alone. There are a number of other optional fields including the language of your feed, an image for the logo, when the feed was updated last and many more. </p>
<h4>Adding the content</h4>
<p>Each item in the feed has to be enclosed by an &lt;item> element. An item can be anything: a news post, a status update, new products: anything. Each item requires a title and a corresponding link. As with before, you can make use of a number of optional elements including description and author fields. </p>
<p>A sample item would look like so:</p>
<pre class="xml" name="code">
&lt;item>
&lt;title>Feeds 101&lt;/title>
 &lt;link>http://www.net.tutsplus.com&lt;/link>
 &lt;description>Let's create an RSS feed from scratch!&lt;/description>
 &lt;author>Siddharth&lt;/author>
&lt;/item></pre>
<h3>Building a Static RSS Feed</h3>
<p>Now that we know all the individual parts of a RSS file and how they all gel together, it&#8217;s time to see a complete RSS file. </p>
<pre class="xml" name="code">&lt;?xml version="1.0" encoding="utf-8"?>
&lt;rss version="2.0">
&lt;channel>
	&lt;title>My feed&lt;/title>
   &lt;link>http://www.somesite.com&lt;/link>
   &lt;description>Random ravings <img src='http://net.tutsplus.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> &lt;/description>
   &lt;item>
		&lt;title>Feeds 101&lt;/title>
 		&lt;link>http://www.net.tutsplus.com&lt;/link>
 		&lt;description>Let's create an RSS feed from scratch!&lt;/description>
 		&lt;author>sid@ssiddharth.com&lt;/author>
	&lt;/item>
&lt;/channel>
&lt;/rss>
</pre>
<p>It may not look like much but gents, this is a working RSS feed. We&#8217;ve defined everything that needs to be defined and if you are inclined to do so, you can put this on the web. </p>
<h3>Building a Dynamic RSS Feed</h3>
<p>Happy about building your first RSS feed? You should be! But the problem with this is that the feed is completely static: something which is completely counter intuitive as compared to the concept of feeds. We&#8217;ll rectify this now by building a simple PHP script that mooches off data from a database and updates the RSS feed when needed. </p>
<p>Since I like having pretty URLs, I am going to name this file index.php and place it in a folder called feed so my feed can be accessed at www.mysite.com/feed</p>
<p>For the sake of simplicity, I am going to assume you already have a database containing your articles. I am also assuming the database has columns named <em>title></em>, <em>link</em>, <em>description</em> and <em>date</em> in a table called <em>posts</em>. </p>
<h4>Building the base</h4>
<pre name="code" class="php">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;rss version="2.0">
&lt;channel>
	&lt;title>My feed&lt;/title>
   &lt;link>http://www.somesite.com&lt;/link>
   &lt;description>Random ravings <img src='http://net.tutsplus.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> &lt;/description>

 &lt;?php
    // Code here
 ?>

&lt;/channel>
&lt;/rss></pre>
<p>Since the XML declarations and feed information are going to be pretty static, we&#8217;ll keep them static. You&#8217;d want to keep them dynamic if you were writing a PHP class for generating RSS feeds but for our purposes, this should do.</p>
<h4>Defining database information and connecting</h4>
<pre name="code" class="php">
DEFINE ('DB_USER', 'some_username');
DEFINE ('DB_PASSWORD', 'some_unusually_weak_password');
DEFINE ('DB_HOST', 'localhost');
DEFINE ('DB_NAME', 'database');
</pre>
<p>Simple as it looks. We just note down a bunch of information for use later.</p>
<pre name="code" class="php">
$connection = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD) or
die('Connection to the specified database couldn't be established');
mysql_select_db(DB_NAME)  or
die ('Specified database couldn't be selected');
</pre>
<p>Pretty generic connection code. We try to connect using the credentials noted earlier. If nothing hitches up, we select the relevant database for use later.</p>
<h4>Querying the database</h4>
<pre name="code" class="php">
$query = "SELECT * FROM posts ORDER BY date DESC";
$result = mysql_query($query) or die ("Query couldn't be executed");
</pre>
<p>This isn&#8217;t really a SQL oriented tutorial and so I&#8217;ll skim over it. We just grab all the posts from the table so that we can add it to the feed. Nothing else fancy going on over there. </p>
<h4>Populating the items list</h4>
<pre name="code" class="php">
while ($row = mysql_fetch_array($result, MYSQL_ASSOC) {
echo '&lt;item>
		 &lt;title>'.$row['title'].'&lt;/title>
		 &lt;link>'.$row['link'].'&lt;/link>
		 &lt;description>'.$row['description'].'&lt;/description>
	   &lt;/item>';
}
</pre>
<p>We grab each individual record and then print it inside the relevant element to create the items list. Note that since I wanted a hash to work with I set the result type to MYSQL_ASSOC. </p>
<p>And with that the PHP part is done. The complete code should look like below. </p>
<pre name="code" class="php">
 &lt;?php
     header("Content-Type: application/rss+xml; charset=utf-8");
 ?>

 &lt;?xml version="1.0" encoding="utf-8"?>
 &lt;rss version="2.0">
 &lt;channel>
	&lt;title>My feed&lt;/title>
   &lt;link>http://www.somesite.com&lt;/link>
   &lt;description>Random ravings <img src='http://net.tutsplus.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> &lt;/description>

 &lt;?php
    DEFINE ('DB_USER', 'some_username');
	 DEFINE ('DB_PASSWORD', 'some_unusually_weak_password');
	 DEFINE ('DB_HOST', 'localhost');
	 DEFINE ('DB_NAME', 'database'); 

	 $connection = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD) or
	 die('Connection to the specified database couldn't be established');
	 mysql_select_db(DB_NAME)  or
	 die ('Specified database couldn't be selected');  

	 $query = "SELECT * FROM posts ORDER BY date DESC";
	 $result = mysql_query($query) or die ("Query couldn't be executed");  

	 while ($row = mysql_fetch_array($result, MYSQL_ASSOC) {
		echo '&lt;item>
			 	&lt;title>'.$row['title'].'&lt;/title>
		 		&lt;link>'.$row['link'].'&lt;/link>
		 		&lt;description>'.$row['description'].'&lt;/description>
	  	 	  &lt;/item>';
	 }
 ?>

 &lt;/channel>
 &lt;/rss>
</pre>
<p>You should now be able to access your feed at www.yoursite.com/feed.</p>
<h3>Validate your Feed</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/474_feed/images/validfeed.jpg" alt="Feed image" border="0" /></div>
<p>Just like with xHTML, RSS/XML needs to be well-formed and without errors. There are a number of validators to help you with this. Here are some of my often used ones.</p>
<ul>
<li><a href="http://validator.w3.org/feed/">W3C&#8217;S Validator</a></li>
<li><a href="http://beta.feedvalidator.org/">Feed Validator</a></li>
<li><a href="http://www.rssboard.org/rss-validator">RSS Board&#8217;s Validator</a></li>
</ul>
<p>Since RSS can only handle escaped HTML, make sure you use &amp;lt; lt; for < and &amp;lt; gt; for > respectively. Also make sure you replace special characters to their respective HTML codes. Forgetting to do so will probably result in invalid markup and break the feed.</p>
<h3>All Done! Publish that Feed</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/474_feed/images/feednotify.jpg" alt="Feed image" border="0" /></div>
<p>Now that we&#8217;ve created the feed and made sure it validates, we can now go publish it. You can use a service like Feedburner to manage your feeds. This lets you glean a lot of information including how many subscribers you have. Or you can take the easy way out and just link to your feed on your site.</p>
<p>Have you ever noticed the feed icon on your browser lighting up for certain pages alone? This means the browser has been notified that a feed of the current page is available for subscription. In order for the user&#8217;s browser to automatically detect the feed&#8217;s presence you need to add this small snippet to the head section of your page:</p>
<pre name="code" class="html">
&lt;link rel="alternate" type="application/rss+xml" title="Article RSS Feed"
href="http://www.yoursite.com/feed" />
</pre>
<p>You need not limit yourself to one feed. You may have a feed for each author or a feed for each category of the products you sell. Feel free to add as many feeds you want to the head section. </p>
<h3>Conclusion</h3>
<p>And that brings us to an end to this joy ride. We&#8217;ve gone over what feeds are, what purpose they serve and the different formats available. Next we looked at RSS, its skeleton structure and then learned how to create a simple dynamic RSS feed. Hopefully you&#8217;ve found this tutorial interesting and this has been useful to you.</p>
<p>Questions? Nice things to say? Criticisms? Hit the comments section and leave me a comment. Happy coding!</p>
<ul class="webroundup">
<li>Follow us on <a href="http://www.twitter.com/nettuts">Twitter</a>, or subscribe to the <a href="http://feeds.feedburner.com/nettuts" title="Nettuts+ RSS Feed">Nettuts+ RSS Feed</a> for the best web development tutorials on the web.</li>
</ul>
<p>
<script type="text/javascript"><!--digg_url = "post permalink (not digg url)"; // -->
</script><br />
<script src="http://digg.com/tools/diggthis.js" type="text/javascript"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/other/feeds-101/feed/</wfw:commentRss>
		<slash:comments>61</slash:comments>
		</item>
		<item>
		<title>The Only SEO Tools You&#8217;ll Ever Need</title>
		<link>http://net.tutsplus.com/tutorials/other/the-only-seo-tools-youll-ever-need/</link>
		<comments>http://net.tutsplus.com/tutorials/other/the-only-seo-tools-youll-ever-need/#comments</comments>
		<pubDate>Wed, 30 Sep 2009 12:40:35 +0000</pubDate>
		<dc:creator>Siddharth</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[seo]]></category>

		<guid isPermaLink="false">http://net.tutsplus.com/?p=6998</guid>
		<description><![CDATA[<img src="http://nettuts.s3.amazonaws.com/451_seo/200x200.jpg" alt="Essential SEO Tools" />]]></description>
			<content:encoded><![CDATA[<p>Search Engine Optimization is a rather complex and never ending process. You have to analyze a lot of things including what keywords people are searching for, the density of those keywords in your sites, how many sites link back to you, how popular your links are and so on. Doing all this manually can be a huge pain. </p>
<p>With that in mind, regardless of whether you&#8217;re an SEO guru or a beginner, these twenty tools are guaranteed to make your life easier. </p>
</p>
<p><span id="more-6998"></span></p>
<h3>Keyword Research</h3>
<p>When people &#8211; like us &#8211; build web sites, they assume they know what keywords people use to get to their sites. For the basic keywords this works but there a lot of untapped keywords that you might be unaware of. Doing the proper research to find out all possible keywords is imperative in this case. The keyword research tools below let you do all that in a jiffy.</p>
<h3><a href="http://www.google.com/sktool/">Google Search Based Keyword Tool</a></h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/451_seo/images/gsb.png" alt="Google Search Based Keyword Tool" border="0" /></div>
<p>Google&#8217;s tool provides keyword ideas and suggestions siphoned directly from Google&#8217;s search data. This is slightly different from the Adwords Keyword tool in that it suggests keywords not already associated with your Adwords account and provides a lot more information. </p>
<p>Just key in your site and normal keywords and let it provide you with a plethora of new ideas.</p>
<h3><a href="http://freekeywords.wordtracker.com/">WordTracker</a></h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/451_seo/images/wt.png" alt="WordTracker" border="0" /></div>
<p>An excellent tool, with a paid counterpart, which lets you find out related keywords you might have missed out on so far. It also provides rough estimations of the search volume generated by the keywords.  </p>
<h3><a href="http://tools.seobook.com/keyword-tools/seobook/">SEOBook Keyword Suggestions</a></h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/451_seo/images/sbk.png" alt="SEOBook Keyword Suggestions" border="0" /></div>
<p>This tool cross references the keyword you input with multiple search engines to provide suggestions.</p>
<h3><a href="http://adlab.msn.com/Keyword-Forecast/default.aspx">Microsoft&#8217;s Keyword Forecast</a></h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/451_seo/images/msdn.jpg" alt="Microsoft's Keyword Forecast" border="0" /></div>
<p>This tool predicts search volume and impressions for the keywords you enter into the system. Useful tool when you are about to launch a SEO campaign. Also provides a ton of target demographic data you&#8217;d want to take advantage of. </p>
<h3><a href="http://www.keyworddiscovery.com/search.html">Trellian&#8217;s Keyword Discovery</a></h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/451_seo/images/kwd.png" alt="Trellian's Keyword Discovery" border="0" /></div>
<p>Another popular keyword research tool with a paid version available for those who want additional features. Just type in your basic keywords and let it generate a list of top keywords which will work well for you.</p>
<h3>Keyword Density</h3>
<p>The number of times a keyword occurs in your page&#8217;s content is extremely important. Be too skimpy and your site won&#8217;t be counted for that keyword. Go overboard and you&#8217;ll be penalized for keyword stuffing. The optimum numbers seems to be between 2 to 4 percent and these tools will let you make sure you make this number.</p>
<h3><a href="http://tools.seobook.com/general/keyword-density/">SEOBook Keyword Density Analyzer</a></h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/451_seo/images/sbkd.png" alt="SEOBook Keyword Density Analyzer" border="0" /></div>
<p>Just enter your URL and let the tool do its thing. It shows you which keywords are present most in your content, how many times it occurs and how much place it takes up relative to the other words on the page. </p>
<h3><a href="http://www.iwebtool.com/keyword_density">iWebTool Keyword Density Checker</a></h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/451_seo/images/iwebkd.png" alt="iWebTool Keyword Density Checker" border="0" /></div>
<p>Another tool which looks through your page and creates a tag cloud. If you prefer raw data, it also shows you how many times each keyword occurs on your page. </p>
<h3><a href="http://www.webconfs.com/keyword-density-checker.php">Webconfs Keyword Cloud</a></h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/451_seo/images/webconfkd.jpg" alt="Webconfs Keyword Cloud" border="0" /></div>
<p>Webconfs&#8217; tool produces a keyword cloud for easy perusal. Just like with other tools it also produces a listing of which keyword occurs the most and its density.</p>
<h3>Search Engine Rank Checkers</h3>
<h3><a href="http://www.linkvendor.com/seo-tools/multi-pagerank.html">Link Vendor&#8217;s Page Rank Checker</a></h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/451_seo/images/lvr.png" alt="link Vendor's Page Rank Checker" border="0" /></div>
<p>This Page Rank checker lets you find out your Page Rank at individual Google data centers. </p>
<h3><a href="http://www.pageranktool.net/">PageRank Tool</a></h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/451_seo/images/prt.png" alt="PageRank Tool" border="0" /></div>
<p>This tools lets you find out your page rank quickly with minimal fuss.</p>
<h3><a href="http://www.selfseo.com/check_google_pagerank.php">Self SEO Rank Checker</a></h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/451_seo/images/sslc.png" alt="Self SEO Rank Checker" border="0" /></div>
<p>You can find out your PageRank and Alexa rating along with a bunch of other useful info using this tool. </p>
<h3>Link Popularity</h3>
<p>A major part of SEO is getting linked. The number of backlinks you are getting is a fair approximation of how well your site is doing and makes tracking this statistic an important affair. Using these tools, you can find out who links to you, which pages are linked the most and a lot of other data.</p>
<h3><a href="http://www.webmaster-toolkit.com/link-popularity-checker.shtml">WebMaster Toolkit Link Popularity Checker</a></h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/451_seo/images/wtpop.jpg" alt="WebMaster Toolkit Link Popularity Checker" border="0" /></div>
<p>Just enter the URL in question and it&#8217;ll show you how many pages popular search engines link to through their search engine result pages. </p>
<h3><a href="http://www.seocentro.com/tools/search-engines/link-popularity.html">SEOCentro Link Popularity Check Tool</a></h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/451_seo/images/centropop.jpg" alt="SEOCentro Link Popularity Check Tool" border="0" /></div>
<p>Lets you know how many incoming links you have and breaks it down to individual search engines. Also provides an interesting table of sites with differing numbers of incoming links for reference.</p>
<h3><a href="http://www.linkvendor.com/seo-tools/site-analysis.html">LinkVendor&#8217;s Link Popularity Tool</a></h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/451_seo/images/linkvendorpop.jpg" alt="LinkVendor's Link Popularity Tool" border="0" /></div>
<p>An excellent tool which provides a plethora of information including how many web sites link to you, how many individual linkbacks you get, your PageRank, your Alexa rank and so much more.</p>
<h3>Site Analytics</h3>
<p>Monitoring your site&#8217;s traffic, page views and visitor behavior is extremely important once you&#8217;ve finished the initial SEO to make sure your plan is sound. Use these tools to track down your site&#8217;s statistics.</p>
<h3><a href="www.google.com/analytics/">Google Analytics</a></h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/451_seo/images/ga.jpg" alt="Google Analytics" border="0" /></div>
<p>Google Analytics provides an extremely slick summary of your data. Use it to check which pages get linked to the most, how much time people spend on your site, what percentage of visitors are new and a lot more. </p>
<h3><a href="http://www.compete.com/">Compete</a></h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/451_seo/images/compete.jpg" alt="Compete" border="0" /></div>
<p>Just like Google Analytics, this tool presents an extremely pleasing way to monitor your site&#8217;s well being. As a fun feature, it lets you compare the stats of up to 5 different sites.</p>
<h3><a href="http://haveamint.com/">Mint</a></h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/451_seo/images/mint.jpg" alt="Mint" border="0" /></div>
<p>If you don&#8217;t mind a paid solution, Mint is a top-notch analytics suite which a lot of developers swear by. It features a beautiful interface to present all the data.</p>
<h3>Crawl tests</h3>
<p>Understanding how your pages look to spiders (heh) is important while optimizing for them. This lets us strip out all the visual elements and see the page as a crawler would see. Such a test helps you understand how accessible a page is to a crawler and lets you weed out potential issues before full deployment. These 3 tools let you do just that.</p>
<h3><a href="http://tools.seobook.com/general/spider-test/">SEOTools Spider Test</a></h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/451_seo/images/seobookspider.png" alt="SEOTools Spider Test" border="0" /></div>
<p>This tool not only lets you see how your page looks to spiders but also returns a lot of useful information including the number of words in the page, the keyword density and pages you link to.</p>
<h3><a href="http://www.iwebtool.com/spider_view">iWebTool Spider View</a></h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/451_seo/images/iwebspider.png" alt="iWebTool Spider View" border="0" /></div>
<p>If you are just looking to find a tool to simulate a spider without any extra frills, this is the tool for you. Crawls through your site and lets you see how it looks to a bot.</p>
<h3><a href="http://www.webconfs.com/search-engine-spider-simulator.php">WebConfs&#8217; Spider Simulator</a></h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/451_seo/images/webconfspider.png" alt="WebConfs' Spider Simulator" border="0" /></div>
<p>WebConfs&#8217; Spider Simulator simulates a spider crawling through your site. Shows you how a page looks to a spider and also nets you the list of sites you link to, the meta description and meta keyword.</p>
<h3>Conclusion</h3>
<p>I hope this list made it easier for you optimize your web applications for search engines. With the internet being a big place, I am sure I&#8217;ve missed a ton of equally useful SEO tools. Let us know about these hidden gems in the comments. Thanks for reading! </p>
<ul class="webroundup">
<li>Follow us on <a href="http://www.twitter.com/nettuts">Twitter</a>, or subscribe to the <a href="http://feeds.feedburner.com/nettuts" title="Nettuts+ RSS Feed">Nettuts+ RSS Feed</a> for more daily web development tuts and articles.</li>
</ul>
<p>
<script type="text/javascript"><!--digg_url = "post permalink (not digg url)"; // -->
</script><br />
<script src="http://digg.com/tools/diggthis.js" type="text/javascript"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/other/the-only-seo-tools-youll-ever-need/feed/</wfw:commentRss>
		<slash:comments>110</slash:comments>
		</item>
		<item>
		<title>A Deeper Look at mod_rewrite for Apache</title>
		<link>http://net.tutsplus.com/tutorials/other/a-deeper-look-at-mod_rewrite-for-apache/</link>
		<comments>http://net.tutsplus.com/tutorials/other/a-deeper-look-at-mod_rewrite-for-apache/#comments</comments>
		<pubDate>Mon, 14 Sep 2009 17:53:05 +0000</pubDate>
		<dc:creator>Joseph Pecoraro</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[mod rewrite]]></category>
		<category><![CDATA[mod_rewrite]]></category>

		<guid isPermaLink="false">http://net.tutsplus.com/?p=6708</guid>
		<description><![CDATA[<img src="http://nettuts.s3.amazonaws.com/435_htaccess/200x200.jpg" alt="A Deeper Look at mod_rewrite" />]]></description>
			<content:encoded><![CDATA[<p>When people think of .htaccess configuration the first thing that pops into most people&#8217;s minds is URL manipulation with mod_rewrite. People typically get frustrated with mod_rewrite&#8217;s complexity.  This tutorial will walk you through everything you need to know for the most common mod_rewrite tasks.</p>
<p><span id="more-6708"></span></p>
<p>When people think of .htaccess configuration the first thing that pops into<br />
most people&#8217;s minds is URL manipulation with mod_rewrite. Thoughts on<br />
mod_rewrite vary quite a bit. To get a quick feel for what the world thinks<br />
for it I just ran a twitter search on &#8220;mod_rewrite&#8221; and picked a few from the<br />
front pages at the time I started this article:</p>
<blockquote>
<p><a href="http://twitter.com/mldk">mldk</a>: Aargh! .htaccess and mod_rewrite can be such<br />
  a pain in the &#8212;!</p>
<p><a href="http://twitter.com/bsterzenbach">bsterzenbach</a>: Man do I love mod_rewrite. I<br />
  could work with it the rest of my life and still not master it &#8211; so powerful</p>
<p><a href="http://twitter.com/mikemackay">mikemackay</a>: Still loving the total<br />
  flexibility of mod_rewrite &#8211; coming to the rescue again. Often so<br />
  overlooked&#8230;and easier than you might think too!</p>
<p><a href="http://twitter.com/hostpc">hostpc</a>: I hate mod_rewrite. Can&#8217;t get this dang<br />
  application to work properly <img src='http://net.tutsplus.com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<p><a href="http://twitter.com/awanderingmind">awanderingmind</a>: Oh Wordpress and<br />
  Apache, how thou dost vex me. Mod_rewrite be damned!</p>
<p><a href="http://twitter.com/danielishiding">danielishiding</a>: Why won&#8217;t mod_rewrite<br />
  work! Damn it!</p>
</blockquote>
<p>A few things I noticed are that people clearly recognize the power of<br />
mod_rewrite but are often frustrated by the syntax. Thats not surprising<br />
considering the front page of <a href="http://httpd.apache.org/docs/2.0/rewrite/">Apache&#8217;s mod_rewrite documentation</a> says<br />
basically the same thing:</p>
<blockquote>
<p>Despite the tons of examples and docs, mod_rewrite is voodoo. Damned cool<br />
  voodoo, but still voodoo.&#8221; &#8212; <a href="http://httpd.apache.org/docs/2.0/rewrite/">Brian Moore</a></p>
</blockquote>
<p>What a turn off! So, in this article I&#8217;m really going to take things down a<br />
notch. I&#8217;m going to try and address not only mod_rewrite&#8217;s syntax but try and<br />
provide a workflow that you can use to debug and solve your mod_rewrite<br />
problems. I&#8217;m also going to give you a few useful real-world examples.</p>
<p>However, before I start I&#8217;m going to give a warning. With many subjects, this<br />
one in particular, you won&#8217;t learn unless you try on your own! That is one of<br />
the reasons I&#8217;m going to focus on teaching a debug workflow. As usual I&#8217;ll<br />
show you how to get your system setup if you don&#8217;t already have the module<br />
loaded. I urge you to work through the examples on your own server, preferably<br />
in a test environment. The more experience and success that you have the<br />
easier it will be to expand on that knowledge to more advanced examples and<br />
applications. Enjoy.</p>
<h3 id="what_is_mod_rewrite">What is mod_rewrite?</h3>
<p>mod_rewrite is an Apache module that allows for<br />
server-side manipulation of requested URLs. Incoming URLs are checked against<br />
a series of rules. The rules contain a regular expression to detect a<br />
particular pattern. If the pattern is found in the URL, and the proper<br />
conditions are met, the pattern is replaced with a provided substitution<br />
string or action. This process continues until there are no more rules left or<br />
the process is explicitly told to stop.</p>
<p>This is summarized in these three points:</p>
<ul>
<li>There are a list of rules that are processed in order.</li>
<li>If a rule matches it checks the conditions for that rule.</li>
<li>If everything is a go it makes a substitution or action.</li>
</ul>
<h3 id="advantages_of_mod_rewrite">Advantages of mod_rewrite</h3>
<p>There are some obvious advantages of using a URL rewriting tool like this but<br />
there are some things that are probably not as obvious.</p>
<p>The main reason people use mod_rewrite are to transform ugly, cryptic URLs into<br />
what are known as &#8220;friendly URLs&#8221; or &#8220;<a href="http://www.seoconsultants.com/articles/1000/url-rewriting.asp">clean URLs</a>.&#8221;  The new URLs are<br />
friendly in more ways then one. They are user friendly often making it much<br />
easier for humans to understand at a glance and possibly manipulate on their<br />
own. As an added bonus these URLs are also more search engine friendly.<br />
Creating friendly URLs is one search engine optimization technique. URLs are an<br />
effective way to describe the content its linking to. Take the following example:</p>
<pre name="code" class="html">Not so friendly: http://example.com/user.php?id=4512
Much friendlier: http://example.com/user/4512/
Even better:     http://example.com/user/Joe/
</pre>
<p>Not only is the final link easier on the eyes, its possible for search engines to<br />
extract semantic meaning from it. This basic kind of URL rewriting is one way<br />
that mod_rewrite is used. However, as you will see it can do a lot more<br />
then just these simple transformations.</p>
<p>Expanding on the same example, some people claim there are security benefits<br />
by having mod_rewrite tranform your URLs. Given the same example, imagine<br />
the following attack on the user id:</p>
<pre name="code" class="html">http://example.com/user.php?id=AHHHHHH
http://example.com/user/AHHHHHH/
</pre>
<p>In the first example the php script is explicitly being invoked and must handle<br />
the invalid id number. A poorly written script would likely fail and in a more<br />
extreme case (in a poorly written web application) bad input could cause data<br />
corruption. However, if the user is only ever shown the friendlier URLs they<br />
wouldn&#8217;t even know that the user.php page existed. They might only know about<br />
the friendly URL structure. Trying the same attack in that case would likely fail<br />
before it even reaches the php script. This is because at the core of mod_rewrite is<br />
regular expression pattern matching. In the example case above you would have<br />
been expecting a number, for example <code>(\d+)</code>, not characters like <code>a-z</code>.  The<br />
rewrite would have failed as soon as it found letters instead of numbers.</p>
<p>This extra layer of abstraction is nice from a security perspective. You could<br />
even prevent direct access to the original PHP scripts if you wanted. However,<br />
I am in no way condoning using mod_rewrite as a replacement for the usual<br />
security measures. You should always have server-side validation in your<br />
scripts.</p>
<h3 id="enabling_mod_rewrite_in_the_server">Enabling mod_rewrite on the Server</h3>
<p>Just like enabling .htaccess support, enabling mod_rewrite or any apache module<br />
must be done from the global configuration file (httpd.conf). Just as before,<br />
since mod_rewrite usage is so widespread hosting companies nearly always have<br />
it enabled. However, if you suspect that your hosting company does not have it<br />
enabled, and we will test for that below, you should contact them and they will<br />
likely enable it.</p>
<p>If you rolled your own Apache installation its worth noting that mod_rewrite<br />
needs to be included when compiled Apache, as it is not done so by default.<br />
However, its so common that nearly all installation guides, including<br />
<a href="http://httpd.apache.org/docs/2.2/install.html#configure">Apache&#8217;s</a> show how in their example. However, pre-packaged versions will<br />
have it enabled. If you&#8217;re reading this there is probably a 99% chance that<br />
mod_rewrite is compiled on your Apache, so you can just proceed to the next<br />
step.</p>
<p>If you&#8217;re the administrator for your webserver and you want to make sure that<br />
you load the module you should look in the httpd.conf file. In the<br />
configuration file there will be a large section which just loads a whole<br />
bunch of modules. The following line will likely appear in the file. If it<br />
is, great!  If its commented out, meaning there is a # symbol at the start<br />
of the line then remove the # to be left with:</p>
<pre name="code" class="html">LoadModule rewrite_module modules/mod\_rewrite.so
</pre>
<p>Olders version of Apache 1.3, may require you to add the following directive,<br />
after the <code>LoadModule</code> directive.</p>
<pre name="code" class="html"># Only in Apache 1.3
AddModule mod\_rewrite.c
</pre>
<p>However, this seems to have <a href="http://www.webmasterworld.com/forum92/94.htm">disappeared in Apache 2</a> and later. Only the<br />
LoadModule directive is required.</p>
<p>If you had to modify the configuration file at all then you will have to<br />
restart the web server. As always you should remember to make a backup of the<br />
original file in case you need to revert back to it later.</p>
<h3 id="testing_for_mod_rewrite">Testing for mod_rewrite</h3>
<p>You can test if mod_rewrite is enabled/working in a number of ways. One of the<br />
simplest ways is to view the output from PHP&#8217;s <code>phpinfo</code> function. Create this<br />
very simple PHP page, open it in your browser and search for &#8220;mod_rewrite&#8221; in<br />
the output.</p>
<pre name="code" class="php">&lt;?php phpinfo(); ?&gt;
</pre>
<p>mod_rewrite should show up in the &#8220;Loaded Modules&#8221; section of the page like so:</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/phpinfo.png" alt="Good, mod_rewrite enabled" style="width: 600px;" /></div>
<p>However, if you&#8217;re not using PHP (although I will for the rest of the tutorial)<br />
there are some others ways to check. Apache comes with a number of command<br />
line tools. I mentioned the htpasswd tool in the first tutorial for Basic<br />
Authentication. You can use other tools like apachectl or httpd to directly<br />
test for the module. There are command line switches that allow<br />
you to check all of the loaded modules in the existing installation. You<br />
can execute the following to get a listing of all of the loaded modules.</p>
<pre name="code" class="html"> shell&gt; apachectl -t -D DUMP_MODULES </pre>
<p>Here I show the help page for the command. I then run the command and<br />
search for &#8220;rewrite&#8221; in the results and it shows there was a line of output<br />
that matched!</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/apachectl.png" alt="apache test" style="width: 600px;" /></div>
<p>Finally, if you are still unsure if its enabled, like before just give it a<br />
shot and see what happens!  I&#8217;ll go over the syntax later but here would be<br />
a very bare bones test to see if its working. The following .htaccess file<br />
would redirect any request in the given folder to the good.html file. That<br />
means if mod_rewrite is working you should see good.html. If mod_rewrite<br />
is not working then you will see index.html which shows a warning.</p>
<pre name="code" class="html"># Redirect everything in this directory to "good.html"
RewriteEngine on
RewriteRule .* good.html
</pre>
<p>Here are the Good and Bad result pages:</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/bare_good.png" alt="Good, mod_rewrite worked" /></div>
<div class="tutorial_image">
<img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/bare_bad.png" alt="Bad, mod_rewrite didn't work" /></div>
<h3 id="inside_htaccess">Inside .htaccess</h3>
<p>As always, anything that you can put in a .htaccess file can also be put inside<br />
the global configuration file. With mod_rewrite there is a small differences<br />
if you put a rule in one or the other. Most noticeably:</p>
<blockquote>
<p>if you&#8217;re putting [&#8230;] rules in an .htaccess file [&#8230;] the directory<br />
  prefix (/) is removed from the REQUEST_URI variable, as all requests are<br />
  automatically assumed to be relative to the current directory.<br />
  &#8211; <a href="http://httpd.apache.org/docs/2.2/rewrite/rewrite_intro.html#htaccess">Apache Documentation</a></p>
</blockquote>
<p>Just something to keep in mind if you see examples online or if you&#8217;re trying<br />
an example yourself, beware of the leading slash!  I will attempt to clarify<br />
this below when we got through some examples together.</p>
<h3 id="regular_expressions">Regular Expressions</h3>
<p>This tutorial does not intend to teach you regular expressions.  For those of<br />
you that know regular expressions, the regular expressions used in mod_rewrite<br />
seem to vary between versions of Apache.  In Apache 2.0 they seem to be<br />
<a href="http://perldoc.perl.org/perlre.html">Perl Compatible Regular Expressions (PCRE)</a>. This means that many of the<br />
shortcuts you are used to, such as <code>\w</code> meaning <code>[A-Za-z0-9_]</code>, <code>\d</code> meaning<br />
<code>[0-9]</code>, and much more <em>do</em> exist.  However, my hosting company uses Apache 1.3<br />
and the regular expressions are more limited.</p>
<p>If you don&#8217;t know regular expressions here are some useful tutorials that will<br />
bring you up to speed quickly.</p>
<ul>
<li><a href="http://blog.themeforest.net/screencasts/a-crash-course-in-regular-expressions/">Nettuts very own Jeffrey&#8217;s Crash Course</a></li>
<li><a href="http://immike.net/blog/2007/04/06/the-absolute-bare-minimum-every-programmer-should-know-about-regular-expressions/">The Absolute Bare Minimum Every Programmer Should Know About Regular Expressions</a></li>
<li><a href="http://en.kerouac3001.com/regex-tutorial-8.htm">Quick And Practical Tutorial</a></li>
<li><a href="http://www.smashingmagazine.com/2009/05/06/introduction-to-advanced-regular-expressions/">Smashing Magazine Links on Regular Expressions</a></li>
</ul>
<p>And a few references that everyone should know about:</p>
<ul>
<li><a href="http://www.addedbytes.com/download/regular-expressions-cheat-sheet-v2/png">Popular Added Bytes Cheatsheet For Regular Expressions</a></li>
<li><a href="http://www.addedbytes.com/apache/mod_rewrite-cheat-sheet/">Added Bytes Cheatsheet for mod_rewrite</a></li>
<li><a href="http://rick.measham.id.au/paste/explain.pl?regex=%5Cd%2B%28.%5Cd%2B%29%3F%28%5BeE%5D%5Cd%2B%29%3F">Explain Regular Expressions</a></li>
</ul>
<p>If you haven&#8217;t spent the time to learn regular expressions I highly suggest<br />
that you take the time to learn them. As is usually the case, they are not as<br />
complex as you may think they are. I selected the links above from my years of<br />
experience working with regular expressions. I feel that these guides do a very<br />
good job of getting the basics across. Regular Expressions are crucial to know<br />
if you want to effectively use mod_rewrite, and they are also useful to know<br />
for many different aspects of general development, such as &#8220;find/replace&#8221; in<br />
your favorite code editor!</p>
<h3 id="getting_a_feel_for_it">Getting a Feel for it.</h3>
<p>Okay, you&#8217;ve waited patiently enough, lets run through a quick example. This is<br />
included in the linked source files. Here is the code from the <code>.htaccess</code> file:</p>
<pre name="code" class="html"># Enable Rewriting
RewriteEngine on

# Rewrite user URLs
#   Input:  user/NAME/
#   Output: user.php?id=NAME
RewriteRule ^user/(\w+)/?$ user.php?id=$1
</pre>
<p>Before I can explain any of it I have to give you more information about the<br />
other files in the directory.</p>
<p>The directory contains an index.php and a user.php file. The index just has<br />
some links, of various formats, to the user page. The php code is purely debug<br />
to show that the page was accessed and what the given &#8220;id&#8221; parameter contained.<br />
Here is user.php code:</p>
<pre name="code" class="php">&lt;?php

// Get the username from the url
$id = $_GET['id'];

?&gt;&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"&gt;
&lt;head&gt;
    &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8"/&gt;
    &lt;title&gt;Simple mod\_rewrite example&lt;/title&gt;
    &lt;style type="text/css"&gt; .green { color: green; } &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;h1&gt;You Are on user.php!&lt;/h1&gt;
  &lt;p&gt;Welcome: &lt;span class="green"&gt;&lt;?php echo $id; ?&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>This example has a few different parts. First, notice that URL Rewriting must<br />
be enabled via the <code>RewriteEngine</code> directive!  If your .htaccess file is going<br />
to use rewrite rules you should always include this line, otherwise you can&#8217;t<br />
be sure if its enabled or not!  As a rule of thumb, always include it and make<br />
sure that you only have it once per .htaccess file.  The string &#8220;on&#8221; is case<br />
insensitive.  So when you see other examples on the net that show &#8220;On&#8221;, that<br />
is equally acceptable.</p>
<p>The first <code>RewriteRule</code> is for handling the user.php page. As the comments<br />
indicate we are rewriting the friendly URL into the format of the normal URL.<br />
To do that, when the friendly URL comes in as input we are actually<br />
transforming it into the standard query string URL. Breaking it down we get:</p>
<pre name="code" class="html">The Rule:
RewriteRule ^user/(\w+)/?$ user.php?id=$1

Pattern to Match:
^              Beginning of Input
user/          The REQUEST_URI starts with the literal string "user/"
(\w+)          Capture any word characters, put in $1
/?             Optional trailing slash "/"
$              End of Input

Substitute with:
user.php?id=   Literal string to use.
$1             The first (capture) noted above.
</pre>
<p>Here are some examples and an explanation for each:</p>
<table class="rewrite">
<caption>User.php</caption>
<thead>
<tr>
<th scope="col">Incoming</th>
<th scope="col">Match</th>
<th scope="col">Capture</th>
<th scope="col">Outgoing</th>
<th scope="col">Result</th>
</tr>
</thead>
<tbody>
<tr class="even">
<td>user.php?id=joe</td>
<td>No</td>
<td>&nbsp;</td>
<td>user.php?id=joe</td>
<td>Normal</td>
</tr>
<tr class="odd">
<td>user/joe</td>
<td>Yes</td>
<td>joe</td>
<td>user.php?id=joe</td>
<td>Good</td>
</tr>
<tr class="even">
<td>user/joe/</td>
<td>Yes</td>
<td>joe</td>
<td>user.php?id=joe</td>
<td>Good</td>
</tr>
<tr class="odd">
<td>user/joe/x</td>
<td>No</td>
<td>&nbsp;</td>
<td>user/joe/x</td>
<td>Fail</td>
</tr>
</tbody>
</table>
<p>So the first example goes through unaffected by the <code>RewriteRule</code> and works<br />
just fine. The second and third examples match the <code>RewriteRule</code>, are<br />
rewritten accordingly and end up working just fine. The last example does not<br />
match the rule and proceeds untouched. The server doesn&#8217;t have a<br />
<code>user</code> directory and fails trying to find it. This is as expected because<br />
<code>user/joe/x</code> is a bad URL in the first place!</p>
<p>This example was rather easy to understand. However, there were a lot of<br />
minute details that I glossed over. To do anything more complex I want to<br />
clarify exactly what is happening. In the next section I&#8217;m going to walk<br />
through exactly what happens and we will take a look at a more complex<br />
example that touches on all the core aspects of rewriting.</p>
<p>NOTE: If this example didn&#8217;t work for you its possible that your Apache or<br />
mod_rewrite versions are not PCRE compatible.  Try changing <code>^user/(\w+)/?$</code><br />
into <code>^user/([a-z]+)/?$</code>.  Notice that I did not use the <code>\w</code> shorthand.  If<br />
this version works for you then you will have to avoid the regex shortcuts<br />
and instead use their longer equivalents (see the Regular Expressions section<br />
above).</p>
<h3 id="flow_of_execution_in_detail">Flow of Execution in Detail</h3>
<p>The flow of execution through the rewrite rules is simple but its not exactly<br />
straightforward. So, I&#8217;m going to break it down into painful detail. It all<br />
starts with the user making a request to your server. They type a URL into<br />
their browser&#8217;s address bar, their browser translates that into an HTTP request<br />
to send to the server, Apache receives that request, and parses it into pieces.<br />
Here is an example:</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/url_full.png" alt="Full URL Analysis" /></div>
<p>Note that whenever I mention one of Apache&#8217;s variables I use a weird syntax:<br />
<code>%{APACHE_VAR}</code>. That is just because its similar to the syntax that<br />
mod_rewrite uses to access the variables. However, it is the name inside the<br />
braces that is important.</p>
<p>So what part does mod_rewrite deal with?  If you&#8217;re working inside a .htaccess<br />
file, then you&#8217;re working with the <code>REMOTE_URI</code> portion but <em>without the leading slash</em>!<br />
I mentioned this before, and its something that is very confusing for most<br />
people when they start out.  If you&#8217;re working from inside the global<br />
configuration file, then you would leave the leading slash in.</p>
<p>To be as specific as possible, buried in the <a href="http://httpd.apache.org/docs/2.2/rewrite/rewrite_intro.html#rewriterule">Apache Documentation</a> is<br />
this description of the &#8220;URL Part&#8221; that mod_rewrite acts on:</p>
<blockquote>
<p>The Pattern is always a regular expression matched against the URL-Path of<br />
  the incoming request (the part after the hostname but before any question<br />
  mark indicating the beginning of a query string).<br />
  <a href="http://httpd.apache.org/docs/2.2/rewrite/rewrite_intro.html#rewriterule">Apache Documentation</a></p>
</blockquote>
<p>To remove any ambiguity, highlighted in gold in these two URLs below is the<br />
&#8220;URL Part&#8221; that mod_rewrite acts on inside a .htaccess file:</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/url_part.png" alt="The Rewrite Portion of the URL" /></div>
<p>For the rest of this section I&#8217;ll be using these two URLs to describe the flow<br />
of execution. I will refer to the first url as the &#8220;green&#8221; URL and the second<br />
as the &#8220;blue&#8221; URL.  Also I will be using &#8220;URL Part&#8221; throughout this analysis,<br />
meaning the <code>REMOTE_URI</code> without the leading slash.</p>
<hr />
<p>For those readers that want to be 100% technical these two things that I am<br />
calling URLs are actually URIs. The definition of a Uniform Resource<br />
Identifier (URI) differs from a Uniform Resource Locator (URL). A URI is just<br />
an indicator of where a resource is. This means that multiple URIs can point<br />
to the same resource but are themselves different addresses. Following a URI<br />
might take any number of hops or redirections until it actually arrives at the<br />
resource. A URL however, is a stricter term that identifies the exact location<br />
of a resource. This subtle difference has blurred over time such that nobody<br />
cares about the difference. I will continue to use the term URL because people<br />
are more comfortable with it.</p>
<hr />
<p>So, now we know what the rewrite rules are going to be acting on. Once Apache<br />
has parsed the request it translates that to the file it thinks is needed and<br />
proceeds to fetch that file. At this point it will traverse directories and<br />
encounter the .htaccess files. Assuming the .htaccess file enables the<br />
RewriteEngine any RewriteRule could change the URL. A drastic enough change<br />
(such as one that points Apache to another directory instead of the original<br />
directory it was heading towards) will cause Apache to issue a sub-request<br />
and proceed to fetch the new file.</p>
<p>In most cases sub-requests are invisible to you. This implementation detail<br />
is not important to know for the majority of the simple rewrites that you will<br />
ever write or use. What is more important to know is how Apache processes<br />
the rewrite rules inside a .htaccess file.</p>
<p>The rules in a .htaccess file are processed in the order that they appear.<br />
Note that each <code>RewriteRule</code> is acting on the &#8220;URL Part&#8221; that is similar to<br />
the <code>REMOTE_URI</code>. When a rule makes a substitution, the modified &#8220;URL Part&#8221;<br />
will be handed to the next rule. That means that the URL that a rule is<br />
processing may have been edited by a previous rule! The URL is continually<br />
being updated by each rule that it matches. This is important!</p>
<p>Here is a flow chart that tries to provide a visualization of the generic<br />
flow of execution across multiple rules in a .htaccess file:</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/flow_chart.png" alt="mod_rewrite flow chart" /></div>
<p>Note that at the top of the flow chart the value going into the rewrite rules<br />
is that &#8220;URL Part&#8221; and if the substitution is successful the modified part<br />
proceeds into the next rule.</p>
<p>I mentioned rewriting conditions earlier but I didn&#8217;t go into detail. Each<br />
<code>RewriteCond</code> is associated with a single <code>RewriteRule</code>. The conditions appear<br />
before the rule they are associated with, but only get evaluated if the rule&#8217;s<br />
pattern matched. As the flow chart shows, if a rewrite rule&#8217;s pattern matches<br />
then Apache will check to see if there are any conditions for that rule. If there<br />
are no conditions then it <em>will</em> make the substitution and continue. If there<br />
are conditions then it will only make the substitution if <em>all</em> of the<br />
conditions are true. Lets visualize this in a concrete example.</p>
<p>The URLs that I&#8217;m working with are actually part of the &#8220;Profile Example&#8221; that<br />
I&#8217;ve included in the source code download in the &#8220;profile_example&#8221; directory.<br />
This is similar to the previous example with the user.php but it now has a<br />
profile.php page, an added rewrite rule, and a condition! Lets take a look at<br />
the code and Apache&#8217;s flow of execution through it:</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/profile_rules.png" alt="Profile Rewrite Rules" /></div>
<p>Here there are two rules. Rule #1 is the same as the user example we saw<br />
before. Rule #2 is new and notice that it has a Condition. The &#8220;URL Part&#8221; we<br />
have been discussing goes through the rules in order, top to bottom. So it will<br />
first go through Rule #1 and then Rule #2.</p>
<p>The key to understanding this example is to first understand the goal. In this<br />
example I am going to allow friendly profile URLs but I&#8217;m actually going to<br />
explicitly forbid access to the php page directly. Note, some people might say<br />
that this is a bad idea. They might say that as a developer this will make<br />
things harder for you to debug. Thats true, I don&#8217;t actually recommend doing a<br />
trick like this, but it makes for an excellent example! More practical uses for<br />
mod_rewrite will show up later in this tutorial.</p>
<p>So, with that in mind lets see what happens with our green URL.  This one we want<br />
to be successful.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/green_flow.png" alt="Green URL Execution" /></div>
<p>Up at the top you see Apache&#8217;s <code>THE_REQUEST</code> variable. I put this at the top<br />
because, unlike many of the Apache variables we will deal with, during the<br />
duration of the request this variables value will <em>never change</em>! That is one<br />
of the reasons why Rule #2 uses <code>%{THE_REQUEST}</code>. Underneath <code>THE_REQUEST</code> we<br />
see the green &#8220;URL Part&#8221; going into the first rule:</p>
<ul>
<li>The URL matches the pattern.</li>
<li>There are no conditions, so it continues.</li>
<li>The substitution is made.</li>
<li>There are no flags, so it continues.</li>
</ul>
<p>After making it through the first rule, the URL has changed. The total URL has<br />
been rewritten to <code>profile.php?id=joe</code> which Apache then breaks down and<br />
updates many of its variables. The <code>?id=joe</code> portion gets hidden from us and<br />
<code>profile.php</code>, the new &#8220;URL Part&#8221;, continues into the second rule. It is our<br />
first encounter with conditions:</p>
<ul>
<li>The URL matches the pattern.</li>
<li>There are conditions so we will try the conditions.</li>
<li>THE_REQUEST does not contains <code>profile.php</code> so the condition fails.</li>
<li>Because a condition failed we ignore the substitution and flags.</li>
<li>The URL is unchanged by this rule.</li>
</ul>
<p>At this point we made it through all the rewrites and the <code>profile.php?id=joe</code><br />
page will be fetched properly.</p>
<p>Here is how the execution looks for the blue URL, the one we want to fail:</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/blue_flow.png" alt="Blue URL Execution" /></div>
<p>Again I put the <code>THE_REQUEST</code> value at the top. The blue &#8220;URL Part&#8221; enters<br />
Rule #1:</p>
<ul>
<li>The URL does not match the pattern.</li>
<li>Everything else is ignored and the URL proceeds unchanged.</li>
</ul>
<p>The first rule was easy. As is often the case a URL that you have won&#8217;t match<br />
a rule&#8217;s patten and will proceed untouched. Now it enters Rule #2:</p>
<ul>
<li>The URL matches the pattern.</li>
<li>There are conditions so we will try the conditions.</li>
<li>THE_REQUEST contains <code>profile.php</code> so the condition passes.</li>
<li>All the conditions passed we can make the substitution.</li>
<li>&#8221;-&#8221; is a special substition that means don&#8217;t change anything.</li>
<li>There are flags on the rule so we process the flags</li>
<li>There is a <code>F</code> flag which means return a forbidden response.</li>
<li>A <code>403 Forbidden</code> response is sent to the client.</li>
</ul>
<p>A few things are worth re-iterating. In order for the substitution to work, all<br />
of the conditions have to pass. In this case there is only one, and it passes<br />
so the substitution happens. Note that <code>-</code> is a special substitution that<br />
doesn&#8217;t change anything. This is useful when you just want to use flags to do<br />
something for you, which is exactly what we want to do in this case.</p>
<p>Here is the familiar table breakdown of example URLs and their responses:</p>
<table class="rewrite">
<caption>Profile.php</caption>
<thead>
<tr>
<th scope="col">Incoming</th>
<th scope="col">Match</th>
<th scope="col">Capture</th>
<th scope="col">Outgoing</th>
<th scope="col">Result</th>
</tr>
</thead>
<tbody>
<tr class="even">
<td>profile.php?id=joe</td>
<td>Yes (#2)</td>
<td>&nbsp;</td>
<td>profile.php?id=joe</td>
<td>Forbidden</td>
</tr>
<tr class="odd">
<td>profile/joe</td>
<td>Yes (#1)</td>
<td>joe</td>
<td>profile.php?id=joe</td>
<td>Good</td>
</tr>
<tr class="even">
<td>profile/joe/</td>
<td>Yes (#1)</td>
<td>joe</td>
<td>profile.php?id=joe</td>
<td>Good</td>
</tr>
<tr class="odd">
<td>profile/joe/x</td>
<td>No</td>
<td>&nbsp;</td>
<td>profile/joe/x</td>
<td>Fail</td>
</tr>
</tbody>
</table>
<h3 id="syntax">Syntax</h3>
<p>While going over the syntax of <code>RewriteRule</code> and <code>RewriteCond</code> I would suggest<br />
that you first download the <a href="http://www.addedbytes.com/download/regular-expressions-cheat-sheet-v2/png">AddedBytes Cheatsheet</a>. This is because<br />
the cheatsheet lists the most useful server variables, flags, has regular<br />
expression tips, and even a few examples. There is just so much there that it<br />
would be difficult to put it inline.</p>
<p>Lets start with RewriteRule. You can always visit<br />
<a href="http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html#rewriterule">Apache&#8217;s Documentation on RewriteRule</a> if you need to do something<br />
really specific. Here is my overview:</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/syntax_rewriterule.png" alt="Syntax of RewriteRule" /></div>
<p>The cheatsheet shows what types of flags are available. Many tutorials cover these<br />
flags in detail, and I&#8217;ll go through the flags that I see most commonly used in<br />
the examples below.</p>
<p>Here is <a href="http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html#rewritecond">Apache&#8217;s Documentation on RewriteCond</a> and my overview:</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/435_htaccess/images/syntax_rewritecond.png" alt="Syntax of RewriteCond" /></div>
<h3 id="debug_workflow">Debug Workflow</h3>
<p>Whenever you&#8217;re working with mod_rewrite and creating new rules, always<br />
start with a simple, dumbed down version of the rule and work your way<br />
up towards the final version. Never try to do everything at once. The same<br />
thing applies for conditions. Add rules and conditions one at a time.<br />
Test often!</p>
<p>The key concept I am trying to get across with this approach is that this will<br />
let you know quickly if a change you made doesn&#8217;t work properly or causes<br />
something to work incorrectly. When doing too much at once inevitably you will<br />
run into an error and you will have to revert all of the changes you made to<br />
track down what the problem was. This is a very roller coaster approach and<br />
will likely lead to frustration. However, if you&#8217;re always steadily advancing,<br />
and each step along the way moving to workable checkpoints you&#8217;re in much,<br />
much better shape.</p>
<p>People often ignore this advice, create a complex rule, and it ends up not<br />
working.  Hours later they find out the problem was not in the complex portion,<br />
but instead it was just a simple mistake in the regular expression that could<br />
have been caught much earlier had they carefully constructed the rule like<br />
I&#8217;ve explained above. The same goes for deconstructing a rule to reverse<br />
engineer a problem. This approach will seriously reduce frustration!</p>
<h3 id="in_the_examples">In the Examples</h3>
<p>In the examples below I will always assume the website&#8217;s domain is<br />
<code>example.com</code>. This domain name is important because it affects the<br />
<code>HTTP_HOST</code> variable as well as specifying a redirect URL to another file on<br />
your website. Keep this in mind in case you intend to modify any of the examples<br />
for your own website. If so, simply replace &#8220;example.com&#8221; with your domain.<br />
For example, Nettuts would replace &#8220;example.com&#8221; with &#8220;nettuts.com&#8221;.</p>
<h3 id="removing_www">Removing www</h3>
<p>This is the most classic rewrite rule. This will make it so anyone who comes<br />
to your website via http://www.example.com they will get a hard redirect and<br />
thus the Location Bar in their browser will update accordingly.</p>
<pre name="code" class="html">RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]
</pre>
<p>The rule matches anything, and saves everything as <code>$1</code>. The important part<br />
in this example is the condition. The condition checks the <code>HTTP_HOST</code> variable<br />
to see if it started with &#8220;www.&#8221;  If this condition is true, the rewrite<br />
happens:</p>
<ul>
<li>The substitution is a full URL (it starts with http://)</li>
<li>The substitution contains $1 which was captured earlier</li>
<li>The [R=301] flag redirects the browser to the rewritten URL, this is a hard<br />
redirect in the sense that it causes the browser to load the new page and<br />
update its Location Bar with the new URL.</li>
<li>The [L] flag means that this is the last rule to parse, the rewrite engine,<br />
should stop.</li>
</ul>
<p>If the incoming URL had been &#8220;http://www.example.com/user/index.html&#8221; then<br />
<code>HTTP_HOST</code> would have been <code>www.example.com</code> and the rewrite would happen<br />
creating <code>http://example.com/user/index.html</code>.</p>
<p>If the incoming URL had been &#8220;http://example.com/user/index.html&#8221; then<br />
<code>HTTP_HOST</code> would have been <code>example.com</code>, the condition would have failed<br />
and the rewrite engine would proceed with the URL unchanged.</p>
<h3 id="forbid_hotlinking">Forbid Hotlinking</h3>
<p>Hotlinking, referred to as <a href="http://en.wikipedia.org/wiki/Inline_linking">Inline Linking on Wikipedia</a>, is the term<br />
used to describe one site leeching off of another site. Usually one site, the<br />
Leecher, will include a link to some media file (lets say an image or video)<br />
that is hosted on another site, the Content Host.  In this scenario, the<br />
Content Host&#8217;s servers are wasting bandwidth serving content to some other<br />
website.</p>
<p>For many people, its fine if other sites cross link to their content.  However,<br />
many people would rather prevent hotlinking so as not to pay for the extra<br />
bandwidth required to send the content to someone else&#8217;s site.</p>
<p>The most common, and basic approach to preventing hotlinking is to whitelist<br />
a number of websites, and block everything else. To find out who is asking<br />
for the content from your site you can check the referrer.  The <code>HTTP_REFERER</code><br />
header (yes that is how it is spelled) is set by the browser or client that<br />
is requesting the resource. In the end this is not 100% reliable, however it<br />
is more then effective at stopping the majority of hotlinking.  So, verify<br />
if the referrer is in a whilelist of acceptable referrers. If the referrer<br />
is not acceptable (blank or someone else&#8217;s site) then you can send them<br />
a forbidden warning:</p>
<pre name="code" class="html"># Give Hotlinkers a 403 Forbidden warning.
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^http://example\.net/?.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http://example\.com/?.*$ [NC]
RewriteRule \.(gif|jpe?g|png|bmp)$ - [F,NC]
</pre>
<p>Here the RewriteRule is checking for a request of a file with any popular<br />
image extension.  Such as .gif, .png, or .jpg.  You could add other extensions<br />
to this list if you want to protect .flv, .swf, or other files.</p>
<p>The domains that are allowed to access the content are &#8220;example.net&#8221; and<br />
&#8220;example.com&#8221;.  In either of these two cases a Rewrite Conditions will fail<br />
and the substitution won&#8217;t happen.  If any other domain makes an attempt, lets<br />
say &#8220;sample.com&#8221; attempts, then all the Rewrite Conditions will pass, the<br />
substitution will happen, and the <code>[F]</code> forbidden action will trigger.</p>
<h3 id="give_hotlinkers_a_warning_image">Give Hotlinkers a Warning Image</h3>
<p>The previous example returns a 404 Forbidden warning when someone trys to<br />
hotlink content from your server. You can actually go one step further, and<br />
send the hotlinker any resource of your choice. For example you can send<br />
a useful warning image can just be some text stating &#8220;hotlinking is not<br />
allowed&#8221;.  This way the other person can realize their mistake and host a copy<br />
on their own server.  The only change is to actually go through with the rewrite<br />
substitution and provide a choosen image instead of the one being requested:</p>
<pre name="code" class="html"># Redirect Hotlinkers to "warning.png"
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^http://example\.net/?.*$
RewriteCond %{HTTP_REFERER} !^http://example\.com/?.*$   [NC]
RewriteRule \.(gif|jpe?g|png|bmp)$ http://example.com/warning.png [R,NC]
</pre>
<p>Note that this is an example of what I call a &#8220;hard&#8221; or &#8220;external&#8221; redirect.<br />
The RewriteRule has a URL in the substitution portion and it also has the [R]<br />
flag.</p>
<h3 id="custom_404">Custom 404</h3>
<p>One trick that you can do with htaccess is check to see if the current &#8220;URL Part&#8221;<br />
leads to an actual file or directory on the web server. This is a good way to<br />
create a custom 404 &#8220;File not Found&#8221; page.  For example, if a user trys to<br />
fetch a page in a particular directory that doesn&#8217;t exist you can redirect them<br />
to any page you want, such as the index page or a custom 404 page.</p>
<pre name="code" class="html"># Generic 404 to show the "custom_404.html" page
# If the requested page is not a file or directory
# Silent Redirect: the user's URL bar is unchanged.
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* custom_404.html [L]
</pre>
<p>This is a great example of mod_rewrite&#8217;s file test operators.  They are<br />
identical to file tests in bash shell scripts and even Perl scripts.  Here<br />
the condition checks if the <code>REQUEST_FILENAME</code> is not a file and not a<br />
directory.  In the case where it is neither, then then there is no such<br />
file for the request.</p>
<p>If the incoming request filename can&#8217;t be found then this loads<br />
a &#8220;custom<em>404.html&#8221; page.  Note that there is no [R] flag, so this<br />
is a silent redirect, not a hard redirect.  The user&#8217;s Location Bar<br />
will not change, but the contents of the page will be<br />
&#8220;custom</em>404.html&#8221;.  Short and simple.</p>
<h3 id="safety_first">Safety First</h3>
<p>If you have mod_rewrite snippets that you use often and want to easily<br />
distribute to other servers or environments you may want to be careful. As<br />
was mentioned, any invalid directive in a .htaccess file will likely cause<br />
internal server errors. So if an environment you move the snippet to doesn&#8217;t<br />
have mod_rewrite you could temporarily break it.</p>
<p>One solution to this problem is the &#8220;check&#8221; for the mod_rewrite module. This<br />
is possible with any module.  Just wrap your mod_rewrite code in an<br />
<code>&lt;IfModule&gt;</code> block and you&#8217;ll be all set:</p>
<pre name="code" class="html">&lt;IfModule mod_rewrite.c&gt;

  # Turn on
  RewriteEngine on

  # Always remove www (with a hard redirect)
  RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
  RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]

  # Generic 404 for anyplace on the site
  # ...

&lt;/IfModule&gt;
</pre>
<h3 id="conclusion">Conclusion</h3>
<p>I hope that this tutorial proves that mod_rewrite isn&#8217;t all that scary, and in<br />
fact its quirks and speed bumps can be avoided with careful development<br />
practices.</p>
<ul class="webroundup">
<li>Follow us on <a href="http://www.twitter.com/nettuts">Twitter</a>, or subscribe to the <a href="http://feeds.feedburner.com/nettuts" title="Nettuts+ RSS Feed">Nettuts+ RSS Feed</a> for more daily web development tuts and articles.</li>
</ul>
<p>
<script type="text/javascript"><!--digg_url = "post permalink (not digg url)"; // -->
</script><br />
<script src="http://digg.com/tools/diggthis.js" type="text/javascript"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/other/a-deeper-look-at-mod_rewrite-for-apache/feed/</wfw:commentRss>
		<slash:comments>62</slash:comments>
		</item>
		<item>
		<title>Search Engine Optimization 101</title>
		<link>http://net.tutsplus.com/tutorials/other/search-engine-optimization-101/</link>
		<comments>http://net.tutsplus.com/tutorials/other/search-engine-optimization-101/#comments</comments>
		<pubDate>Fri, 11 Sep 2009 16:44:05 +0000</pubDate>
		<dc:creator>Siddharth</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[search engine optimization]]></category>
		<category><![CDATA[seo]]></category>

		<guid isPermaLink="false">http://net.tutsplus.com/?p=6679</guid>
		<description><![CDATA[<img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/200x200.jpg" alt="Search Engine Optimization 101" />]]></description>
			<content:encoded><![CDATA[<p>Your website may be top notch but what&#8217;s the use of an online presence if no one can find it? In this quick start guide to search engine optimization we&#8217;ll review an assortment of tactics to increase your page ranking.</p>
<p><span id="more-6679"></span></p>
<h3>A word from the Author</h3>
<blockquote>
<p>Before we start looking at these techniques, just know and understand this: don&#8217;t expect overwhelming changes to occur over night. Getting higher ranks on search engines through SEO is a meticulous process and takes times to obtain positive results. Don&#8217;t be too hasty and more importantly, don&#8217;t resort to black hat SEO techniques. It may give you almost instant results but in the long term, the search engine is probably going to flag and blacklist you. You don&#8217;t want that. Take it slow, be earnest and wait for the results.</p>
</blockquote>
<h3>What is SEO?</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/seo.jpg" border="0" /></div>
<p><strong>S</strong>earch <strong>E</strong>ngine <strong>O</strong>ptimization is the process of increasing the number of visitors by achieving a high position within search results when relevant keywords are searched for. It is common knowledge that people rarely look passed the second or third page of the search results. Optimally you&#8217;ll want a first page position or even the first result in the first page. However, to accomplish this, you&#8217;ll need to optimize and code accordingly. </p>
<h3>Choose the Right Keywords</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/kw.jpg" border="0" /></div>
<p>Choosing the right keywords can be painless or extremely tricky depending upon the scenario. You&#8217;d want to avoid the generic ones since it is going to be extremely difficult to optimize for them. Try to pick keywords that are just as specific as they need to be. For example if you are a freelancer based in Melbourne, your optimal keywords would be <em>freelancer Melbourne</em> or <em>web development services Melbourne</em>. Going for the generic <em>freelancer</em> or <em>web development</em> keywords isn&#8217;t going to do you any good.</p>
<p>Research your keywords. Know which ones are probably going to be searched for most and go from there. </p>
<h3>Focus on the Content</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/content.jpg" border="0" /></div>
<p>Content always comes first. It doesn&#8217;t matter if you perform some dark voodoo to get your site the top place in the results. You&#8217;ll still need solid content to back that up since the visitors are going to be leaving pretty quickly if they don&#8217;t find what they are looking for.</p>
<p>Having good, relevant content is the most important aspect of SEO. Your content needs to be suitably useful for the people who you&#8217;d want to find your site. You need the content to make sense to the reader. The content needs to appeal to people and make them come back for more. </p>
<p>Having original content is very important. Don&#8217;t expect to just copy-paste some text from another site, throw in some keywords and call it a day. You need lots and lots of original content with the keywords in the content itself. If people searching for jQuery come to your page, they expect something related to jQuery to be found on your page. Throw in relevant keywords within the content of the page. But don&#8217;t just spam them sporadically like with tweeting. Your keywords need to be in the appropriate position and of appropriate density. Throw too much keywords around in the content and you are going to be flagged for spam.</p>
<p>Just as important as having original content is having regularly updated content. Fresh content will bring in people and bots alike which in turn will let you get your site indexed with much more frequency which will in turn return fresher results to the search results. But don&#8217;t update just for the sake of updating. Bots have little incentive to come back if all the updates you perform are only marginally incremental. Just try to have something fresh for the visitors and you should be alright.</p>
<h3>Get a Proper Domain Name</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/domain.jpg" border="0" /></div>
<p>This is a hard to obtain part. If at all possible, get a domain name with the keywords in the domain name itself. www.webdevelopmentaustralia.com is going to have a lot more weight with search engines than www.somecompany.com. Obtaining a domain with the proper keywords should be difficult though. </p>
<p>Domains with the keyword as part of it do look ugly but keep in mind that keywords in the domain name carry very great weight. </p>
<h3>Create Pretty URLs</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/url.jpg" border="0" /></div>
<p>Using a URL scheme where parameters are passed as a query string through the URL make it difficult for search engine spiders to look through your site. More importantly, when you are passing the session ID as part of the URL you are essentially creating a separate URLs for each session with almost the same content. This is probably going to get you penalized for duplicate content. We&#8217;ll talk about that later on. </p>
<p>Human readable, bot parsable URLs are generally preferred over traditional parameter filled URLs. <em>www.somecompany.com/games/2009/callofduty6</em> is generally preferred to <em>www.somecompany.com/index.php?cat=game&amp;year=2009&amp;name=callofduty6</em>. When crafting pretty URLs try to avoid days, months and years.<em> www.somecompany.com/blog/seobasics</em> is preferred to <em>www.somecompany.com/blog/2009/09/09/seobasics</em></p>
<h3>Dish out Relevant Page Titles</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/title.jpg" border="0" /></div>
<p>The text within the <em>title</em> tags: the text that is displayed on your browser&#8217;s title bar is amongst the most important elements of a page. Actually I&#8217;d venture so far as to say it&#8217;s the most important part of your page after the actual content itself. </p>
<p>Make sure the title is unique for each page and contains relevant keywords. With regards to the title&#8217;s structure itself <em>Page Title -&gt; Site Name</em> is vastly preferred to <em>Site Name -&gt; Page Title</em>. There are no reasons for you to feel the title needs to be as terse as possible but on the other hand don&#8217;t try to make it too long. 60 characters is the accepted limit.</p>
<p>Also whilst using keywords in your title text, please don&#8217;t try to spin it too much. If the search bot sees too many keywords, you are going to be flagged for spam. Remember, the title text is what appears on the search engine result page. You need to convey as much information as possible without sounding too spammy.</p>
<h3>Tweak the Meta Elements</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/meta.jpg" border="0" /></div>
<p>The meta elements used to matter eons ago when search engine bots were less sophisticated and relied on the meta description and keyword attributes to help them. When this was taken advantage of by spammers, search bots started giving less importance to meta elements.</p>
<p>Having said that, it doesn&#8217;t hurt to include the meta description element. This is the text used in the description of your site. Try to limit yourselves to 200 characters, keep it simple, grammatically correct and include relevant keywords. Keep the descriptions unique for each page.</p>
<h3>Optimize the Page Structure</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/page.jpg" border="0" /></div>
<p>Layouts vary. Positions of your sidebar or navigation vary too. But with respect to the core markup itself, it&#8217;s best to put your main content as close to the body tag as possible. If your other elements have to be placed before the content, use CSS to position it before the content instead of moving the markup itself before the content. </p>
<p>Footers are wonderful places to link to other content on your site. Don&#8217;t just ignore your footer. Place links to recent posts or popular posts in the footer. Having said that, try to not make it look like a link farm. </p>
<h3>Use Appropriate Tags</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/tag.jpg" border="0" /></div>
<p>Use the appropriate tags when developing a site. The heading tags are widely under used. People are instead using generic div tags to encapsulate important information. This is wrong. Strictly looking at the markup alone, the heading tags lets us see the informational hierarchy of the page and this applies for the bots too. Use<em> h1</em> for the title of the post, <em>h2</em> for each section&#8217;s heading and so on. </p>
<p>If you are including some code, use the pre tag. If you think some information is important feel free to make it bold. Bots tend to place value on bolded text just like we immediately see what the bolded text. As always, use it sparingly. You don&#8217;t want to be flagged for spam.</p>
<h3>Craft Proper Links</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/proper.jpg" border="0" /></div>
<p>When creating links, try to stay away from the generic read me text. It&#8217;s not very SEO friendly. Try to include a part of the child link&#8217;s title to the anchor text itself. This is not as hard as it sounds. For example, instead of using <em>read more</em>, use<em> read more about seo</em>. It doesn&#8217;t take that much time to change but yields a lot of SEO benefits.</p>
<p>While linking to page on your site, try to make the anchor text as focused as possible. <em>Portfolio</em> is a better candidate than <em>What I&#8217;ve Done</em>. The latter sounds more catchy but the former represents better SEO. </p>
<h3>Link Internally</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/linkstructure.jpg" border="0" /><br />Courtesy of Opera</div>
<p>Don&#8217;t be scared to interlink the pages in your site. If the number of pages is small, putting it all up on the navigation bar is the way to go. If yours is a big site with a ton of pages, just put all the main category pages on the navigation bar. One way or the other, make sure your pages can be found through links on your site. </p>
<p>Thinking outside the box, you could just as easily include a popular post section on each page. This way you get the interlinking SEO needs and at the same time your visitors can get to see some of the popular posts on your site. It&#8217;s a win-win situation. </p>
<h3>Make your site Accessible</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/accessible.png" border="0" /></div>
<p>Remember, search engines are meant to bring people to your site. Which means your site is primarily for human parsing. Design with them in mind. </p>
<p>Include alt attributes for all images on your site. This is not only good practice but also a necessity if you want valid markup. If it&#8217;s appropriate include relevant keywords in the alt text. Remember, search bots can&#8217;t really look at a picture and decide whether it&#8217;s relevant or not. Appropriate keywords lets it make that decision. As always don&#8217;t go overboard on the text. Keep it simple and to the point.</p>
<p>Please don&#8217;t hide your content behind obnoxious JavaScript or Flash. Spiders can&#8217;t go through those to get to your content. And without content, the entire point of your site fails. Miserably. Avoid this unless you absolutely have to.</p>
<h3>Avoid Duplicate Content</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/duplicate.jpg" border="0" /></div>
<p>Google is very strict about duplicate content and severely penalizes sites which do so. This is regardless of whether the content is on different domains. If the same, exact content appears on different pages, the page last indexed is going to be penalized.</p>
<p>This is mostly common sense: don&#8217;t have the same content on each page. The footer text can be repeated with no penalties but not if your footer text is big enough to qualify as an article.</p>
<p>Also, your site may dish out alternative print capable pages which might be seen by the search engine as duplicate content. In this case, use robotx.txt to disallow indexing on these pages.</p>
<h3>Use robots.txt</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/robots.jpg" border="0" /></div>
<p>Create a robots.txt file to allow/disallow spiders from certain parts of your site. You just create a file named <em>robots.txt</em> and place it at the root of your web site and all co-operating spiders will respect the rules you&#8217;ve mentioned in the file. </p>
<p>You can do everything from disallowing all bots from accessing a specific folder to disallowing bots from a specific search engine. Read up more about it <a href="http://www.robotstxt.org/">here</a>. </p>
<h3>Create a Site Map</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/sitemap.jpg" border="0" /><br />Courtesy of Opera</div>
<p>A site map lets the search engine know about the existence of pages it might not have discovered through spidering through your site normally. Ideally, you should create a normal HTML site map for your users and an XML site map for the search bots. If at all possible, link both.</p>
<h3>Avoid Frames</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/frames.gif" border="0" /></div>
<p>I can&#8217;t say this enough: frames are bad. Both from a web developer perspective and a seo perspective. Content inside frames are virtually invisible to search engines. </p>
<p>More disturbingly, even if one frame of the page gets indexed and is returned as result the result would take you to just the frame without all of its supporting frames inside the parent document. Frames cause undue confusion to people and virtually stop spiders from crawling through your site. Unless you absolutely have to, don&#8217;t use frames. </p>
<h3>Reduce Code Bloat</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/bloat.jpg" border="0" /></div>
<p>And by this I mean 2 things: </p>
<p>Move your JavaScript and CSS to their own separate files. Spiders have no business with them and it is best practice to remove them from the core markup. Create separate files and include them later.</p>
<p>No presentational markup. This is not only SEO friendly but also best practice. Your HTML markup is no place to define how the content should look and similarly the bots have no reason to know how your site is programmed to look. Format the document to your heart&#8217;s content in your CSS and leave the markup pristine and clean.</p>
<h3>Avoid using a Flash Only Navigation</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/flash.jpg" border="0" /></div>
<p>This is common sense but a lot of designers and developers tend to overlook this. Bots can&#8217;t crawl through flash based content and if the only navigation is flash based, the bot has nothing to crawl through. </p>
<p>If your entire site is flash based, it makes sense to create a text only version for spiders and bots to crawl through and find your content. It&#8217;ll take extra time to create that but without a text version to fall back on  your site will be virtually invisible to search engines.</p>
<h3>Use a Common Domain Naming Scheme</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/naming.jpg" border="0" /></div>
<p>Decide on a common naming scheme and stick to it. Personally I prefer www.somename.com but others may like http://somename.com. Decide on a format and stick to it. Use URLs of this format while linking other pages on your site.</p>
<p>Also decide on a whether trailing slashes are required or not. Search engines considers www.somename.com/seo and www.somename.com/seo/ to be different URLs and there is a possibility you are going to be penalized for duplicate content. To get around this, modify your .htaccess file to redirect to the format you like with a 301 redirect. This tells the bot that the page has been moved permanently.</p>
<h3>Submit your Site</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/submit.jpg" border="0" /></div>
<p>If your site is newly hatched and hasn&#8217;t been indexed yet, it&#8217;s a good idea to get the ball rolling by submitting it to search engines and inspiration galleries. This not only let the search engines get to your site early but also brings in a ton of new traffic and back links. </p>
<p>Do not resort to link submitters unless you absolutely trust it. A lot of these submit your links to a number of link farms, an activity which might get you penalized. Just stick to the big search engines and galleries.</p>
<h3>Check for Broken Links</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/broken.jpg" border="0" /></div>
<p>Nothing stops spiders dead in their tracks quicker than broken links specially in the home page. Check thoroughly for broken links to ensure the bots have something to start crawling through your site.</p>
<p>Create a proper 404 page in case the search engine leads the visitor to an old URL. Include appropriate links in the error page. </p>
<h3>Get Linked by Peer Sites</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/link.jpg" border="0" /></div>
<p>This is the massive step that is going to take you a lot of time to get right. Ideally, you&#8217;d want a lot of sites linking to your site and your posts . Each link to your site is considered as a vote to your site by the linking site. Getting inbound links from sites catering to the same user base is extremely vital since the current way of ranking relies on the fact  that if a lot of sites link back to you then the site must contain relevant information.</p>
<p>Unfortunately, this is a long, arduous and never ending task and only one thing can assure you this: good content. Provide good content and sites will automatically start linking to your content. The more sites link to you, the higher your rank is going to be. </p>
<p>Do not resort to illegal means to get back links. This includes link farms and so. Doing anything like this is going to get you kicked out pretty quickly. Accepted means of getting back links includes reciprocal linking where a site places a link to another site in exchange for that site linking back to the original site. </p>
<p>The way I prefer is to write for Net Tuts. Each article I write nets me a back link and Net Tuts being as large as it is, these contribute heavily to my rankings. Plus it brings in a ton of interested new visitors. <img src='http://net.tutsplus.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>Use Appropriate Tools</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/tools.jpg" border="0" /></div>
<p>Tools like Google Analytics helps you analyze and track a number of data including from where your traffic comes from, which pages visitors look at, how much time they spend at each page, how many pages and so on. Use this data to fine tune your site. </p>
<p>Don&#8217;t forget Google WebMaster tools. It lets you look at  the search queries which bring visitors to your page, whether the spider encountered any error while trying to crawl through your site, which sites link to you and more. Invaluable when you are trying to optimize.</p>
<h3>Avoid Black Hat Techniques</h3>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/432_seoTips/images/blackhat.JPG" border="0" /></div>
<p>I can&#8217;t say this enough: don&#8217;t try to cheat. Sooner or later, most probably sooner than you think, you are going to be caught and kicked out with no chance of getting listed again. This includes legit sounding techniques like link farms or cross linking to keyword stuffing and keyword dilution. </p>
<p>Just don&#8217;t do it. </p>
<h3>Wait for the Results</h3>
<p>At this point, you&#8217;ve hopefully done everything right. The only thing you need to do is sit back, generate some quality content and wait for the rankings to increase. Be patient, this doesn&#8217;t happen over night but it definitely happens once you have the basics nailed down.</p>
<h3>Continue Learning</h3>
<p>These are of course only the tip of the huge iceberg that is search engine optimization. Here are some links to get you started:</p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Search_engine_optimization">WikiPedia</a></li>
<li><a href="http://www.google.com/support/webmasters/bin/answer.py?hl=en&#038;answer=35769">Google guidelines</a></li>
<li><a href="http://help.yahoo.com/l/us/yahoo/search/basics/basics-18.html">Yahoo guidelines</a></li>
<li><a href="http://help.live.com/help.aspx?mkt=en-us&#038;project=wl_webmasters&#038;querytype=&#038;query=&#038;tmt=&#038;domain=help.live.com&#038;format=b1">Bing guidelines</a></li>
</ul>
<ul class="webroundup">
<li>Follow us on <a href="http://www.twitter.com/nettuts">Twitter</a>, or subscribe to the <a href="http://feeds.feedburner.com/nettuts" title="Nettuts+ RSS Feed">Nettuts+ RSS Feed</a> for more daily web development tuts and articles.</li>
</ul>
<p>
<script type="text/javascript"><!--digg_url = "post permalink (not digg url)"; // -->
</script><br />
<script src="http://digg.com/tools/diggthis.js" type="text/javascript"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/other/search-engine-optimization-101/feed/</wfw:commentRss>
		<slash:comments>135</slash:comments>
		</item>
		<item>
		<title>8 Regular Expressions You Should Know</title>
		<link>http://net.tutsplus.com/tutorials/other/8-regular-expressions-you-should-know/</link>
		<comments>http://net.tutsplus.com/tutorials/other/8-regular-expressions-you-should-know/#comments</comments>
		<pubDate>Mon, 10 Aug 2009 15:55:29 +0000</pubDate>
		<dc:creator>Vasili</dc:creator>
				<category><![CDATA[Other]]></category>

		<guid isPermaLink="false">http://net.tutsplus.com/?p=6149</guid>
		<description><![CDATA[<img src="http://nettuts.s3.amazonaws.com/404_regularExpressions/images/200x200.jpg" alt="8 Regular Expressions You Should Know" />]]></description>
			<content:encoded><![CDATA[<p>Regular expressions are a language of their own. When you learn a new programming language, they&#8217;re this little sub-language that makes no sense at first glance. Many times you have to read another tutorial, article, or book just to understand the &#8220;simple&#8221; pattern described. Today, we&#8217;ll review eight regular expressions that you should know for your next coding project.<span id="more-6149"></span>
</p>
<p><!--more--></p>
<h2>Background Info on Regular Expressions</h2>
<p>This is what Wikipedia has to say about them:</p>
<blockquote><p>In computing, regular expressions provide a concise and flexible means for identifying strings of text of interest, such as particular characters, words, or patterns of characters. Regular expressions (abbreviated as regex or regexp, with plural forms regexes, regexps, or regexen) are written in a formal language that can be interpreted by a regular expression processor, a program that either serves as a parser generator or examines text and identifies parts that match the provided specification.</p>
</blockquote>
<p>
Now, that doesn&#8217;t really tell me much about the actual patterns. The regexes I&#8217;ll be going over today contains characters such as \w, \s, \1, and many others that represent something totally different from what they look like.
</p>
<p>
If you&#8217;d like to learn a little about regular expressions before you continue reading this article, I&#8217;d suggest watching the <a href="http://www.multiurl.com/ga/regexdummies">Regular Expressions for Dummies</a> screencast series.
</p>
<p>
The eight regular expressions we&#8217;ll be going over today will allow you to match a(n): username, password, email, hex value (like #fff or #000), <a href="http://en.wikipedia.org/wiki/Slug_%28typesetting%29">slug</a>, URL, IP address, and an HTML tag. As the list goes down, the regular expressions get more and more confusing. The pictures for each regex in the beginning are easy to follow, but the last four are more easily understood by reading the explanation.
</p>
<p>
The key thing to remember about regular expressions is that they are almost read forwards and backwards at the same time. This sentence will make more sense when we talk about matching HTML tags.
</p>
<p>
<em>Note:</em> The delimiters used in the regular expressions are forward slashes, &#8220;/&#8221;. Each pattern begins and ends with a delimiter. If a forward slash appears in a regex, we must escape it with a backslash: &#8220;\/&#8221;.
</p>
<h2>Matching a Username</h2>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/404_regularExpressions/images/username.jpg" alt="Matching a username" /></div>
<h4>Pattern:</h4>
<pre name="code" class="html">/^[a-z0-9_-]{3,16}$/</pre>
<h4>Description:</h4>
<p> We begin by telling the parser to find the beginning of the string (^), followed by any lowercase letter (a-z), number (0-9), an underscore, or a hyphen. Next, {3,16} makes sure that are at least 3 of those characters, but no more than 16. Finally, we want the end of the string ($).</p>
<h4>String that matches:</h4>
<p>my-us3r_n4m3</p>
<h4>String that doesn&#8217;t match:</h4>
<p>th1s1s-wayt00_l0ngt0beausername (too long)</p>
<h2>Matching a Password</h2>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/404_regularExpressions/images/password.jpg" alt="Matching a password" /></div>
<h4>Pattern:</h4>
<pre name="code" class="html">/^[a-z0-9_-]{6,18}$/</pre>
<h4>Description:</h4>
<p> Matching a password is very similar to matching a username. The only difference is that instead of 3 to 16 letters, numbers, underscores, or hyphens, we want 6 to 18 of them ({6,18}).</p>
<h4>String that matches:</h4>
<p> myp4ssw0rd</p>
<h4>String that doesn&#8217;t match:</h4>
<p>mypa$$w0rd (contains a dollar sign)</p>
<h2>Matching a Hex Value</h2>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/404_regularExpressions/images/hex-copy.jpg" alt="Matching a hex valud" /></div>
<h4>Pattern:</h4>
<pre name="code" class="html">/^#?([a-f0-9]{6}|[a-f0-9]{3})$/</pre>
<h4>Description:</h4>
<p>We begin by telling the parser to find the beginning of the string (^). Next, a number sign is optional because it is followed a question mark. The question mark tells the parser that the preceding character &mdash; in this case a number sign &mdash; is optional, but to be &#8220;greedy&#8221; and capture it if it&#8217;s there. Next, inside the first group (first group of parentheses), we can have two different situations. The first is any lowercase letter between a and f or a number six times. The vertical bar tells us that we can also have three lowercase letters between a and f or numbers instead. Finally, we want the end of the string ($).
</p>
<p>
The reason that I put the six character before is that parser will capture a hex value like #ffffff. If I had reversed it so that the three characters came first, the parser would only pick up #fff and not the other three f&#8217;s.
</p>
<h4>String that matches:</h4>
<p>#a3c113</p>
<h4>String that doesn&#8217;t match:</h4>
<p>#4d82h4 (contains the letter h)</p>
<h2>Matching a Slug</h2>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/404_regularExpressions/images/slug.jpg" alt="Matching a slug" /></div>
<h4>Pattern:</h4>
<pre name="code" class="html">/^[a-z0-9-]+$/</pre>
<h4>Description:</h4>
<p>You will be using this regex if you ever have to work with mod_rewrite and pretty URL&#8217;s. We begin by telling the parser to find the beginning of the string (^), followed by one or more (the plus sign) letters, numbers, or hyphens. Finally, we want the end of the string ($). </p>
<h4>String that matches:</h4>
<p> my-title-here</p>
<h4>String that doesn&#8217;t match:</h4>
<p>my_title_here (contains underscores)</p>
<h2>Matching an Email</h2>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/404_regularExpressions/images/email.jpg" alt="Matching an email" /></div>
<h4>Pattern:</h4>
<pre name="code" class="html">/^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/</pre>
<h4>Description:</h4>
<p>We begin by telling the parser to find the beginning of the string (^). Inside the first group, we match one or more lowercase letters, numbers, underscores, dots, or hyphens. I have escaped the dot because a non-escaped dot means any character. Directly after that, there must be an at sign. Next is the domain name which must be: one or more lowercase letters, numbers, underscores, dots, or hyphens. Then another (escaped) dot, with the extension being two to six letters or dots. I have 2 to 6 because of the country specific TLD&#8217;s (.ny.us or .co.uk). Finally, we want the end of the string ($).
</p>
<h4>String that matches:</h4>
<p> john@doe.com</p>
<h4>String that doesn&#8217;t match:</h4>
<p>john@doe.something (TLD is too long)</p>
<h2>Matching a URL</h2>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/404_regularExpressions/images/url.jpg" alt="Matching a url" /></div>
<h4>Pattern:</h4>
<pre name="code" class="html">/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/</pre>
<h4>Description:</h4>
<p>This regex is almost like taking the ending part of the above regex, slapping it between &#8220;http://&#8221; and some file structure at the end. It sounds a lot simpler than it really is. To start off, we search for the beginning of the line with the caret.</p>
<p>
The first capturing group is all option. It allows the URL to begin with &#8220;http://&#8221;, &#8220;https://&#8221;, or neither of them. I have a question mark after the s to allow URL&#8217;s that have http or https. In order to make this entire group optional, I just added a question mark to the end of it.
</p>
<p>
Next is the domain name: one or more numbers, letters, dots, or hypens followed by another dot then two to six letters or dots. The following section is the optional files and directories. Inside the group, we want to match any number of forward slashes, letters, numbers, underscores, spaces, dots, or hyphens. Then we say that this group can be matched as many times as we want. Pretty much this allows multiple directories to be matched along with a file at the end. I have used the star instead of the question mark because the star says zero <strong>or more</strong>, not zero <strong>or one</strong>. If a question mark was to be used there, only one file/directory would be able to be matched.
</p>
<p>
Then a trailing slash is matched, but it can be optional. Finally we end with the end of the line.
</p>
<h4>String that matches:</h4>
<p> http://net.tutsplus.com/about</p>
<h4>String that doesn&#8217;t match:</h4>
<p> http://google.com/some/file!.html (contains an exclamation point)</p>
<h2>Matching an IP Address</h2>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/404_regularExpressions/images/ip.jpg" alt="Matching an IP address" /></div>
<h4>Pattern:</h4>
<pre name="code" class="html">/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/</pre>
<h4>Description:</h4>
<p>Now, I&#8217;m not going to lie, I didn&#8217;t write this regex; I got it from <a href="http://www.regular-expressions.info/regexbuddy/ipaccurate.html">here</a>. Now, that doesn&#8217;t mean that I can&#8217;t rip it apart character for character.</p>
<p>
The first capture group really isn&#8217;t a captured group because
<pre name="code" class="html">?:</pre>
<p> was placed inside which tells the parser to not capture this group (more on this in the last regex). We also want this non-captured group to be repeated three times &mdash; the {3} at the end of the group. This group contains another group, a subgroup, and a literal dot. The parser looks for a match in the subgroup then a dot to move on.
</p>
<p>
The subgroup is also another non-capture group. It&#8217;s just a bunch of character sets (things inside brackets): the string &#8220;25&#8243; followed by a number between 0 and 5; or the string &#8220;2&#8243; and a number between 0 and 4 and any number; or an optional zero or one followed by two numbers, with the second being optional.
</p>
<p>
After we match three of those, it&#8217;s onto the next non-capturing group. This one wants: the string &#8220;25&#8243; followed by a number between 0 and 5; or the string &#8220;2&#8243; with a number between 0 and 4 and another number at the end; or an optional zero or one followed by two numbers, with the second being optional.
</p>
<p>
We end this confusing regex with the end of the string.
</p>
<h4>String that matches:</h4>
<p>73.60.124.136 (no, that is not my IP address <img src='http://net.tutsplus.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> )</p>
<h4>String that doesn&#8217;t match:</h4>
<p>256.60.124.136 (the first group must be &#8220;25&#8243; and a number between zero and <strong>five</strong>)</p>
<h2>Matching an HTML Tag</h2>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/404_regularExpressions/images/htmltag.jpg" alt="Matching an HTML tag" /></div>
<h4>Pattern:</h4>
<pre name="code" class="html">/^&lt;([a-z]+)([^&lt;]+)*(?:&gt;(.*)&lt;\/\1&gt;|\s+\/&gt;)$/</pre>
<h4>Description:</h4>
<p>One of the more useful regexes on the list. It matches any HTML tag with the content inside. As usually, we begin with the start of the line. </p>
<p>
First comes the tag&#8217;s name. It must be one or more letters long. This is the first capture group, it comes in handy when we have to grab the closing tag. The next thing are the tag&#8217;s attributes. This is any character but a greater than sign (&gt;). Since this is optional, but I want to match more than one character, the star is used. The plus sign makes up the attribute and value, and the star says as many attributes as you want.
</p>
<p>
Next comes the third non-capture group. Inside, it will contain either a greater than sign, some content, and a closing tag; or some spaces, a forward slash, and a greater than sign. The first option looks for a greater than sign followed by any number of characters, and the closing tag. \1 is used which represents the content that was captured in the first capturing group. In this case it was the tag&#8217;s name. Now, if that couldn&#8217;t be matched we want to look for a self closing tag (like an img, br, or hr tag). This needs to have one or more spaces followed by &#8220;/&gt;&#8221;.
</p>
<p>
The regex is ended with the end of the line.
</p>
<h4>String that matches:</h4>
<p> &lt;a href=&#8221;http://net.tutsplus.com/&#8221;&gt;Nettuts+&lt;/a&gt;</p>
<h4>String that doesn&#8217;t match:</h4>
<p>&lt;img src=&#8221;img.jpg&#8221; alt=&#8221;My image&gt;&#8221; /&gt; (attributes can&#8217;t contain greater than signs)</p>
<h2>Conclusion</h2>
<p>
I hope that you have grasped the ideas behind regular expressions a little bit better. Hopefully you&#8217;ll be using these regexes in future projects! Many times you won&#8217;t need to decipher a regex character by character, but sometimes if you do this it helps you learn. Just remember, don&#8217;t be afraid of regular expressions, they might not seem it, but they make your life a lot easier. Just try and pull out a tag&#8217;s name from a string without regular expressions! <img src='http://net.tutsplus.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />
</p>
<ul class="webroundup">
<li>Follow us on <a href="http://www.twitter.com/nettuts">Twitter</a>, or subscribe to the <a href="http://feeds.feedburner.com/nettuts" title="NETTUTS RSS Feed">NETTUTS RSS Feed</a> for more daily web development tuts and articles.</li>
</ul>
<p>
<script type="text/javascript"><!--digg_url = "post permalink (not digg url)"; // -->
</script><br />
<script src="http://digg.com/tools/diggthis.js" type="text/javascript"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/other/8-regular-expressions-you-should-know/feed/</wfw:commentRss>
		<slash:comments>158</slash:comments>
		</item>
		<item>
		<title>Using htaccess Files for Pretty URLS</title>
		<link>http://net.tutsplus.com/tutorials/other/using-htaccess-files-for-pretty-urls/</link>
		<comments>http://net.tutsplus.com/tutorials/other/using-htaccess-files-for-pretty-urls/#comments</comments>
		<pubDate>Fri, 31 Jul 2009 17:07:02 +0000</pubDate>
		<dc:creator>Noah Hendrix</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[modrewrite]]></category>

		<guid isPermaLink="false">http://net.tutsplus.com/?p=6049</guid>
		<description><![CDATA[<img src="http://nettuts.s3.amazonaws.com/396_htAccess2/images/200x200.jpg" alt="Using HTACCESS for Pretty URLS" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://net.tutsplus.com/tutorials/other/5-fun-and-practical-htaccess-solutions/">Continuing</a> our review of htaccess files, today we&#8217;ll examine how to use mod_rewrite to create pretty URLs.<span id="more-6049"></span>
</p>
<p><!--more--></p>
<h3>Benefits of Formatted URLs</h3>
<p>
  While some claim pretty URLs help in search engine rankings, the debate here is fierce, we can all agree that pretty URLs make things easier for our users and adds a level of professionalism and polish to any web application. I could go over all the theoretical reasons for this, but I like real-world examples better. Like it or hate it we all must admit that <a href="http://twitter.com">Twitter</a> is a wildly popular web application and part of the reason for that is most certainly how it formats URLs. I can tell anyone in the know that my Twitter username is noahhendrix, and they know my profile can easily be found at <a href="http://twitter.com/noahhendrix">twitter.com/noahhendrix</a>. This seemingly simple concept has vast effects in the popularity of your application.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/396_htAccess2/images/1.png" border="0" /></div>
<p>
  Just to put things in perspective we can look at another popular social networking website, <a href="http://facebook.com">Facebook</a>. Since the site launched in 2004 the profile system has grown and evolved to better tailor to users, but one glaring hole was the URL to a profile. From the time I registered with Facebook my profile was at the URL <a href="http://www.facebook.com/profile.php?id=1304880680">http://www.facebook.com/profile.php?id=1304880680</a>. That is quite a mouth full, and just recently it appears Facebook has <a href="http://blog.facebook.com/blog.php?post=90316352130">realized that</a> and they launched Facebook vanity URLs. Now I can share my Facebook profile by telling people my Facebook username is &#8220;noahhendrix&#8221;, which they know can be found by going to <a href="http://facebook.com/noahhendrix">facebook.com/noahhendrix</a>. While the odds are that we won&#8217;t have an application as popular as Facebook, we can still borrow a few pages from their book.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/396_htAccess2/images/2.png" border="0" /></div>
<h3>Quick Overview</h3>
<p>
  A quick overview before we dive into code, in today&#8217;s tutorial we will go over two slightly different methods of creating pretty URLs using HTACCESS. The difference between the methods is whether Apache or PHP is doing the heavy lifting to break the URL apart for parsing. I want to point out that mod_rewrite tutorials are almost as old as the internet itself and  <a href="http://www.roscripts.com/Pretty_URLs_-_a_guide_to_URL_rewriting-168.html">this</a> <a href="http://www.sourcerally.net/regin/12-Make-pretty-URLs-with-PHP-and-mod_rewrite">is</a> <a href="http://corz.org/serv/tricks/htaccess2.php">not</a> <a href="http://roshanbh.com.np/2008/03/url-rewriting-examples-htaccess.html">the</a> <a href="http://web-programming.suite101.com/article.cfm/url_rewriting_via_htaccess">first</a>. At the end I will use one of the methods to create a simple application to show how these solutions would look in a real-live website (well not 100% production quality). The service we will create is a URL shortener that can mirrors the functionality of such sites like <a href="http://bit.ly">bit.ly</a>, <a href="http://tinyurl.com">TinyURL</a>, or <a href="http://su.pr">su.pr</a>. So without anymore fluff let us look at the code.
</p>
<h3>Using Apache</h3>
<p>
  First, we can place all of our code in Apache .htaccess files. This could look something like this:
</p>
<pre name="code" class="php">
  Options +FollowSymLinks
  RewriteEngine On

  RewriteCond %{SCRIPT_FILENAME} !-d
  RewriteCond %{SCRIPT_FILENAME} !-f

  RewriteRule ^users/(\d+)*$ ./profile.php?id=$1
  RewriteRule ^threads/(\d+)*$ ./thread.php?id=$1

  RewriteRule ^search/(.*)$ ./search.php?query=$1
</pre>
<p>
  Let&#8217;s start at the top and work our way down to better understand what is going on here. The first line sets the environment up to follow symbolic links using the <a href="http://httpd.apache.org/docs/1.3/mod/core.html#options">Options directive</a>. This may or may not be necessary, but some web hosts use symlinks (similar to alias in MacOSX or shortcuts is Windows) for common HTTP request errors and these are usually symlinked files, or at least this is how I understand the reasoning. Next we tell Apache we are going to use the <a href="http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html">Rewrite Engine</a>. The next two lines are very, very important it restricts rewriting URLs only to paths that do not actually exists. This prevents the rules below from matching <strong>example.com/images/logo.png</strong> for example. The first prevents existing directories with the <strong>!-d</strong> flag and the second with <strong>!-f</strong> means ignore existing files.
</p>
<p>
  The next three lines are the actual URL rewriting commands. Each line creates a rule that tries to match a regular expressions pattern against the incoming URL. Regular expressions, at least for me, are a hard set of rules to remember but I always find it helpful to use <a href="http://blog.themeforest.net/screencasts/regular-expressions-for-dummies/">this tutorial</a> by Nettut&#8217;s own Jeffery Way and <a href="http://gskinner.com/RegExr/">the tool</a> he recommends. I found it easy to type in sample URLs we want to match and then try to hack together the pattern.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/396_htAccess2/images/3.png" border="0" /></div>
<p>
  The first argument is the pattern, between the caret and dollar sign. We tell Apache we want URLs asking for the users directory (an artificial directory, doesn&#8217;t have to actually exist) followed by a / and any length of numbers. The parenthesis create a capture group, you can use as many of these as you want, they serve as variables that we can then transplant into our rewrite. The asterisk means the user can enter whatever they want, and it won&#8217;t affect the rewrite, this is primarily to handle a trailing slash so <strong>example.com/users/123</strong> is the same as <strong>example.com/users/123/</strong> as users would expect.
</p>
<p>
  The second argument is the path we want to actually call, this unlike the first must be a real file. We tell Apache to look in the current directory for a file called <strong>profile.php</strong> and send the parameter <strong>id=$1</strong> along with it. Remember the capture group earlier? That is where we get the variable $1, capture groups start at one. This creates a URL on the server like <strong>example.com/profile.php?id=123</strong>.
</p>
<p>
  This method is great for legacy web applications that have existing URL structures that prevent us from easily rewriting the backend to understand a new URL schema because to the server the URL looks the same, but to the user it looks much nicer.
</p>
<h3>Using PHP</h3>
<p>
  This next method is great for those who don&#8217;t want to distribute too much logic to Apache and feel more comfortable in PHP (or similar scripting languages). The concept here is capture any URL the server receives and push it to a PHP controller page. This comes with the added benefit of control, but greater complexity at the same time. Your HTACCESS file might look something like this:
</p>
<pre name="code" class="php">
  Options +FollowSymLinks
  RewriteEngine On

  RewriteCond %{SCRIPT_FILENAME} !-d
  RewriteCond %{SCRIPT_FILENAME} !-f

  RewriteRule ^.*$ ./index.php
</pre>
<p>
  Everything is the same as above, except the last line so we will skip to it. Instead of creating a capture group we just tell Apache to grab every URL and redirect it to <strong>index.php</strong>. What this means is we can do all of our URL handling in PHP without relying too much on stringent URL paths in HTACCESS. Here is what we might do at the top of our index.php file to parse out the URL:
</p>
<pre name="code" class="php">
  &lt;?php
    #remove the directory path we don't want
    $request  = str_replace("/envato/pretty/php/", "", $_SERVER['REQUEST_URI']);

    #split the path by '/'
    $params     = split("/", $request);
  ?&gt;
</pre>
<p>
  The first line is not necessary unless you application doesn&#8217;t live at the root directory, like my demos. I am removing the non-sense part of the URL that I don&#8217;t want PHP to worry about. <strong>$_SERVER['REQUEST_URI']</strong> is a global server variable that PHP provides and stores the request URL, it generally looks like this:
</p>
<pre name="code" class="html">
  /envato/pretty/php/users/query
</pre>
<p>
  As you can see it is basically everything after the domain name. Next we split up the remaining part of the virtual path and <a href="http://us3.php.net/split">split</a> it by the <strong>/</strong> character this allows us to grab individual variables. In my example I just printed the <strong>$params</strong> array out in the body, of course you will want to do something a little more useful.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/396_htAccess2/images/4.png" border="0" /></div>
<p>
  One thing you might do is take the first element of the <strong>$params</strong> array and include a file by that same name and within in the file you can use the second element in the array to execute some code. This might look something like this:
</p>
<pre name="code" class="php">
	 &lt;?php
	   #keeps users from requesting any file they want
	   $safe_pages = array("users", "search", "thread");

	   if(in_array($params[0], $safe_pages)) {
	     include($params[0].".php");
	   } else {
	     include("404.php");
	   }
	 ?&gt;
</pre>
<blockquote>
<p>
  WARNING: The first part of this code is unbelievably important! You absolutely must restrict what pages a user can get so they don&#8217;t have the opportunity to print out any page they wish by guessing at file names, like a database configuration file. </p>
</blockquote>
<p>Now that we have the soapbox out of the way let&#8217;s move on. Next we check if the requested file is in the <strong>$safe_pages</strong> array, and if it is we include otherwise will include a 404 not found page. In the included page you will see that you have access to the <strong>$params</strong> array and you can grab whatever data from it that is necessary in your application.
</p>
<p>
  This is great for those who want a little more control and flexibility. It obviously requires quite a bit extra code, so probably better for new projects that won&#8217;t require a lot of code to be updated to fit the new URL formats.
</p>
<h3>A Simple URL Shortner</h3>
<p>
  This last part of the tutorial is going to let us put some use to the code we went over above, and is more or less a &#8220;real-life&#8221; example. We are going to create a service called <strong>shrtr</strong>, I made up this name so any other products with this name are not associated with the code I am posting below. <strong>Note</strong>: I know this is by far not an original concept, and is only meant for demonstration of <strong>mod_rewrite</strong>. First let&#8217;s take a look at the database:
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/396_htAccess2/images/5.png" border="0" /></div>
<p>
  As you can see this is very straightforward, we have only 4 columns:
</p>
<ul>
<li><strong>id</strong>: unique identifier used to reference specific rows</li>
<li><strong>short</strong>: unique string of characters appended to the end of our URL to determine where to redirect</li>
<li><strong>url</strong>: the URL that the short url redirects to</li>
<li><strong>created_at</strong>: a simple timestamp so we know when this URL was created</li>
</ul>
<h3>The Basics</h3>
<p>
  Next, let&#8217;s go over the six files we need to create for this application:
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/396_htAccess2/images/8.png" border="0" /></div>
<ul>
<li>.htaccess: redirects all short urls to serve.php</li>
<li>create.php: validates URL, creates shortcode, saves to DB</li>
<li>css/style.css: holds some basic styling information</li>
<li>db_config.php: store variables for database connections</li>
<li>index.php: The face of our application with form for entering URL</li>
<li>serve.php: looks up short URL and redirects to actual URL</li>
</ul>
<p>
  That is all we need for our basic example. I will not cover <strong>index.php</strong> or <strong>css/style.css</strong> in very great detail because they are have no PHP, and are static files.
</p>
<pre name="code" class="html">
# index.php
----
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;
    &lt;title&gt;Makes URLs Shrtr&lt;/title&gt;
    &lt;link type="text/css" rel="stylesheet" href="./css/style.css" /&gt;
	&lt;/head&gt;
	&lt;body&gt;
	 &lt;div id="pagewrap"&gt;
  	 &lt;h1&gt;shrt&lt;span class="r"&gt;r&lt;/span&gt;.me&lt;/h1&gt;

  	 &lt;div class="body"&gt;
  	   &lt;form action="./create.php" method="post"&gt;

  	     &lt;span class="instructions"&gt;Type your URL here&lt;/span&gt;
  	     &lt;input name="url" type="text" /&gt;
  	     &lt;input type="submit" value="shrtr" /&gt;

  	   &lt;/form&gt;
  	 &lt;/div&gt;

	 &lt;/div&gt;
	&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>
  The only real interesting to note here is that we submit the form with a field called URL to <strong>create.php</strong>.
</p>
<pre name="code" class="css">
# css/style.css
----
/* reset */
* {
  font-family: Helvetica, sans-serif;
  margin: 0;
  padding: 0;
}

/* site */
html, body { background-color: #008AB8; }
a { color: darkblue; text-decoration: none;}

  #pagewrap {
    margin: 0 auto;
    width: 405px;
  }

    h1 {
      color: white;
      margin: 0;
      text-align: center;
      font-size: 100px;
    }
      h1 .r { color: darkblue; }

    .body {
      -moz-border-radius: 10px;
      -webkit-border-radius: 10px;
      background-color: white;
      text-align: center;
      padding: 50px;
      height: 80px;
      position: relative;
    }

      .body .instructions {
        display: block;
        margin-bottom: 10px;
      }
      .body .back {
        right: 15px;
        top: 10px;
        position: absolute;
      }

      .body input[type=text] {
        display: block;
        font-size: 20px;
        margin-bottom: 5px;
        text-align: center;
        padding: 5px;
        height: 20px;
        width: 300px;
      }
</pre>
<p>
  That is all very generic, but makes our application a little more presentable.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/396_htAccess2/images/6.png" border="0" /></div>
<p>
  The last basic file we need to look at is our <strong>db_config.php</strong>, I created this to abstract some of the database connection information.
</p>
<pre name="code" class="php">
# db_config.php
----
&lt;?php

  $database = "DATABASE_NAME";
  $username = "USERNAME";
  $password = "PASSWORD";
  $host     = "localhost";

?&gt;
</pre>
<p>
  You need to replace the values with what works in your database, and host is probably <strong>localhost</strong>, but you need to double check with your hosting provider to make sure. Here is the SQL dump of the table, <strong>url_redirects</strong> that holds all the information we showed above:
</p>
<pre name="code" class="php">
--
-- Table structure for table `url_redirects`
--

CREATE TABLE IF NOT EXISTS `url_redirects` (
  `id` int(11) NOT NULL auto_increment,
  `short` varchar(10) NOT NULL,
  `url` varchar(255) NOT NULL,
  `created_at` timestamp NOT NULL default CURRENT_TIMESTAMP,
  PRIMARY KEY  (`id`),
  KEY `short` (`short`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
</pre>
<h3>Creating the Short URL</h3>
<p>
  Next lets look at the code necessary to create our short URL.
</p>
<pre name="code" class="php">
# create.php
----
&lt;?php
  require("./db_config.php");

  $url = $_REQUEST['url'];

  if(!preg_match("/^[a-zA-Z]+[:\/\/]+[A-Za-z0-9\-_]+\\.+[A-Za-z0-9\.\/%&#038;=\?\-_]+$/i", $url)) {
    $html = "Error: invalid URL";
  } else {

    $db = mysql_connect($host, $username, $password);

      $short = substr(md5(time().$url), 0, 5);

      if(mysql_query("INSERT INTO `".$database."`.`url_redirects` (`short`, `url`) VALUES ('".$short."', '".$url."');", $db)) {
        $html = "Your short URL is&lt;br /&gt;shrtr.me/".$short;
      } else {
        $html = "Error: cannot find database";
      }

    mysql_close($db);
  }
?&gt;

&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;
    &lt;title&gt;Makes URLs Shrtr&lt;/title&gt;
    &lt;link type="text/css" rel="stylesheet" href="./css/style.css" /&gt;
	&lt;/head&gt;
	&lt;body&gt;
	 &lt;div id="pagewrap"&gt;
  	 &lt;h1&gt;shrt&lt;span class="r"&gt;r&lt;/span&gt;.me&lt;/h1&gt;

  	 &lt;div class="body"&gt;
  	   &lt;?= $html ?&gt;
  	   &lt;br /&gt;&lt;br /&gt;
  	   &lt;span class="back"&gt;&lt;a href="./"&gt;X&lt;/a&gt;&lt;/span&gt;
  	 &lt;/div&gt;

	 &lt;/div&gt;
	&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>
  Now we are getting a bit more complex! First we need to include the database connection variables we created earlier, then we store the URL parameter sent to us by the create form in a variable called <strong>$url</strong>. Next we do some regular expressions magic to check if they actually sent a URL, if not we store an error. If the user entered a valid URL we create a connection to the database using the connection variables we include at the top of page. Next we generate a random 5 character string to save to the database, using the <a href="http://us2.php.net/substr">substr</a> function. The string we split up is the md5 hash of the current <a href="http://us2.php.net/time">time()</a> and <strong>$url</strong> concatenated together. Then we insert that value into the <strong>url_redirects</strong> table along with the actual URL, and store a string to present to the user. If it fails to insert the data we store an error. If you move down into the HTML part of the page all we do is print out the value of <strong>$html</strong>, be it error or success. This obviously isn&#8217;t the most elegant solution but it works!
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/396_htAccess2/images/7.png" border="0" /></div>
<h3>Serving the Short URL</h3>
<p>
  So we have the URL in the database let&#8217;s work on <strong>serve.php</strong> so we can actually translate the short code into a redirect.
</p>
<pre name="code" class="php">
&lt;?php
  require("./db_config.php");

  $short = $_REQUEST['short'];

  $db = mysql_connect($host, $username, $password);
    $query = mysql_query("SELECT * FROM `".$database."`.`url_redirects` WHERE `short`='".mysql_escape_string($short)."' LIMIT 1", $db);
    $row = mysql_fetch_row($query);

    if(!empty($row)) {
      Header("HTTP/1.1 301 Moved Permanently");
      header("Location: ".$row[2]."");
    } else {
      $html = "Error: cannot find short URL";
    }

  mysql_close($db);
?&gt;

&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;
    &lt;title&gt;Makes URLs Shrtr&lt;/title&gt;
    &lt;link type="text/css" rel="stylesheet" href="./css/style.css" /&gt;
	&lt;/head&gt;
	&lt;body&gt;
	 &lt;div id="pagewrap"&gt;
  	 &lt;h1&gt;shrt&lt;span class="r"&gt;r&lt;/span&gt;.me&lt;/h1&gt;

  	 &lt;div class="body"&gt;
  	   &lt;?= $html ?&gt;
  	   &lt;br /&gt;&lt;br /&gt;
  	   &lt;span class="back"&gt;&lt;a href="./"&gt;X&lt;/a&gt;&lt;/span&gt;
  	 &lt;/div&gt;

	 &lt;/div&gt;
	&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>
  This one is very similar to <strong>create.php</strong> we include the database information, and store the short code sent to us in a variable called <strong>$short</strong>.  Next we query the database for the URL of that short code. If we get a result we redirect to the URL, if not we print out an error like before.
</p>
<p>
  As far as PHP goes that is all we need to do, but at the moment to share a short URL users must enter this, <strong>http://shrtr.me/server.php?short=SHORT_CODE</strong> not very pretty is it? Let&#8217;s see if we can&#8217;t incorporate some mod_rewrite code to make this nicer.
</p>
<h3>Pretty-ify With HTACCESS</h3>
<p>
  Of the two methods I wrote about at the beginning of the tutorial we will use the Apache one because this application is already created without considering any URL parsing. The code will look something like this:
</p>
<pre name="code" class="html">
  Options +FollowSymLinks
  RewriteEngine On

  RewriteCond %{SCRIPT_FILENAME} !-d
  RewriteCond %{SCRIPT_FILENAME} !-f

  RewriteRule ^(\w+)$ ./serve.php?short=$1
</pre>
<p>
  Skipping to the RewriteRule we are directing any traffic that doesn&#8217;t already have a real file or directory to <strong>serve.php</strong> and putting the extension in the GET variable short. Not to bad no go try it out for yourself!
</p>
<h3>Conclusion</h3>
<p>
  Today we learned a few different ways to utilize mod_rewrite in our application to make our URLs pretty.  As always I will be watching over the comments if anybody has trouble, or you can contact me on <a href="http://twitter.com/noahhendrix">twitter</a>. Thanks for reading!
</p>
<ul class="webroundup">
<li>Follow us on <a href="http://www.twitter.com/nettuts">Twitter</a>, or subscribe to the <a href="http://feeds.feedburner.com/nettuts" title="NETTUTS RSS Feed">NETTUTS RSS Feed</a> for more daily web development tuts and articles.</li>
</ul>
<p>
<script type="text/javascript"><!--digg_url = "post permalink (not digg url)"; // -->
</script><br />
<script src="http://digg.com/tools/diggthis.js" type="text/javascript"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/other/using-htaccess-files-for-pretty-urls/feed/</wfw:commentRss>
		<slash:comments>77</slash:comments>
		</item>
		<item>
		<title>5 Fun and Practical Htaccess Solutions</title>
		<link>http://net.tutsplus.com/tutorials/other/5-fun-and-practical-htaccess-solutions/</link>
		<comments>http://net.tutsplus.com/tutorials/other/5-fun-and-practical-htaccess-solutions/#comments</comments>
		<pubDate>Fri, 17 Jul 2009 16:00:22 +0000</pubDate>
		<dc:creator>Noah Hendrix</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[ht access]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[htaccess files]]></category>

		<guid isPermaLink="false">http://net.tutsplus.com/?p=5852</guid>
		<description><![CDATA[<img src="http://nettuts.s3.amazonaws.com/384_htaccess/200x200.jpg" alt="5 Fun and Practical Htaccess Solutions" />]]></description>
			<content:encoded><![CDATA[<p>Today we will go over some practical uses of htaccess files that you can use in your web applications.<span id="more-5852"></span>
</p>
<p><!--more--></p>
<h3>Requirements</h3>
<p>
  <a href="http://httpd.apache.org/docs/1.3/howto/htaccess.html">Htaccess</a> files are plain-text configuration files used by the <a href="http://httpd.apache.org/">Apache</a> HTTP web server. They allow users to set directory level options without requiring access to the <strong>httpd.conf</strong> file. As such it is required that your server uses Apache, and a web host that allows <strong>htaccess</strong> files (the most popular hosts do).
</p>
<p>
  I assume a basic working knowledge of htaccess, but if you need to freshen up check out <a href="The Ultimate Guide to .htaccess Files">this article</a> by <a href="http://net.tutsplus.com/author/josephpecoraro/">Joseph Pecoraro</a>
</p>
<h3>1. Prevent Hotlinking</h3>
<p>
  <a href="http://en.wikipedia.org/wiki/Inline_linking">Hotlinking</a>, or inline linking, is when one web site links directly to an object on another site. This costs the hosting site bandwidth to provide the image on the page of the second site. On popular photo sites this can be a major problem, albeit <a href="http://www.shapelessmass.com/index.html/?p=578">humorous</a> at times.</p>
<div class="tutorial_image">
<a href="http://www.shapelessmass.com/index.html/?p=578"><br />
<img src="http://nettuts.s3.amazonaws.com/384_htaccess/sued.gif" alt="ShapelessMass.com" /><br />
</a></p>
<div><em><a href="http://www.shapelessmass.com">http://www.shapelessmass.com</a></em></div>
</div>
<p> There are ways to fix this growing problem using htaccess. First here is the image we are trying to protect.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/384_htaccess/./images/1.png" border="0" /></div>
<pre name="code" class="php">
  RewriteEngine on
  RewriteCond %{HTTP_REFERER} !^$

  #domains that can link to images
  #add as many as you want
    RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?demo.collegeaintcheap.com [NC]
    # RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?noahhendrix.com [NC]

  #show no image when hotlinked
    RewriteRule \.(jpg|png|gif)$ - [NC,F,L]
</pre>
<p>
  We will step through this line-by-line.</p>
<ol>
<li>First we need to turn on the <a href="http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html">rewrite engine</a> in Apache, this allows us to redirect the user&#8217;s request. </li>
<li>Next we start setting our conditions using <a href="http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html#RewriteCond">RewriteCond</a>. This is a function that takes two arguments: <strong>TestString</strong> and <strong>CondPattern</strong>. TestString is the string we want to check our CondPattern against (using regular expressions). <strong>${HTTP_REFERER}</strong> is a variable provided by Apache that holds the domain the request came from, in this instance we want to allow requests from blank HTTP referrers to protect users who are on a proxy server that sends blank referrers. </li>
<li>Next we set the domains from which we will allow our images to be linked using the same syntax except now we provide a URL. The <strong>[NC]</strong> flag at the end of the command simply instructs the engine to ignore casing. You can add as many lines domains as you&#8217;d like here, using the same syntax. For the sake of example I added my personal domain, but commented it out. </li>
<li>Finally, the last line is the <a href="http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html#RewriteRule">RewriteRule</a> we wish to use if any of the conditions above are not met. It takes two arguments as well <strong>Pattern</strong> and <strong>Substitution</strong>, where pattern is a regular expression match and substitution is what we want to replace any matches with. In this case we are looking for requests that end in jpg, png, and gif; if found we want to use a blank substitution. However in the flags we tell it furthermore what we want to be done, <strong>NC</strong> means no case, <strong>F</strong> sends a 403 forbidden error to user, and <strong>L</strong> tells the engine to stop rewriting so no other rules are applied. </li>
</ol>
<p>
  This is fairly straightforward, but perhaps we are interested in telling the user we don&#8217;t want them to hotlink our images, so let&#8217;s redirect all hotlinked requests to an image instead of sending a 403 forbidden error. This is done by replacing the last line with this code.
</p>
<pre name="code" class="php">
  #show an alternate image
    RewriteRule \.(jpg|png|gif)$ http://demo.collegeaintcheap.com/envato/htaccess/hotlink/images/hotlink.jpeg [NC,R,L]
</pre>
<p>
  You can change url to any image path you&#8217;d like on your domain, but remember it needs to not end in jpg, png, or gif as it will reapply the rule and send the server into a never-ending loop. I chose to use the older .jpeg extension to fix this. The <strong>R</strong> flag that replaced <strong>F</strong> simply sends a redirect.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/384_htaccess/./images/2.png" border="0" /></div>
<h3>2. Block User By IP Address</h3>
<p>
  This is a great little tip if you have a spammer on your website. If you can find their IP in your logs, simply add it to an htaccess file.
</p>
<pre name="code" class="php">
  Order Deny,Allow
  Deny from 24.121.202.23
  # Deny from 0.0.0.0
</pre>
<p>
  Using the <a href="http://httpd.apache.org/docs/1.3/mod/mod_access.html#order">Order</a> directive in the <a href="http://httpd.apache.org/docs/1.3/mod/mod_access.html">mod_access</a> module we can specify IPs to deny and allow. Simply using the syntax <strong>Deny from IP ADDRESS</strong> we can forbid those users from accessing our directory.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/384_htaccess/./images/3.png" border="0" /></div>
<h3>3. Error Documents</h3>
<p>
  All production ready sites should use custom error pages for a professional touch. This is easy using the <a href="http://httpd.apache.org/docs/1.3/mod/core.html#errordocument">ErrorDocument</a> directive in Apache&#8217;s core. A custom page is far better than the default Apache error pages.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/384_htaccess/./images/4.png" border="0" /></div>
<pre name="code" class="php">
  ErrorDocument 404 http://demo.collegeaintcheap.com/envato/htaccess/errors/404.html
  ErrorDocument 403 http://demo.collegeaintcheap.com/envato/htaccess/errors/403.html
  ErrorDocument 500 http://demo.collegeaintcheap.com/envato/htaccess/errors/500.html
</pre>
<p>
  ErrorDocument takes two arguments <strong>error-code</strong> and <strong>document</strong>. In the code above I created error documents for the 3 most common HTTP errors: 404 not found, 403 forbidden, and 500 server error. Then you can provide the full URL or relative path to your error documents. You could also them redirect to a PHP script that logs the errors in a database or emails them to you (might get annoying though). This is a great way to take control of errors in your web application, be sure to check out <a href="http://www.smashingmagazine.com/">Smashing Magazine&#8217;s</a> 404 error page <a href="http://www.smashingmagazine.com/2009/01/29/404-error-pages-one-more-time/">showcase</a> for inspiration.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/384_htaccess/./images/5.png" border="0" /></div>
<h3>4. Redirect While Performing Upgrades</h3>
<p>
  If you are performing a major site upgrade you most likely should redirect users to a page informing them. This prevents users from seeing broken pages or potential security holes while the application is uploading. One caveat to consider is that we want to allow certain IP addresses into the site for testing before it goes live all of this can be achieved in an htaccess file.
</p>
<pre name="code" class="php">
  RewriteEngine on
  RewriteCond %{REQUEST_URI} !/upgrade.html$
  RewriteCond %{REMOTE_HOST} !^24\.121\.202\.30
  RewriteRule $ http://demo.collegeaintcheap.com/envato/htaccess/upgrade/upgrade.html [R=302,L]
</pre>
<p>
  We are using the <a href="http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html">rewrite engine</a> again to do this, but in a kind of reverse way. First we need to set a condition that excludes the document describing the upgrade otherwise our server start a never ending loop. Next we exclude a single IP address from being redirected for testing purposes. Finally we use the rewrite rule to send users to an upgrade page. The flags we have looked at before, except this time we setting the redirect to a 302 status code, telling the browser that the page has temporarily moved and to handle caching accordingly. Smashing Magazine, again, has a great showcase of <a href="http://www.smashingmagazine.com/2009/06/12/effective-maintenance-pages-examples-and-best-practices/">Effective Maintenance Pages</a>.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/384_htaccess/./images/6.png" border="0" /></div>
<h3>5. Hiding Directory Listing</h3>
<p>
  For numerous security reasons it is a good idea to restrict directory listing, the default behavior in Apache. This can be done with a simple line in our htaccess file we can prevent visitors from seeing our directory listings.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/384_htaccess/./images/7.png" border="0" /></div>
<pre name="code" class="php">
  Options -Indexes
</pre>
<p>
  Now users who request a directory that doesn&#8217;t have an index file it will show them a 403 forbidden error page.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/384_htaccess/./images/8.png" border="0" /></div>
<h3>Conclusion</h3>
<p>
  These are several of my favorite uses of htaccess. Leave yours in the comments! I am available for help in the comments or on <a href="http://twitter.com">twitter</a>. If there is a great deal of interest, I will do more htaccess tutorials with solutions to your requests in the comments. Thanks for reading!
</p>
<ul class="webroundup">
<li>Follow us on <a href="http://www.twitter.com/nettuts">Twitter</a>, or subscribe to the <a href="http://feeds.feedburner.com/nettuts" title="NETTUTS RSS Feed">NETTUTS RSS Feed</a> for more daily web development tuts and articles.</li>
</ul>
<p>
<script type="text/javascript"><!--digg_url = "post permalink (not digg url)"; // -->
</script><br />
<script src="http://digg.com/tools/diggthis.js" type="text/javascript"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/other/5-fun-and-practical-htaccess-solutions/feed/</wfw:commentRss>
		<slash:comments>92</slash:comments>
		</item>
		<item>
		<title>Authenticating Users With Facebook Connect and Google Friend Connect</title>
		<link>http://net.tutsplus.com/tutorials/other/authenticating-users-with-facebook-connect-and-google-friend-connect/</link>
		<comments>http://net.tutsplus.com/tutorials/other/authenticating-users-with-facebook-connect-and-google-friend-connect/#comments</comments>
		<pubDate>Wed, 08 Jul 2009 07:29:17 +0000</pubDate>
		<dc:creator>Noah Hendrix</dc:creator>
				<category><![CDATA[Other]]></category>

		<guid isPermaLink="false">http://net.tutsplus.com/?p=5731</guid>
		<description><![CDATA[<img src="http://nettuts.s3.amazonaws.com/375_facebookConnect/200x200.jpg" alt="Authenticating Users With Facebook Connect and Google Friend Connect" />]]></description>
			<content:encoded><![CDATA[<p>Most social networks have API tools that allow almost any website to authenticate users through their system. In today&#8217;s tutorial, we will learn how to use these tools. Using a simple comment model, users will learn how to leave a comment within their Facebook or Google profiles. </p>
<p><span id="more-5731"></span></p>
<div class="tutorial_image">
<a href="http://nettuts.s3.amazonaws.com/375_facebookConnect/Code.zip"><img src="http://nettuts.com/wp-content/themes/nettuts/site_images/button_src_nm.jpg"></a>
</div>
<h3>The Application</h3>
<p>
  Briefly, I will go over the demo application. I have a very simple, static HTML page that shows a photo and allows the user to comment on it. In a real application you would probably save the comments to a database, but for the sake of demonstration I just save them to a text file with each line representing a new comment. This code isn&#8217;t particularly important until you get to the add comment form.
</p>
<pre name="code" class="html">
# index.php
...
&lt;div class="new-comment"&gt;
  &lt;h2 class="sub-title"&gt;Add A Comment&lt;/h2&gt;

  &lt;form action="php/savecomment.php" id="comment-form" method="post"&gt;
    &lt;div id="userbox" style="display:none;"&gt;&lt;/div&gt;

    &lt;div id="userinfo"&gt;

      Name: &lt;input id="name" name="name" type="text" /&gt;
      &lt;input id="url" name="url" type="hidden" /&gt;
      &lt;input id="image" name="image" type="hidden" /&gt;

    &lt;/div&gt;

    &lt;div class="comment"&gt;
      Comment:&lt;br /&gt;
      &lt;textarea id="comment" name="comment"&gt;&lt;/textarea&gt;
    &lt;/div&gt;
    &lt;input type="submit" value="Send Comment" /&gt;
  &lt;/form&gt;

&lt;/div&gt;
...
</pre>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/375_facebookConnect/./images/4.png" border="0" /></div>
<p>
  Here you see we have a basic form with four fields: name, url, image, and comment. I chose to hide the url and image fields because this is data we will get from Facebook and Google Friend Connect. The form is submitted to a PHP file, <strong>savecomment.php</strong>, which I won&#8217;t go over but is included in the download. In essence it takes all the post data and stores in an existing comments data file with pipe, &#8220;|&#8221;, characters separating each field. Again, not a practical technique but sufficient for our purposes. A little above the form we list out all the comments in that file by including another PHP script, <strong>readcomments.php</strong>.
</p>
<pre name="code" class="html">
# index.php
...
&lt;div class="comments"&gt;
  &lt;h2 class="sub-title"&gt;Comments&lt;/h2&gt;

  &lt;?php include("php/readcomments.php"); ?&gt;
&lt;/div&gt;
...
</pre>
<p>
  One last piece of code we need to look at is the JavaScript includes. All of our authentication is done on the client side, so I created <strong>application.js</strong> to hold the code responsible for that, and to save myself from writing too much JavaScript I included jQuery (via Google).
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/375_facebookConnect/./images/5.png" border="0" /></div>
<pre name="code" class="html">
# index.php
---
&lt;head&gt;
...
  &lt;script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"&gt;&lt;/script&gt;
  &lt;script src="./js/application.js" type="text/javascript"&gt;&lt;/script&gt;
&lt;/head&gt;
</pre>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/375_facebookConnect/./images/6.png" border="0" /></div>
<h3>Updating The Page to Show User&#8217;s Information.</h3>
<p>
  After creating this we can move into the <strong>application.js</strong> file mentioned earlier. I decided that it would be best to create a function for each service that wrapped all the logic required in authentication. Then, after creating these for both services I extracted out common code to keep the code concise. After creating the file declare a function called <strong>update_userbox()</strong>
</p>
<pre name="code" class="js">
# application.js
---
//Generic updates #userbox with info retrieved
//from services
function update_userbox(name, image, url, logout) {

  //populate the data in #userbox and show it
  $('#userbox').html( "&lt;a href='"+url+"'&gt;"
                    + "&lt;img alt='"+name+"' src='"+image+"' /&gt;"
                    + "Logged in as " + name + "&lt;/a&gt; "
                    + "(&lt;a href='./index.php' onclick='" + logout + "'&gt;logout&lt;/a&gt;)" ).show();

  //hide name input and service
  //login buttons
  $('#userinfo').hide();

  //populate the values of the inputs
  //using data from service
  $('#name').val(name);
  $('#url').val(url);
  $('#image').val(image);

}
</pre>
<p>
  This function is generic and can be used with either service, and as more spring up could probably be used in others as well. The purpose of this is to insert HTML into an empty div called <strong>#userbox</strong> so the user has a visual understanding that they logged into a service. This is done by hiding the name box, and showing a profile image from the remote service along with their name and a logout link to disconnect from the service. Also behind the scenes we fill in the name, url, and image inputs so they are submitted to the server along with the comment for saving to our database file. You can see this is done by passing in four variables:
</p>
<ul>
<li>name: the user&#8217;s name they provided to the service</li>
<li>image: a url to the user&#8217;s profile image</li>
<li>url: a url to the user&#8217;s profile on the service</li>
<li>logout: a string of JS code to execute when logout is pressed</li>
</ul>
<p>
  These are all pretty straightforward, except the logout variable. This can be explained when you look at the APIs that FB and GFC offer. Each has function that will notify the service that the user wishes to be logged out, this is how I chose to pass that function call into the logout link.
</p>
<h3>Facebook Connect &#8211; Getting Your API Key</h3>
<p>
  We will start with <a href="http://developers.facebook.com/connect.php">Facebook Connect</a>. The first thing we will need to do is <a href="http://www.facebook.com/developers/createapp.php">create an application</a> on Facebook&#8217;s Developers site. It seems a bit odd at first that we have to create a Facebook application for this, but as far as I can tell it is only to receive the API key and to register your URLs with their developer program.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/375_facebookConnect/./images/2.png" border="0" /></div>
<p>
  After you have created the application we need to edit some settings, on the left side of the screen you will see tabs, click on <a href="http://www.facebook.com/developers/editapp.php?app_id=100603521509&#038;view=connect">Connect</a>. Here you need to enter the <strong>Connect URL</strong> which is the URL where the root of your site exists. I also chose to upload a picture, and I recommend all websites do this as it gives you some visual branding.
</p>
<p>
  Alright now you can save these changes and it will take you to the application summary page. Here is where we can find the application API key, so go ahead and copy that on to your clipboard.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/375_facebookConnect/./images/3.png" border="0" /></div>
<h3>Adding A Cross-Domain Receiver</h3>
<p>
  Facebook architected their connect API to work entirely on the client side. This tutorial will require no server side code to authenticate users. This is done through some intricate AJAX techniques where Facebook passes data back and forth via iframes to circumvent the same-origin policy implemented by most browsers. Part of this process requires that we <a href="http://wiki.developers.facebook.com/index.php/Cross-domain_communication_channel">place a file</a> on our server that Facebook can interact with to verify our identity. So at the top-level of your domain create a file called <strong>xd_receiver.html</strong> and insert this code.
</p>
<pre name="code" class="html">
# xd_receiver.html
---
&lt;pre name="code" class="html"&gt;
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;body&gt;
    &lt;script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/XdCommReceiver.js" type="text/javascript"&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
&lt;/pre&gt;
</pre>
<h3>The Facebook Connect Button</h3>
<p>
  Facebook requires us to jump through a few hoops to get everything working, first of which is we need to include a JS file from the Facebook website and run the <a href="http://wiki.developers.facebook.com/index.php/JS_API_M_FB.Facebook.Init">init()</a> function in our <strong>index.php</strong> file at very bottom just above the closing &lt;/body&gt; tag.
</p>
<pre name="code" class="html">
# index.php
---
&lt;!-- Facebook API Includes --&gt;
&lt;script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php" type="text/javascript"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;
  FB.init("FB_API_KEY", "xd_receiver.htm", {"ifUserConnected" : auth_using_fb});
&lt;/script&gt;
</pre>
<p>
  There are a few things we need to look at in this function. First, be sure to replace <strong>FB_API_KEY</strong> with your API key. Next we have a string representing the path to our cross-domain receiver file which should be at the root of your application directory. Finally, we can pass in a hash of options. We want to maintain users&#8217; login state so we tell Facebook to run a function <strong>auth_using_fb</strong> (we will create this in a few moments) if the user is already connected to our site. This means that if the user reloads the page it will still show them as logged in so they don&#8217;t have to re-login on every page.
</p>
<p>
  Next we have to create the actual login button, this requires using <a href="http://wiki.developers.facebook.com/index.php/XFBML">XFBML</a>, Facebook Markup Language which is an extension to HTML. The X denotes code that is inserted on 3rd party websites and not on Facebook&#8217;s website. Somewhere on the page we have to insert the tag <a href="http://wiki.developers.facebook.com/index.php/Fb:login-button">Fb:login-button</a> and a few options.
</p>
<pre name="code" class="html">
  &lt;fb:login-button length="long" onlogin="auth_using_fb();"&gt;&lt;/fb:login-button&gt;
</pre>
<p>
  I chose to put this next to my name textbox so the user could easily see it when they go to add a comment. Notice we have two attributes <strong>length</strong> and <strong>onlogin</strong>. <strong>Length</strong> allows us to specify the text on the button and has two options: short (the default) and long. Short says <strong>Connect</strong> and long says <strong>Connect with Facebook</strong>. <strong>Onlogin</strong> works a lot like <strong>onclick</strong> or <strong>onmouseover</strong> and allows us to execute JS when the user successfully authenticates with our site through Facebook. We call the same function we mentioned earlier, <strong>auth_using_fb()</strong>, but before we can create that we need to make one more change. At the top of the page in the HTML tag we need to tell the browser we are using more than one markup language.
</p>
<pre name="code" class="html">
# index.php
---
&lt;html xmlns="http://www.w3.org/1999/xhtml" xmlns:fb="http://www.facebook.com/2008/fbml"&gt;
</pre>
<p>
  The <a href="http://www.w3schools.com/tags/att_html_xmlns.asp">xmlns</a> attribute specifies the xml namespace for the document. The first is the standard <strong>xhtml</strong>, and the second is the new facebook markup language, this helps make our document W3C compliant.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/375_facebookConnect/./images/7.png" border="0" /></div>
<h3>Writing the Javascript</h3>
<p>
  Now we are going to go back to <strong>application.js</strong> and write the <strong>auth_using_fb()</strong> function.
</p>
<pre name="code" class="js">
# application.js
---
//Facebook Connect
function auth_using_fb() {
  //get the users data from FB
  var viewer  = FB.Facebook.apiClient.fql_query(

      'SELECT name, pic_square_with_logo,profile_url FROM user WHERE uid='+FB.Facebook.apiClient.get_session().uid,

      function(results) {
        update_userbox( results[0].name,
                        results[0].pic_square_with_logo,
                        results[0].profile_url,
                        'FB.Connect.logoutAndRedirect("./index.php");return false;')
      }
  );
}
</pre>
<p>
  This is the function we use to interface with Facebook&#8217;s data, and retrieve users&#8217; data. The login button we created earlier actually has the functionality for signing the user into Facebook built-in, but if want to grab the information about the user we must request it separately. The first line of code in the function is a call to the Facebook API method, <a href="http://wiki.developers.facebook.com/index.php/JS_API_M_FB.ApiClient.Fql_query">fql_query()</a>. This function allows us to use Facebook&#8217;s SQL like query language to fetch the user&#8217;s data. We only need the three columns we discussed earlier: name, picture, and url. The Facebook Developer wiki has <a href="http://wiki.developers.facebook.com/index.php/FQL_Tables">a page</a> containing all the various tables that you can query for information. It is important to add the <strong>WHERE</strong> clause that limits to the currently logged in user. The second parameter of <strong>fql_query</strong> is a callback function that is passed an array of the results. We just need to take the first result in the array and send each property to our <strong>update_userbox()</strong> function along with the logout JS call. It is important to include <strong>&#8220;return false;&#8221;</strong> after the <a href="http://wiki.developers.facebook.com/index.php/JS_API_M_FB.Connect.LogoutAndRedirect">logoutAndRedirect()</a> call because otherwise it causes the page to reload before the API can log out the user.
</p>
<p>
  And amazingly that is all we need to do for Facebook Connect to work, go ahead and try it out!
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/375_facebookConnect/./images/8.png" border="0" /></div>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/375_facebookConnect/./images/9.png" border="0" /></div>
<h3>Google Friend Connect &#8211; API Key</h3>
<p>
  Much like Facebook Connect, Google Friend Connect requires us to <a href="http://www.google.com/friendconnect/admin/site/setup?hl=en_US">sign up</a> for an API Key. This is far quicker than Facebook Connect as they have an easy-to-use wizard that walks you through it all. First you need to provide the application name and URL just like in Facebook Connect.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/375_facebookConnect/./images/10.png" border="0" /></div>
<p>
  Next it instructs you to upload a few files to your server for cross-domain AJAX support, again just like Facebook Connect. Seeing a trend here?
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/375_facebookConnect/./images/11.png" border="0" /></div>
<p>
  The final step will verify that everything is setup properly. Google calls the API Key the Site ID, but it acts the exact same Facebook&#8217;s API key.
</p>
<h3>Including the Necessary Files</h3>
<p>
  Next we need to include the proper JS files at the bottom of our page after the Facebook files. We also need to implement the <a href="http://code.google.com/apis/friendconnect/js_api.html">initOpenSocialApi()</a> method of the Google Friend Connect API. This takes one parameter in the form of a hash of options. The only required option is <strong>site</strong> which is our Site ID we collected earlier.
</p>
<pre name="code" class="js">
# index.php
---
&lt;!-- Google API Includes --&gt;
&lt;script src="http://www.google.com/friendconnect/script/friendconnect.js?v=0.8" type="text/javascript"&gt;&lt;/script&gt;

&lt;!-- Initialize the Google Friend Connect OpenSocial API. --&gt;
&lt;script type="text/javascript"&gt;
  google.friendconnect.container.setParentUrl('/envato/nologin/' /* location of rpc_relay.html and canvas.html */);
  google.friendconnect.container.initOpenSocialApi({
    site: 'GFC_API_KEY',
    onload: function(securityToken) { auth_using_gfc(); }
  });
  google.friendconnect.renderSignInButton({id:"google-login",style:'long'})
&lt;/script&gt;
</pre>
<p>
  We also need to page in a callback function to execute when the user is authenticated with Google Friend Connect. Additionally we have to call a function that renders the sign in button, this is very similar to the XFBML markup we used earlier except Google decided to stick with plain HTML. This function requires we pass it a DOM id of the element we want the signin button to be created in, I made a div just below the FB login button with an id of <strong>google-login</strong>. We also pass in the <strong>style:&#8217;long&#8217;</strong> option so that it is similar to our Facebook button.
</p>
<pre name="code" class="html">
&lt;div class="services"&gt;
  &lt;fb:login-button length="long" onlogin="auth_using_fb();"&gt;&lt;/fb:login-button&gt;
  &lt;div id="google-login"&gt;&lt;/div&gt;
&lt;/div&gt;
</pre>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/375_facebookConnect/./images/12.png" border="0" /></div>
<h3>Writing the JavaScript</h3>
<p>
    Google Friend Connect is similar in many ways to Facebook Connect, which of course makes our job all the easier. One language difference I found is that Google&#8217;s API tends to be a bit more verbose in nature so we will split our explanation of <strong>auth_using_gfc()</strong> into two parts.
</p>
<pre name="code" class="js">
//Google Friend Connect
function auth_using_gfc() {
  //Request GFC to send extra profile data
  var params = {};
      params[opensocial.DataRequest.PeopleRequestFields.PROFILE_DETAILS] =
      [opensocial.Person.Field.URLS];

  // Create a request to grab the current viewer.
  var req = opensocial.newDataRequest();
  req.add(req.newFetchPersonRequest('VIEWER', params), 'viewer_data');
...
</pre>
<p>
  The first thing we do is declare the <strong>params</strong> variable as an empty hash. This will contain the options we need to send with our request to Google, because by default we do not receive the user&#8217;s profile URL. Next we create a request object that will actually make the request to Google for the user&#8217;s profile data. The <strong>add()</strong> method takes two arguments a <strong>newFetchPersonRequest()</strong> object and then a unique string to identify the data. <strong>VIEWER</strong> is a constant representing the currently logged in user.
</p>
<pre name="code" class="js">
// Sent the request
req.send(function(data) {

  // If the view_data had an error, then user is not signed in
  if (!data.get('viewer_data').hadError()) {
    //get the users data from GFC
    var viewer = data.get('viewer_data').getData();

    update_userbox( viewer.getDisplayName(),
                    viewer.getField(opensocial.Person.Field.THUMBNAIL_URL),
                    viewer.getField(opensocial.Person.Field.URLS)[0].getField('address'),
                    'google.friendconnect.requestSignOut()' );
  }

});
</pre>
<p>
  The last part of the function is the actual request for data, using the <strong>send()</strong> method which takes one argument of a callback function. We declare the function inline and we have an if statement that checks weather the request received an error. If it doesn&#8217;t we assume everything went alright and we declare a variable called view that holds the data received from the request. This data is then passed into our <strong>update_userbox()</strong> function. The only thing to note here is the the third argument that passes in the user&#8217;s URL. Google allows users to enter multiple profile URLs (such as Facebook, Twitter, etc.) and we only need the first one which is the Google profile URL. The final argument is our string of JS to execute that signs the user out which also reloads the page.
</p>
<p>
  This is all we need to do, so go ahead and try it out! One really nice thing you&#8217;ll notice is that user&#8217;s don&#8217;t have to have a Google account to login they can also use their AOL/AIM, Yahoo!, Netlog, or Open ID accounts.
</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/375_facebookConnect/./images/13.png" border="0" /></div>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/375_facebookConnect/./images/14.png" border="0" /></div>
<h3>Conclusion</h3>
<p>
  While this specific example is not production ready, hopefully you can see how easy it would be for us to implement this into our existing applications. I encourage everyone to take a good look over the documentation Facebook and Google offer.
</p>
<ul>
<li><a href="http://wiki.developers.facebook.com/index.php/Facebook_Connect">Facebook Connect Documentation</a></li>
<li><a href="http://wiki.developers.facebook.com/index.php/Facebook_Connect_Tutorial1">FBC Tutorial</a></li>
<li><a href="http://developers.facebook.com/tools.php?api">FQL Simulator</a></li>
<li><a href="http://code.google.com/apis/friendconnect/js_api.html">Google Friend Connect Documentation</a></li>
<li><a href="http://code.google.com/apis/friendconnect/code.html">GFC Example Code</a></li>
<li><a href="http://code.google.com/apis/ajax/playground/?exp=friendconnect">GFC Simulator</a></li>
</ul>
<p>
  I hope you enjoyed this tutorial, and if there is enough interest, I will write a follow-up tutorial on how this can be further integrated using PHP on the server-side. As always, if anyone needs help or you can find me on <a href="http://twitter.com">Twitter</a>, <a href="http://twitter.com/noahhendrix">@noahhendrix</a>.
</p>
<ul class="webroundup">
<li>Follow us on <a href="http://www.twitter.com/nettuts">Twitter</a>, or subscribe to the <a href="http://feeds.feedburner.com/nettuts" title="NETTUTS RSS Feed">NETTUTS RSS Feed</a> for more daily web development tuts and articles.</li>
</ul>
<p>
<script type="text/javascript"><!--digg_url = "post permalink (not digg url)"; // -->
</script><br />
<script src="http://digg.com/tools/diggthis.js" type="text/javascript"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/other/authenticating-users-with-facebook-connect-and-google-friend-connect/feed/</wfw:commentRss>
		<slash:comments>52</slash:comments>
		</item>
		<item>
		<title>10 Tips for New iPhone Developers</title>
		<link>http://net.tutsplus.com/tutorials/other/10-tips-for-new-iphone-developers/</link>
		<comments>http://net.tutsplus.com/tutorials/other/10-tips-for-new-iphone-developers/#comments</comments>
		<pubDate>Wed, 01 Jul 2009 15:44:40 +0000</pubDate>
		<dc:creator>Paolo Ranoso</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[mobile development]]></category>

		<guid isPermaLink="false">http://net.tutsplus.com/?p=5625</guid>
		<description><![CDATA[<img src="http://nettuts.s3.amazonaws.com/366_iphone/200x200.jpg" alt="10 Tips for New iPhone WebApp Developers" />]]></description>
			<content:encoded><![CDATA[<p>Making a webapp for the iPhone is a lot like making a normal web site, but with a few quirks to abide by. In this article, I&#8217;ll give you a wide variety of tips, covering things such as: &#8220;must-haves&#8221;, usability guidelines, testing/debugging, pitfalls, and performance issues. I hope you enjoy it!
</p>
<p><span id="more-5625"></span></p>
<h3>WebApps vs. Native Apps</h3>
<p>Keep in mind that a web application runs in the browser, while a native application is installed on the iPhone.<br />
So, if you want to make something like a high-performance, fast-responsive, action-packed game with awesome graphics, then you&#8217;re probably better<br />
off just learning Objective-C and making a native app.  However, if you don&#8217;t own a Mac and/or if you are trying to do something a lot simpler, like<br />
making a mobile version of your website or blog, then making a web app might be the faster and more reasonable road to take.
</p>
<p>Still not convinced?  Here are a list of popular sites that are iPhone web apps/websites:</p>
<ul>
<li><a href="http://iphone.facebook.com">iphone.facebook.com</a></li>
<li><a href="http://m.digg.com">m.digg.com</a></li>
<li><a href="http://hotels.com/iphone">hotels.com/iphone</a></li>
<li><a href="http://iphone.fmylife.com/">iphone.fmylife.com</a></li>
<li><a href="http://iphone.coldwellbanker.com/">iphone.coldwellbanker.com</a></li>
</ul>
<p>
The list goes on&#8230;<br />
If you&#8217;re REALLY smart, you&#8217;ll make BOTH a native app(hopefully free) and web app, like most of the sites above did.
</p>
<h3>1:  Viewport, Viewport, Viewport</h3>
<p>I would say this may be the simplest and most important thing for an iPhone web app.  It&#8217;s just one line of code to include within your head tags:</p>
<pre name="code" class="html">
	&lt;!-- add this in your &lt;head&gt; section with your other meta tags--&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;&quot; /&gt;
</pre>
<p>This tells the browser to scale your page in such a way that will make it fit nicely on the iPhone.  Here&#8217;s what each field means:</p>
<ul>
<li><strong>width=device-width</strong><br />This fits the page to the device&#8217;s width.  The iPhone&#8217;s display is 320&#215;480 pixels in portrait mode, and 480&#215;320 pixels in landscape mode, which is why you sometimes see sites use width=320 instead of width=device-width.</li>
<li><strong>initial-scale=1.0</strong><br />This is the scaling when the page first loads up.</li>
<li><strong>maximum-scale=1.0</strong><br />This is the maximum scaling allowed.</li>
<li><strong>user-scalable=0</strong><br />This determines whether the user is allowed to zoom in and out by pinching/double-tapping.  You can also use user-scalable=no and user-scalable=yes instead of 0 and 1.</li>
</ul>
<p>Keep in mind that the viewport IS NOT A WINDOW.  Think of it like a magnifying glass over a page.  You can move the magnifying glass around and zoom in/out.<br />
This is why certain features like fixed positioning don&#8217;t work on the iPhone(at least at the time of this writing).  In <em>Professional iPhone and iPod touch Programming</em>, Richard Wagner explains what a viewport is:
</p>
<blockquote><p>
A viewport is a rectangular area of screen space within which an application is displayed. Traditional<br />
Windows and Mac desktop applications are contained inside their own windows. Web apps are displayed<br />
inside a browser window. A user can manipulate what is seen inside of the viewport by resizing the<br />
window, scrolling its contents, and in many cases, changing the zoom level.
</p></blockquote>
<p>Specifying the viewport is a <strong><em>*must-have*</em></strong> and is the first step into making your web app iPhone-friendly.</p>
<h3>2:  &quot;Hide&quot; the Address Bar!</h3>
<p>The address bar takes up a considerable portion of the already tiny screen we have to work with.  You&#8217;ll want to hide the address bar to display as much information on the screen as you can, so that the user doesn&#8217;t have to flick down.  Consider the picture below.  Is that the whole screen, or is there more information below?</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/366_iphone/images/withaddressbar.jpg" border="0" alt="With the address bar" /><br/>With the address bar</div>
<p>Now let us hide the address bar by adding this single line of javascript code:</p>
<pre name="code" class="js">
//add this in your javascript code to 'hide' the address bar
window.scrollTo(0, 1);
</pre>
<p>This will &quot;hide&quot; the address bar by scrolling down just enough so that you won&#8217;t see it when loading the page. In our picture below, we see that there was more information to be displayed after all!</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/366_iphone/images/noaddressbar.jpg" border="0" alt="Without the address bar" /><br/>Without the address bar</div>
<p>Notice that this only temporarily hides the address bar by just scrolling down a bit upon loading the page.  Permanently hiding the address bar may not be the best idea, but it is possible.  For safety&#8217;s sake, we&#8217;ll leave that outside of the scope of this article.</p>
<h3>3: Test on iPhone AND Browsers</h3>
<p>Although your ultimate goal is to put your web app on the iPhone, testing it on normal browsers can be beneficial!</p>
<p>Remember, since this is a <strong><em>web</em></strong> application, you can test it like one!  That means useful tools like Firebug, Web Developer, and YSlow still work!</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/366_iphone/images/firebugerror.jpg" border="0" alt="Using Firebug to Test/Debug your iPhone web app" /><br/>&quot;A firebug error!? But that&#8217;s impossible&#8230;my code is <strong><em>always</em></strong> perfect!&quot; </div>
<p>NOTE:  You may get errors for certain pieces of code that are legitimate &#8212; iPhone-specific/webkit-specific code mostly.  With that said, don&#8217;t be too dependent on these tools&#8230;they are more of a guide, not an oracle.</p>
<p>Keep in mind also that Firefox may display things differenty than Safari does, and Safari is also different from Mobile Safari.  You&#8217;ll most certainly notice web apps that you develop in <a href="http://developer.apple.com/tools/dashcode/">Dashcode</a> won&#8217;t display properly on Firefox.<br />
 This is why you still need to test on an iPhone.  If you do however, develop in Dashcode, there are testing/debugging features that come with it.</p>
<h3>4: Mimic a Native App if Possible</h3>
<p>From a usability perspective, making your web app look like a native iPhone app is beneficial because users already know how to use an iPhone application, thus there is a <a href="http://en.wikipedia.org/wiki/Transfer_of_training">positive transfer of knowledge</a>.<br />
Besides that, using the buttons, font, lists, etc is also beneficial.  A lot of time and money was put into researching what would be a good design&#8230;Apple must have hired various usability and design experts.<br />
If you mimic a native app, you won&#8217;t have to go through the whole process of designing and creating something that may in the end prove infeasible.
</p>
<p>Take a look at the picture below&#8230;this is the &quot;Groups&quot; menu from the &quot;Contacts&quot; feature.  Can you guess whether this is the real deal(native app), or a fake(webapp mimic)?</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/366_iphone/images/webapp.jpg" border="0" alt="Is this a native app or web app?" /><br/>Native app or web app?</div>
<p>If you guessed that the above pic is a web app, you are correct!  See how closely you can mimic a native app?</p>
<p>If you do not wish to mimic a native iPhone web app, perhaps because your application doesn&#8217;t fit well that way or because you want to maintain your style, then at least follow some basic guidelines:</p>
<ul>
<li>Be consistent (i.e: navigation buttons on each page)</li>
<li>Make buttons large enough to tap (i.e: for fat fingers or the error-prone)</li>
<li>Make things intuitive (i.e: collapsible boxes should have hint&#8230;like a +/- next to it)</li>
</ul>
<h3>5: Use Frameworks, Libraries, and Tools to Save Time</h3>
<p>If you do decide to mimic a native app, then I suggest not starting from scratch.  There are many things out there that can save you a ton of time:</p>
<ul>
<li><strong><a href="http://developer.apple.com/documentation/AppleApplications/Conceptual/Dashcode_UserGuide/Contents/Resources/en.lproj/MakingaWebApp/MakingaWebApp.html"><br />
Dashcode</a></strong><br/>If you have a Mac, this may be the best route to go if you want to whip up something fast.  Dashcode has a parts library(i.e: buttons/frames), a code snippets library, a workflow steps guide, and way more!</li>
<li><strong><a href="http://code.google.com/p/iui/">iUI</a></strong><br/>Created by <a href="http://www.joehewitt.com/">Joe Hewitt</a>, this nice little framework lets you create web apps with simple HTML!  It has a nice slide-effect too.  Performance is FAST and the framework itself is very tiny filesize-wise.</li>
<li><strong><a href="http://iwebkit.net/">iWebkit</a></strong><br/>Just like iUI, you can create your app with simple HTML.  However, this framework has many <a href="http://demo.iwebkit.net/">features</a> that other frameworks might not have.  It also comes with a user guide which clearly explains how to use the features.<br />
What makes this my favorite framework is that it plays nice with other javascript code, so I can customize my web app and do things like make collapsible boxes</li>
</ul>
<p>There are, of course, many other frameworks, libraries, and tools, but as to date, these are my favorite ones.  Have one that you really like?  Write it in the comments below!</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/366_iphone/images/popupfeature.jpg" border="0" alt="iWebkit popup" /><br/><a href="http://iwebkit.net/">iWebkit</a>&#8217;s pop-up feature</div>
<h3>6: Use Lists When Possible</h3>
<p>Lists are a nice quick n&#8217; dirty way of displaying information.  &quot;Contacts&quot; and &quot;Mail&quot; display information in the form of lists.  Lists allow for easy navigation, let you display a lot of items on the tiny screen, and are easy to touch compared to pictures.<br />
They also load pretty fast since they&#8217;re just text.  Lists will almost always be your navigation method of choice, but then again it really depends on what your web app is.</p>
<p>If you do use a list, grouping items by alphabet, relevance, or usage is always a good way to go.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/366_iphone/images/lists.jpg" border="0" alt="An alphabetical list" /><br/>A list with items grouped by alphabet</div>
<h3>7: Minimize Horizontal Navigation</h3>
<p>If possible, minimize the number of screens your users have to navigate to in order to get the information they want.<br />
Having less pages to jump to means less redirecting and unnecessary loading by going backwards and forewards.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/366_iphone/images/manyscreens.jpg" border="0" alt="Many screens" /><br/>Many navigation screens</div>
<p>In the example picture above, we can possibly eliminate the first two screens by automatically getting the date/time and start out with the third screen.<br />
If a user wants to intentionally pick and different day/time, we can have that in the &quot;Change View&quot; menu.
</p>
<h3>8: Make Your App Small and Fast</h3>
<p>Remember that performance is critical in the mobile world, as a user may be on the EDGE network or just have a slow connection.  Give them as little to download as possible!  Just like normal web sites, the same rules of enhancing performance apply.  Instead of<br />
giving you a checklist of everything, I would just recommend that you get both <a href="http://code.google.com/speed/page-speed/">Page Speed</a> and <a href="http://developer.yahoo.com/yslow/">YSlow</a>, as these<br />
give more detailed checklists on beefing up performance than I could ever give.  </p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/366_iphone/images/iuisize.jpg" border="0" alt="iui filesize" /><br/>Not bad for a framework that has a .js file, a .css file, and a bunch of images, huh?</div>
<h3>9: Have a Homescreen Icon</h3>
<p>Make sure to have a nice icon that people can see when they add your web app to their homescreen.  Make a 57&#215;57 PNG file and add the following code to your home page:</p>
<pre name="code" class="html">
	&lt;!-- add this in your &lt;head&gt; section --&gt;
    &lt;link href=&quot;path/to/your/icon.png&quot; rel=&quot;apple-touch-icon&quot; /&gt;
</pre>
<p>Having an icon is a good way to quickly recognize your web app, as well as look professional while having some nice eye-candy.</p>
<h3>10: iPhone &#8216;Simulators&#8217; aren&#8217;t Perfect</h3>
<p>You will notice that iPhone simulators, even the official &quot;Aspen Simulator&quot;, can sometimes yield different results than on the iPhone.  This is true even when making native apps.  This should actually be somewhat expected since the iPhone OS is different from Mac OS and the iPhone architecture is different from a normal computer.  I want people to know about this, because I&#8217;ve had quite a few friends<br />
develop and test mainly on &quot;simulators&quot; only to find out near final production/deployment that their program on the iPhone was buggy, crashed, or simply just didn&#8217;t work.  Please be careful when using a simulator&#8211;they are here for convenience, NOT for iPhone replacement. Remember that since your ultimate goal is to put something on the iPhone, then test on the iPhone.  Since you are making a web app and not a native app, you won&#8217;t need to worry about paying the developer fee or becoming a registered developer with Apple.</p>
<div class="tutorial_image"><img src="http://nettuts.s3.amazonaws.com/366_iphone/images/sadface.jpg" border="0" alt="simulator FAIL" /><br/>Simulator FAIL</div>
<h3>Conclusion</h3>
<p>I hope you enjoyed this article!  One of the joys of making a web app is you can develop on any platform!  I tried to keep the tips as cross-platform as possible.  However, although this is true, it still might be the best idea to develop on a Mac.</p>
<p>There are many other important tips that I did not mention here, simply because other people have beaten me to the punch!  If you are really serious about iPhone web app development, go out there and learn more!  There are plenty of resources that <a href="http://www.google.com/">your best friend</a><br />
can give you that I would not know about.</p>
<p>Have any tips of your own?  Want to call me out on tips that are nonsense?  Share your knowledge by writing in the comments below!  I love learning new things and I definitely want to be corrected if I am wrong.</p>
<ul class="webroundup">
<li>Please subscribe to the <a href="http://feedproxy.google.com/themeforest" title="ThemeForest RSS Feed">Theme Forest RSS Feed</a>, and follow us on <a href="http://twitter.com/themeforest">Twitter</a>.</li>
</ul>
<p>
<script type="text/javascript"><!--digg_url = "post permalink (not digg url)"; // -->
</script><br />
<script src="http://digg.com/tools/diggthis.js" type="text/javascript"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://net.tutsplus.com/tutorials/other/10-tips-for-new-iphone-developers/feed/</wfw:commentRss>
		<slash:comments>46</slash:comments>
		</item>
	</channel>
</rss>
<!--
This site's performance optimized by W3 Total Cache:

W3 Total Cache improves the user experience of your blog by caching
frequent operations, reducing the weight of various files and providing
transparent content delivery network integration.

Learn more about our WordPress Plugins: http://www.w3-edge.com/wordpress-plugins/

Page Caching using memcached
Database Caching 10/21 queries in 0.011 seconds using memcached
Content Delivery Network via 

Served from: psdtutsplus.com @ 2009-11-21 16:25:31 -->