CakePHP, Using Edit For Add/Edit Functions, & Plugins (Oh My!)

When I work on a project I usually combine my add/edit functions into just edit. This saves some space in my controllers and makes maintenance a lot easier as I have only one function to edit instead of 2.

To accomplish this in Cake, you’d just do something like this:
Router::connect('/:prefix/:controller/add', array('action' => 'edit', "admin" => true));
This will map your controllers in your “app/controllers” folder nicely.

But let’s say you’re building an app that includes plugins. You may think “Ha hah! I’ll just slap this in my routes.php file”:
Router::connect('/:prefix/:plugin/:controller/add', array('action' => 'edit', "admin" => true));
And it will work..kinda.

More specifically, it will work for the subcontrollers of your plugin. For example, if you have a news plugin, and the news plugin has a comments controller, the above route will work, because it will map “/admin/news/comments/add” to /admin/news/comments/edit”.

HOWEVER!! This will NOT work for the news controller itself
Dramatic Chipmunk

*ahem* Luckily, the fix is easy and only took me 2 days to figure out (hey, I have kids; things get put aside…yeah, that’s my reason)
Router::connect('/:prefix/:plugin/add', array('action' => 'edit', 'admin' => true));
Now you can access “/admin/news/add” as you’d expect!

New Source for Code Snippets

I’ve signed up at Github, and will from now on be posting code snippets and such there.

CodeIgniter + Smarty w/Layout Capabilities – http://gist.github.com/264823

Frameworks Part Trois (or, Sometimes when you're right, you're wrong)

Yesterday I posted about my experience trying out CI, Cake, and Kohana side by side while I work on my super-cool-blah-blah-blah idea. I mentioned how I was unable to retrieve lists of things with Cake and Kohana, and how quickly I got through things using CI + DataMapper.

Well, Houston, we hit a problem.

Last night I realized that DM was not encoding passwords before inserting/updating them in the database. I ended up changing it to just encode the posted password value and insert (not an ideal solution, IMO). This morning I was making a few other changes and running some tests and I realized something huge.

DM was not validating any of the data.

Obviously, this is a HUGE concern, and not one I was particularly interested in trying to track down and fix. On a whim I decided to give Kohana one more try, and holy [expletive] am I glad I did.

I have no idea what I was doing wrong yesterday with the ORM library but today it’s been working flawlessly (knock wood). It’s validating things the way it should, inserting and updating the way it should, and (hopefully) will help maintain the relationships the way it should.

As far as the rest of the functions and such, it was extremely easy to switch things from CI to Kohana (the fact that I’m only about 4 files in helps ;)). I’ve been able to find/figure out pretty much everything from the docs on their site and a little googling.

At this point, assuming the ORM continues working the way it should, I feel pretty good that I’ll finish up this project with Kohana.

Side note: I found a module at projects.kohanaphp.com that’s called “Debug Toolbar” and it’s pretty sweet. It shows execution time, memory consumption, all db queries, and other nerdy goodies for the developer to use. It sits at the top of the browser, out of the way, and is slightly transparent. Cool stuff!

Frameworks, My Opinion Part Deux

Earlier this week I had a super-awesome-omg-eureka idea for a program. This idea was so hot that I put the forum project on the back burner so I could concentrate on this new idea – something I never do.

As I’ve mentioned here before, I love CodeIgniter. It’s fast, it’s simple, and it’s flexible. However, I decided for this project to try my hand (again) with CakePHP and Kohana, sort of creating side (CI) – by side (Cake) – by side (Kohana) to see which I was able to develop with faster.

For CI, I used CI 1.7.1 with DataMapper for ORM capabilities.
For Cake, I used the latest 1.2
For Kohana, I used the latest 2.3.1 and utilized the ORM library

Now, I was well aware that I would need to reference a lot more for Cake and Kohana, since I only had passing experience with them.  My biggest focus with them was database interaction since this app is database-driven.

