An introduction to SafeCracker brought to you by META Q

An introduction to SafeCracker

The SafeCracker module for ExpressioneEngine lets users build channel entry forms within site templates, making it possible to edit and add new content outside of the ControlPanel. Although SafeCracker was originally a third party add-on developed by Barrett Newton, it has now been acquired by EllisLab and integrated into the base EE install.

I thought it might be nice to go through the basics of using SafeCracker in a situation that most, if not all ExpressionEngine website developers will encounter: creating a blog. So follow along as I create a stand-alone entry form for a simple blog channel.

In order to use SafeCracker, ExpressionEngine 2.3.1 or later is required.

Getting Started

To start off, I’ve created a sample blog channel, which includes  the following fields:

  • A text area field called “Body”
  • A text input field called “Currently Listening”
  • A select dropdown list field called “Current Mood” with the options Happy, Sad, and Mad

I’ve also created a standard template for displaying entries from this channel.

Installing & configuring SafeCracker

Let’s install SafeCracker.

In the Control Panel go to Add-Ons >> Modules, and then click “install” in the SafeCracker row. Then, follow the steps through installation.

Once SafeCracker is installed, I’m going to configure it for each channel that I want to use Safecracker on. In this case, I only need to configure it for the Blog channel. Next, I’ll select “Open” as the default status and  leave “Allow guests to post entries” unchecked, since I only want to allow logged in members access to my SafeCracker publish forms.

Creating the new entry form and edit entry form

Next I’ll create two forms, one for adding new entries and one for editing existing entries. The forms are aptly named: new entry form and the edit entry form. I’ll create these forms in two different templates, starting with the new entry form.

The new entry form

Inside of an HTML template, which I’ll call, new-entry.html (in the “blog template group) I’ll add the tags that initialize the SafeCracker functionality.

{exp:safecracker channel="blog" return="blog/URL_TITLE"}
{/exp:safecracker}

In these SafeCracker form tags, I've specified “blog” as the channel I want to create entry forms. The return parameter lets me specify a URL to redirect to once the form has been submitted. By using the uppercase URL_TITLE, ExpressionEngine will redirect me to the entry that I've just created.

Now I can move on to creating the blog channel fields. First, I want to add the Title field. Inside the opening and closing exp:SafeCracker tags, I'll add the following code:

<label for="title">Title</label>
<input type="text" name="title" id="title" value="” >

This is a pretty standard label/input pair, but because they reside within the SafeCracker tags, ExpressionEngine knows to store the input as the entry's title.

Now I'll add a status menu after the Title field:

{status_menu}
  <label for="status">Status</label>
  <select name="status" id="status">
    {select_options}
  </select>
{/status_menu}

Here, I've used the {status_menu} pair and select tags to create the status menu dropdown. For each of the options, I added the {select_options} which tells EE to loop through and output each option automatically.

And now for my custom fields, body, currently listening and current mood. These can be coded much like the Title and Status fields above.

<label for="body">Body</label>
<textarea name="body" id="body"></textarea>
<label for="currently_listening">Currently Listening To</label>
<input type="text" name="currently_listening" id="currently_listening">
<label for="current_mood">Current Mood</label>
<select name="current_mood">
  {options:current_mood}
    <option value="{option_value}" {selected}>{option_name}</option>
  {/options:current_mood}
</select>
Of course, it's important to include a submit button:
<input type="submit" name="submit" value="Submit">
That takes care of the new-entry form. The complete code and markup will look like this:
{exp:safecracker channel="blog" return="blog/URL_TITLE"}
  <label for="title">Title</label>
  <input type="text" name="title" id="title" value="” >
  {status_menu}
    <label for="status">Status</label>
    <select name="status" id="status">
      {select_options}
    </select>
  {/status_menu}
  <label for="body">Body</label>
  <textarea name="body" id="body"></textarea>
  <label for="currently_listening">Currently Listening To</label>
  <input type="text" name="currently_listening" id="currently_listening">
  <label for="current_mood">Current Mood</label>
  <select name="current_mood">
    {options:current_mood}
      <option value="{option_value}" {selected}>{option_name}</option>
    {/options:current_mood}
  </select>
  <input type="submit" name="submit" value="Submit">
{/exp:safecracker}

The edit entry form

Once the new-entry form is complete, I can actually copy it to create the edit entry form with a few slight modifications. In the edit entry template, I can paste the code from above and add the entry_id parameter to the opening exp:safecracker tags like so:

