<?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>actionshrimp.com &#187; admin</title>
	<atom:link href="http://www.actionshrimp.com/tag/admin/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.actionshrimp.com</link>
	<description>fun and geekery</description>
	<lastBuildDate>Thu, 12 May 2011 20:12:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>CakePHP: PagesController with Admin Routing</title>
		<link>http://www.actionshrimp.com/2009/04/cakephp-pagescontroller-with-admin-routing/</link>
		<comments>http://www.actionshrimp.com/2009/04/cakephp-pagescontroller-with-admin-routing/#comments</comments>
		<pubDate>Tue, 07 Apr 2009 17:46:14 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[cake]]></category>
		<category><![CDATA[pagescontroller]]></category>
		<category><![CDATA[routing]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.actionshrimp.com/?p=272</guid>
		<description><![CDATA[For small Cake websites with admin routing enabled, I like to use the Auth component to require a login for all admin routes, and allow access to everything else using the following beforeFilter in the AppController superclass: function beforeFilter(){ $admin = Configure::read(&#039;Routing.admin&#039;); if (isset($this-&#62;params[$admin]) and $this-&#62;params[$admin]){ $this-&#62;layout = &#039;admin&#039;; } else { $this-&#62;Auth-&#62;allow(); } } [...]]]></description>
			<content:encoded><![CDATA[<p>For small Cake websites with admin routing enabled, I like to use the Auth component to require a login for all admin routes, and allow access to everything else using the following beforeFilter in the AppController superclass:</p>
<pre class="brush: php">

function beforeFilter(){
    $admin = Configure::read(&#039;Routing.admin&#039;);
    if (isset($this-&gt;params[$admin]) and $this-&gt;params[$admin]){
        $this-&gt;layout = &#039;admin&#039;;
    }
    else {
        $this-&gt;Auth-&gt;allow();
    }
}
</pre>
<p>The problem with this however is static pages handled by the pages controller cannot be password protected. To resolve this problem, I had to overload the PagesController class that Cake comes with, and add in the required functionality. Part of the reason for doing this for me was to allow a setup where there was a password protected admin welcome page or control panel located at my_app_URL/admin, so I&#8217;ll show you the necessary routing to achieve that too.</p>
<p><span id="more-272"></span></p>
<h3>Adding a route and overloading PagesController</h3>
<p>First of all, copy your_app_dir/cake/libs/controller/pages_controller.php into your_app_dir/app/controllers with the rest of your application&#8217;s controllers. Then fire up an editor and take a look at your newly copied version.  You&#8217;ll see there is a function called display, this is what the pages controller uses to display pages. There is a route in app/config/routes.php that maps /pages/* to /pages/display/* to make the URL easier on the eyes, so if we&#8217;re gonna have /admin/pages/* working properly, we&#8217;ll need a similar route. Open up app/config/routes.php, and underneath the line</p>
<pre class="brush: php">

Router::connect(&#039;/pages/*&#039;, array(&#039;controller&#039; =&gt; &#039;pages&#039;, &#039;action&#039; =&gt; &#039;display&#039;));
</pre>
<p>add in the following route:</p>
<pre class="brush: php">

Router::connect(&#039;/admin/pages/*&#039;, array(&#039;controller&#039; =&gt; &#039;pages&#039;, &#039;action&#039; =&gt; &#039;display&#039;, &#039;admin&#039; =&gt; true));
</pre>
<p>Now, when admin routing is enabled, Cake looks for controller actions appened with &#8220;admin_&#8221;, so we&#8217;d better add in the function to handle this in PagesController. Open it up, and underneath the display function, add the following:</p>
<pre class="brush: php">

function admin_display() {
    $path = func_get_args();
    $temp = null;

    $count = count($path);

    if ($path[0] != &#039;admin&#039;) {
        //This adds admin to the beginning of the path so the pages controller will look in the &#039;admin&#039; folder in pages directory
        $path = array_merge((array)&#039;admin&#039;, $path);
    } else {
        //This removes admin from the beginning if it&#039;s there already, and sends the request round again so we end up with URLs that look like app/admin/pages/x
        //when app/admin/pages/admin/x is requested somehow.
        $path = array_slice($path, 1);
        $this-&gt;redirect(array_merge(array(&#039;controller&#039; =&gt; &#039;pages&#039;, &#039;action&#039; =&gt; &#039;display&#039;, &#039;admin&#039; =&gt; true), $path));
    }

    if (!$count) {
        $this-&gt;redirect(&#039;/&#039;);
    }
    $page = $subpage = $title = null;

    if (!empty($path[0])) {
        $page = $path[0];
    }
    if (!empty($path[1])) {
        $subpage = $path[1];
    }
    if (!empty($path[$count - 1])) {
        $title = Inflector::humanize($path[$count - 1]);
    }
    $this-&gt;set(compact(&#039;page&#039;, &#039;subpage&#039;, &#039;title&#039;));
    $this-&gt;render(join(&#039;/&#039;, $path));
}
</pre>
<p>As you can see it&#8217;s fairly similar to the display function, with a few extra lines added in that handle admin pages. There are a few subtleties here which I will explain in a second. Before that however, we also require a slight change to the existing, non-admin display function. Look for the if statement below:</p>
<pre class="brush: php">

if (!empty($path[0])) {
    $page = $path[0];
}
</pre>
<p>and change it to:</p>
<pre class="brush: php">

if (!empty($path[0])) {
    $page = $path[0];
    if ($page == &#039;admin&#039;) {
        //Sends admin page requests to their proper place to stop sneaky access attempts
        $this-&gt;redirect(array_merge(array(&#039;controller&#039; =&gt; &#039;pages&#039;, &#039;action&#039; =&gt; &#039;display&#039;, &#039;admin&#039; =&gt; true), $path));
    }
}
</pre>
<p>Ok so what have we done?</p>
<ol>
<li>The added nested if statement in the display() function redirects requests for /pages/admin/x to their proper place, /admin/pages/x.</li>
<li>The &#8216;else&#8217; clause of the if ($path[0] == &#8216;admin&#8217;) in admin_display redirects requests for /admin/pages/admin/x to /admin/pages/x, which just tidies up a URL aesthetics issue.</li>
<li>Finally, the first part of the same if statement is what handles the /admin/pages/x requests proper &#8211; it adds the &#8216;admin&#8217; part back to the beginning of the $path variable that point 2 removes. This is actually just exploiting a subtlety of the pages controller, &#8216;subpages&#8217; (this seems to be quite hard to find in the documentation actually) &#8211; requests sent to /pages/a/b will display a page b stored in the folder your_app_dir/app/views/pages/a, rather than a page b stored in the pages root. Adding this additional logic helps organisation a bit by storing all admin pages in you_app_dir/app/views/pages/admin/.</li>
</ol>
<p>So now this is all in place, everything should work correctly. Requests to /pages/admin/x and /admin/pages/admin/x both get sent to /admin/pages/x, and these require proper authentication.</p>
<p>The final step is to add in a route that allows my original use for this whole setup to work properly &#8211; displaying an admin homepage or control panel that requires authentication when a user visits your_app_URL/admin, i.e. without referring to any controllers or actions. First, create a page in your_app_dir/app/views/pages/admin/, called home.ctp that contains the content you want. You can now access this from your_app_URL/admin/pages/home, but the shorter URL works after adding the route:</p>
<pre class="brush: php">

Router::connect(&#039;/admin&#039;, array(&#039;controller&#039; =&gt; &#039;pages&#039;, &#039;action&#039; =&gt; &#039;display&#039;, &#039;admin&#039; =&gt; true, &#039;home&#039;));
</pre>
<p>Hooray! We now have an admin homepage. Hope everything worked for you, hit me with a comment if you have an issues and I&#8217;ll try and help out.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.actionshrimp.com/2009/04/cakephp-pagescontroller-with-admin-routing/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
	</channel>
</rss>