I’m still pretty new to ORM, and perhaps there was something I missed, but I absolutely could not get a list of records using Cake or Kohana. I followed the docs on their respective sites and even copied a couple of examples (changing tables/fields as needed), and still nothing. I’m not sure if it’s just me but Kohana’s ORM find_all function does not seem to work at all. The only result I got was “Resource id #31”. Googling both frameworks for some insight brought me no definitive solution. I worked for nearly 3 hours on each to get a complete controller functioning, and only got as far as the C and the U.

On the other hand, using CI + DataMapper, I had a complete controller with all functions – C, R, U, and D – ready to go in less than an hour, including time to reference the DM manual.

I was also less than impressed with Cake’s atrocious loading times. I loaded the same controller from each framework, and my results were CI: 0.348, Kohana 0.83, and Cake 3.29. That means on my (admittedly lower-spec) server, it took 10x as long for Cake to load as CI! I’d hate to see the load times when the entire app was up and running :-\

I guess for now I’ll be sticking with CI + DM. If Kohana can get their ORM library fully functional I’d give them a try again; I will admit that I felt Kohana was more flexible in certain areas and allowed a bit more fine-tuning, as well as having some features that CI doesn’t (Auth, Payment modules).

forum update part deux

I am more or less finished with the first draft of the forum. The nuts and bolts of the program are there (not highly polished but that’s what second/third/fourth drafts are for), and I am feeling pretty good about things.

Originally I was going to use a simple, hard-coded usergroup method to handle permissions for the forums. However, when I wanted to start adding permissions such as ability to view profiles, users online, ips, etc, it became a LOT harder to use the simple, hard-coded method. So I ended up creating somewhat of an ACL (access control list) for usergroups, which is working out pretty nicely. I combined the ACL (which is stored in the database) with some database caching to cut down on queries and it seems to work pretty well.

So far the hardest part has been syncing everything to work correctly — updating thread reply numbers when a post is created or removed, for example. You look over everything before testing it out and there’s (almost always) one little glitch that managed to sneak in there. So you fix it, then go back and reset the database (because apparently your program felt he was being a nice chap by updating what it could) and try again.

I am now on to rewrite #1. I am going to try my hand with Object Relational Mapping this time. I am hoping it will help speed up the CRUD-writing and make maintenance way easier — 2 things that ORM seems to offer, from all the research I’ve done. For anyone who is interested, I’ll be using DataMapper.

So – here I go! 🙂

Forum Update

Well, I’ve been working on my forum for a week now, and so far this is what I have done:

  1. Create/Modify/Close/Open/Delete Categories/Forums with per-forum permissions for each usergroup
  2. Create/Modify/Ban/Unban/Delete Users
  3. User Registration & Login
  4. Create New Thread
  5. Modify/Move/Delete Thread (for those with sufficient permissions)
  6. Reply with BBCode and Smilies
  7. Quick Reply with BBCode
  8. Modify/Delete/Restore Posts
  9. Integrated Smarty with Layout Capabilites

Phew! It’s kind of nice to see that I actually did get a lot done; truthfully I keep wondering if I’m wasting my time with this when there’s so many other forum scripts out there that have a team of people behind them.

Another neat thing I did was port CI’s form helper functions to Smarty functions so I can use things like

{form_open url="controller/function" id=$id}
(The id is if I’m modifying something; it appends the id to the action url)
and
{form_input name="field_name" value="submitted_value" default="default_field_value" extra="usually_css_here"}

If anyone is interested in having a copy, let me know in the comments and I’ll attach the functions I have. Currently includes form_open,form_close,form_dropdown,form_input,form_hidden. In addition, I ported the anchor and link_tag helper functions.

There’s still so much to do I wonder if I’ll get it done. I’m pleased with the progress so far, and if nothing else I am learning a lot 😀

Super duper easy Code Igniter + Smarty WITH layout capabilities!

I’m deep in the midst of the forum I’m creating (more updates about it to come later) and I decided to implement Smarty into it since I’m considering releasing it for distribution at some point, and my target users would definitely be more comfortable with {$var} than <= $var; ?> or <php echo $var; ?> .