{exp:safecracker channel="blog" return="blog/URL_TITLE" entry_id="{segment_3}"}

This tells SafeCracker that I want to use “segment 3” in the URL as the entry ID to edit. So, for example, I could create an HTML link to http://www.example.com/blog/edit-entry/5 and S,afeCracker will know I want to edit “entry 5." I could also use the entry_title parameter instead, but I feel that entry_id is more reliable.

When I edit an entry, I want to see the data that's already there. To do so, I can go through each field tag and add the output tag associated with each field. Here's an example from the Title field:

<input type="text" name="title" id="title" value="{title}” >

Here, I've added the {title} tag to the value attribute of the Title input HTML tag.

The complete markup looks like this:

{exp:safecracker channel="blog" return="blog/URL_TITLE" entry_id="{segment_3}"}
  <label for="title">Title</label>
  <input type="text" name="title" id="title" value="{title}” >
  {status_menu}
    <label for="status">Status</label>
    <select name="status" id="status">
      {select_options}
    </select>
  {/status_menu}
  <label for="body">Body</label>
  <textarea name="body" id="body">{body}</textarea>
  <label for="currently_listening">Currently Listening To</label>
  <input type="text" name="currently_listening" id="currently_listening" value="{currently_listening}">
  <label for="current_mood">Current Mood</label>
  <select name="current_mood">
    {options:current_mood}
      <option value="{option_value}" {selected}>{option_name}</option>
    {/options:current_mood}
  </select>
  <input type="submit" name="submit" value="Submit">
{/exp:safecracker}

Security and limiting access

I now have working SafeCracker forms that allow me to add and edit blog entries!

However, I have to be logged in to do this, and since I don't want to have to access the ControlPanel when I add or edit entries, I can create a stand-alone log in form to take care of that.

To start off, I'll add a bit of code to the header of my templates that tests to see if the user is logged in and, if not, to redirect to the log in form:


  {redirect='/login'}

Then, I'll create a new template called “login,” and add the log in form code:

{exp:member:login_form return="/blog"}
  <label>Username</label>
  <input type="text" name="username" value="">
  <label>Password</label>
  <input type="password" name="password" value="" >
  <input type="submit" name="submit" value="Submit" class="btn">
{/exp:member:login_form}

That's it!

So to recap:

I created a sample blog channel with sample field groups. I configured each channel that I wanted to use SafeCracker on (in this case just the Blog channel). I then created two forms for publishing, the new entry form and the edit entry form.  In order to add and edit blog entries using these forms, SafeCracker requires me to be logged-in. Since I don't always want to login through the ControlPanel, I created a stand-alone login form as well.

More with SafeCracker

In this tutorial I've only just scratched the surface of what SafeCracker can do. With a little imagination and the SafeCracker module, it's possible to create full-fledged web-applications.

If you've created something amazing with SafeCracker, share it below. I'd love to see it in action.

And, as always, feel free to ask any questions in the comment section below. 

Happy SafeCrackin'!

Photo Credit: squacco


Terris Kremer's avatar

Terris Kremer

Front-end developer at Q Digital Studio

Terris Kremer is a front-end developer at Q Digital Studio. While he may joke that both front- and back-end developers are dweebs, Terris really does make development look cool. For Terris, work is a game that he can (and does) play all day long.

Posted

12.6.2011

Categories

Code > ExpressionEngine

Tags

3 comments >

Speak your mind


Social Media Love

What others are saying

Jeff

Thank you, Terris. Very helpful! The only question I have is how would one handle value=” ” when dealing with a file input type, rather than text? My Safecracker form allows for image uploads, so I would love to show the name of the file that the user uploaded. When I try putting value=“anything” (static or {dynamic}) in the <input>, nothing appears in the text field on the front end.

Again, great post. Thanks,
Jeff

Martijn La Feber

Hi Terris,

Thanks for the good tutorial. I have a question. Is it possible to send an email to the person (he is a member) who submitted his content include his email address with SafeCracker?
The wish is to send an html email with filled in content to the submitter.

Tnx in advance.
Keep up the good work.

Grtz,
Martijn

Co-owner EEsnippets.com

Brian

Hello,

Thank you for this tutorial, I am very excited about the possibilites.

I saw one oddity, when I go the the edit page I made with the above code, the title input box has:

mytitletext title” ><label for=

(all that text in it)

When I changed it to
<label for=“title”>Title</label><input name=“title” type=“text” value=”{title}”>

it worked and the title field just said mytitletext I did not get a duplicate entry.

Thx again!

TOP