The one thing snagging me was how to incorporate a layout so I didn’t end up with 100+ template files that had the {include file=”header.tpl”} in them. Definitely a PITA and not that great if you want more flexibility.

With a little bit of trial and error, I created a library that is less than 50 lines long, works awesomely with Smarty and supports layouts.

Instructions
1. Download the latest version of Smarty from http://www.smarty.net
2. Extract the /libs folder to your application/libraries folder and rename to smarty
3. Open your favorite text editor and put the code found @http://codesnippets.joyent.com/posts/show/1966 into it.

Save as Template.php in your application/libraries folder. In the __construct() function, change the paths to suit your application. For me, I chose to place my templates folder above my application folder, and the other folders within the /smarty folder. You can also change the template extension in the layout function to something other than .tpl, if you like.

3b. If you want to load this application-wide, open up your config/autoload.php file and add “template” to the libraries array.

4. Next, create a default.tpl (or default.html, etc) file and where you would like the content displayed, put the following:
{include file="$inner_template.tpl"}
(again, you can change the tpl to something else if you wish). Save this to your templates folder.

5. To use, load the template library and then use it like so:
$this->template->layout("content_template", array("array"=>"of stuff","to"=>"use within the template"));

6. If you want to use a different layout for part of your app, simple include the following line before calling the $this->template->layout function:
$this->template->theme = "other_layout_name";

There may be better ways to do this, and I know a lot of programmers absolutely loathe template engines and will argue til the sun comes up that they serve no useful purpose and everyone should stick with pure php. However, this particular method is working very well for me and my program 🙂

I've had it

I’ve been messing around with various forum software over the past week – phpBB 3, myBB, bbpress, vBulletin. They all have their pluses and minuses, but I’ve decided to create YAFS (yet another forum software) for my site, because, frankly, I’m just totally annoyed with having to bend what I want out of my forum to what is in the aforementioned software.

Overall my main complaint is that phpBB, myBB, and vBulletin are too bloated for what I need. bbPress is charming in its simplicity but it’s actually too simple for what I want.

This should be an interesting test. I will strive to post regularly on my experiences building a forum software.

CSS-Only Accordion

This was actually really easy to do, so much so that I felt kind of embarassed when I figured it out. Most of the credit should be given to cssnewbie; the modifications I made simply expanded on their article to only show the titles of the accordion sections.

The CSS:
#accordion {}
#accordion div {width:100%; height: 20px; padding: 3px; margin-bottom: 10px; color: #fff; overflow: hidden;}
#accordion div.content {display: block; border:1px solid #efefef; color: #363636;}
#accordion span.acc_head{display: block; font-weight: bold; background: #F1E3EB; padding: 3px;}
#accordion:hover div { height: 20px; }
#accordion:hover div:hover { height: auto; color: #363636;}
#accordion ul { list-style-type:none;display:inline table;margin:0;padding:0; width: 100%;  table-layout: fixed; }
#accordion li { display: table-cell; position: relative; min-width: 175px; max-width: 175px;}

The ul and li items are optional; I tend to use this with stuff I want to display in a table-type format.

The HTML:
<div id="accordion">
<div class="content">
<span class="acc_head">Title One</span>
Content and such
</div>
<div class="content">
<span class="acc_head">Title Two</span>
Content and such again
</div>
</div>

That’s it! The divs (should) only display the the titles of the content divs, the div being hovered on should expand to reveal all content, and the non-hovered divs should remain showing titles only.

Dropdown Country List with Code Igniter and Zend Framework

Note: This assumes you are using Code Igniter, have loaded the form helper, and have followed this guide to integrating Zend Framework with CodeIgniter.

This was so easy that it was scary!

public function country_list($field_name="country",$selected="US")
{
$this->load->library('zend');
$this->zend->load('Zend/Locale');
$locale = new Zend_Locale('en_US');
$countries = ($locale->getTranslationList('Territory','en',2));
asort($countries,SORT_LOCALE_STRING);

return form_dropdown($field_name,$countries,$selected);
}

This returns a nice list of countries with the 2-letter codes as the option values.