Wordpress

The WordPress $Post Object and You

September 15, 2011   ·   By   ·   1 Comment   ·   Posted in Customization, Functions, The Loop, Wordpress

Ah, fair $post object. Lets talk about how great you are.

The What What?

Post Object. WordPress stores all post data (think content, author, tags, etc) in a single object, accessible to themes and plugins on each page load. Basically, this is the place you’re going to go to if you want to get some extra information about a post for whatever clever scheme you’ve got cooked up. Need to know how many “n”s are in this particular post? Talk to the post object. Not sure when this post was originally published? Post object. Looking for lawyers who ride? Now we’re talking – but you want the Law Tigers, not the $post object. Watch their commercials. You won’t regret it.

How do I get at this mystical post object?

Single Posts

The post object is available nearly everywhere you’re likely to be looking at a post. If you’re working with a single post page, or an actual page, you’ve got access to that post’s (or page’s) post object anywhere within your theme file. It’s all held in a variable named $post.

Multiple Posts

If you’re on a page with multiple posts, things are a little trickier but not much. If you’re inside the loop, you’ve got access to a $post object (named $post) referring to the current post in the loop.

Elsewhere

What if you want to get at a post that isn’t the one you’re looking at on a particular page – or what if you want to get at one from a plugin, or somewhere where there isn’t a current post explicitly defined? There’s a function for that:

$id = 41;
$mypost = get_post($id);
print_r($mypost);

get_post() to the rescue! There are, however, a couple of gotchas with get_post.

  1. You have to pass it a variable – not an integer. See how in the example above, I set $id to 41, an then used $id as the argument to get_post(), instead of just saying get_post(41)? That’s important. If you try to pass an integer to get_post(), it will blow up. No Joke.
  2. You probably shouldnt use the variable $post. Why not? Because WordPress uses $post all the time, and chances are you’ll either overwrite WordPress’ version of $post, or they’ll overwrite yours – either way, somebody is going to be mad. Choose something more clever than $post (like $mypost!). I know you can do it.

What if I don’t like getting the data back as an object? I’m an associative array kind of guy.

get_post() gets you. So do I. There’s a second, optional argument to get_post that determines what it spits out at you. It defaults to OBJECT, but you can also pass in ARRAY_A, or ARRAY_N to get an associative array or a numeric array version of the post data.

Ok, I’ve got a post object – what kind of data is in there?

Find out for yourself! The snippet above uses the function print_r() – it will show you the structure AND data of a particular post object – very useful stuff. Surround it in a <pre> tag, and you’ll be in even better shape – it will display nicely in your browser.

I’m too lazy for that. Didn’t I come here for you to teach me about this?

Well played. Here’s a quick rundown on the data the post object gives you:

Property Example Explanation
$post->post_title The WordPress $Post Object and You Title of post.
$post->post_excerpt Learn about the WordPress $Post object! Manually created post excerpt. If you didn’t purposefully create an excerpt on the add post page, you’re not getting anything here.
$post->post_status
  • publish
  • pending
  • draft
  • auto-draft
  • future
  • private
  • inherit
  • trash
Current status of the post.
$post->comment_status
  • open
  • closed
  • registered_only
Comment status for this particular post.
$post->ping_status
  • open
  • closed
Does the current post accept pingbacks and trackbacks?
$post->post_password 123456 The plaintext password for this post, if there is one. Empty otherwise.
$post->post_name the-wordpress-post-object-and-you A normalized, sanitized version of the post title, used to generate pretty permalinks.
$post->to_ping http://technorati.com http://someothersitetoping.com Space separated list of sites to ping which have not been pinged yet. Modified by “Send Trackbacks” field on add post page.
$post->pinged http://technorati.com http://someothersitetoping.com Space separated list of sites already pinged for this post.
$post->post_modified 2011-09-15 21:21:59 Time this post was last modified, based on local server time. MySQL timestamp format.
$post->post_modified_gmt 2011-09-15 21:21:59 Time this post was last modified, based on GMT timezone. MySQL timestamp format.
$post->post_content_filtered Post Content This field is designed to hold a version of the post for caching, in situations where filters are being run on the post that are “expensive” (slow), and undesireable to run every time. Not used in WP core, may be used by plugins.
$post->post_parent 0 ID of the parent post. Posts that have parents are generally revisions, or attachments. If the post_parent is 0, this is a bona-fide, original post.
$post->guid

http://codegarage.com/blog/?p=41

Global Unique Identifier for the post. According to the documentation page on wordpress.org, this can’t be relied on to actually work as a link to the post, but I’m not totally sure why. Maybe in cases where the site url has changed?
$post->menu_order 0 Integer determining the order in a list of posts. Generally used for pages in menus, but can be used by plugins for special ordering.
$post->post_type
  • post
  • page
  • attachment
The particular type of post this is. Attachments are generally images, pdfs, etc. Posts and pages are self explanatory.
$post->mime_type image/png Mime type for attachments.
$post->comment_count 14 Number of comments on this post currently.
$post->post_ancestors array Array of parent posts for this post.

Whew!

I think that about covers it. One last question you might have:
How do I get WordPress to spit out properly formatted post content?

Good luck!

Upgrading or Uploading WordPress Via FTP

August 17, 2011   ·   By   ·   No Comments   ·   Posted in Troubleshooting, Wordpress

Yesterday we talked about how to access your WordPress site via FTP – today, we’ll talk about something more important: Upgrading or reinstalling WordPress using FTP instead of the WordPress backend.

Why?

Again – this all comes down to saving your own butt. If an automatic upgrade fails in the middle, you’re in trouble – chances are that some, but not all of the files necessary have been reinstalled/updated. Because of this, the Dashboard is often left inaccessible, and you have to fall back on your old friend FTP.

Other reasons you might do this:

  1. You got hacked, and you want to make sure your core WP files are clean.
  2. You started tinkering with Core WordPress files, and now the site doesn’t work
  3. You uploaded a shady plugin which modified core WordPress files, and now the site doesn’t work

Public Service Announcement

Back up your site before you do this. Please. If you mess it up, and lose all your uploads, you’re going to be really mad, maybe at me. Don’t have a backup service? Good news – I have one that I can shamelessly plug. Check it out at the front page.

Lets get to it. Since we already understand how to access WordPress via FTP, we can get started without fear.

Step 1: Download WordPress

WordPress.org has a handy feature: the latest version of WordPress is always available at:

http://wordpress.org/latest.zip

If you ever need a copy, just enter that address in the url, and it will start downloading. The more traditional page for finding your download is here:

http://wordpress.org/download/

Need an old version of WordPress? They’re nice enough to keep those around too:

http://wordpress.org/download/release-archive/

So you’ve downloaded the version of WordPress you need. Good work!

Step 2: Unzip it

Next, you need to extract the zip you downloaded. Hopefully this isn’t too tricky – as long as you know where your downloads end up. In most cases, it’s as simple as finding the zip file and double clicking it. You should end up with a folder titled “WordPress”, which has the entirety of a WordPress install inside of it.

Step 3: Upload it

All that’s left is to upload. Now – you need to take some special consideration before you just go uploading all these files. Make sure you’re:

  • Uploading the right things
  • To the right place
    • Simple, right? Here’s what we need to do: We want to upload the contents of the WordPress folder (which we just extracted) to the directory on our web server where wordpress is installed, with one important caveat:

      We don’t want to overwrite wp-content

      That deserved to be bolded. The wp-content folder holds your themes, plugins, and uploads – and we don’t want to overwrite it with the default wordpress content. So, we’re going to upload everything except that.

      Upload Everything BUT wp-content


      Now that we’re ready to upload, we’ll just click and drag that mess into filezilla – making sure that in filezilla, we’re looking at the current wordpress install (you should be looking at the inside of a directory that has wp-load.php in it).

      When it asks if you’d like to overwrite files, go ahead and check “Overwite”, as well as “Always use this action” and click “Ok”. Before clicking “Ok” would be a good time to double check that you’ve backed up, adn you’re not overwriting wp-content.

      Now, this is going to take a while – WordPress has a lot of files. Go eat a sandwich, it will be done when you get back.

      All done. Now what?

      Now head back over to your site and get a feel for your handiwork. If you were just trying to fix a problem, ideally at this point your site is working again. If the upload went ok, and your site still isn’t working, the problem lies somewhere else – check your plugins and themes if you haven’t already.

      If you were doing this to upgrade your WordPress install, you’ve got one more step. Head over to yoursite.com/wp-admin, and you should be presented with a screen saying you need to upgrade your database. Go ahead and approve that, give it a minute to think, and you should be redirected to the login page – and you’re done!

Moving a WordPress Blog to a New URL

March 25, 2009   ·   By   ·   5 Comments   ·   Posted in Wordpress

This probably isnt something that comes up too often for the average user – your URL is your identity – so switching them isnt a great choice.  In client work, however, this comes up all the time – development work takes place locally on your computer WAMP/MAMP, or on your server, where the client can keep an eye on things.

Once its ready, however, you need to move the site to their live server, and you need it to work right, and in a hurry.  Oftentimes the client site is already live, and they’re just pushing a redesign out – you need things to not go wrong at this stage.  Even as a personal user, there are a number of things that can go wrong while moving a site to a new URL, and nothing is less satisfying than figuring out why your site wont work after the move.

The Basics:

First, you need to understand how wordpress works – this might seem silly, but I’ve had a number of clients who can’t really conceptualize it – simply because they’ve never really worked with web applications before.  WordPress obviously runs on a database – mysql.  While it would be nice to just be able to move files over to the new server, the database must come along too.  The database stores all of your posts, pages, and comments, as well as any settings that you’ve made during the setup process.  It also stores some important options – most importantly, your blogs URL.   That’s not really within the scope of this post, so the quick version is this – using your database access tool (I like Sequel Pro when I can get external database access, though nearly all hosting setups come with PHPMyAdmin) you need to dump all the wordpress database tables, and import them into the new host’s database.  After that is done, you can put your files (all the wordpress core files, along with your theme, of course) on the new server.

What needs to be updated?

The one file you’ll need to make sure to update is wp-config.php.  You need to make sure that the host has been changed to match your new site’s database settings, and you need to make sure that your database username, password, and database name are all properly updated.

At this point, your blog should be working – but theres a problem – when you load it up, you’re immediately redirected to the old blog url.

picture-11To get around that, you’ll have to get into the database.  WordPress blogs hold nearly all of their settings in a table called options (note – the default name for this table will actually be wp_options, so you’ll have to tack on your database prefix, which is found in wp-config.php, to the front of options to find the right table).  There are 2 main options that need to be changed – the first has an option_name of ‘siteurl’, and the second is ‘home’.  Once you’ve changed these 2 values, you should be able to go to your site at the new url, and login as you normally would.

Other Potential Problems

There are still some problems that you can run into after this point.  The first, and most common relates to your upload directory.  Often, after moving to a new url (or moving to a new host), you’ll start getting a permissions error when you try to use the image uploader.  This happens because of a field in the options table called “upload_path”.  The upload path specifies where to store your uploads (obviously), but when wordpress is installed, this is automatically generated  relative to your filesystem (not web) root.  The easiest way to fix it is to go to the Miscellaneous settings page (Under the settings menu on your dashboard), and change the value there to ‘wp-content/uploads’.

Updating Your Posts

This last piece is a little tricky, and can be dangerous – so please – BACK UP YOUR DATABASE before you try this.  It’s not very hard to mess this up, and its very hard to fix (unless of course, you’ve got a backup lying around).  If you’re moving a blog to a new url, but the old URL had a significant amount of post content on it, you want to make sure that all images now properly link to the new server.  WordPress uses full image paths to link to images inside of posts by default, so if your old url (or the files on it) dissappear, you’ll end up with lots of broken images on the new one.  Also, you want to make sure that any internal linking you did inside of posts is maintained.

The Magic of MySQL find/replace

To get all our old image and link urls properly updated, we’re going to use a mysql find and replace function.  Heres how it looks:

update [table_name] set [field_name] = replace([field_name],'[string_to_find]','[string_to_replace]');

Lots of thanks to this page for teaching me this in the first place.  It has saved me hours.

Here’s how I’d use this mysql snipped to change all the urls in my post content on this blog, if I were moving it to a blog found at http://www.someblog.com/petersnewblog.

update wp_posts set post_content = replace(post_content,'http://yourcodegarage.com/blog/','http://www.someblog.com/petersnewblog/');

A quick rundown of what we did there – The table we want to work with is wp_posts, and the field is post_content.  So we’re taking every instance of

http://yourcodegarage.com/blog/

that is found in the post_content field of the wp_posts table, and replacing it with

http://www.someblog.com/petersnewblog/.

This replaces partial strings, so every time an image used to link to

http://yourcodegarage.com/blog/wp-content/uploads/2009/03/someimage.jpg,

it now links to

http://www.someblog.com/petersnewblog/http://www.someblog.com/petersnewblog/wp-content/uploads/2009/03/someimage.jpg.

The same goes for links.

Thats it – good luck!

Widgetizing a WordPress Plugin: Example Widget Code

March 22, 2009   ·   By   ·   13 Comments   ·   Posted in Wordpress, Writing Plugins

So, every time I need to write a widget for a client, or for a site I’m working on, I have to fire up google. Even though its something I do relatively often, I just can’t seem to remember what exactly I need to hook into, and how to build the actual widget function. Fortunately, this information is impossible to find all in one place – you’ve got Automattic’s page on widgetizing plugins, which is not just confusing, but the code is actually wrong, and won’t work.

Most of the other sample code I’ve found on how to write a widget for your wordpress plugin is either outdated, or not explained, making it pretty difficult to write and customize your own.

First things first – if you really want to know how this all works, check out the source. Its the best place to figure out what is going on. WordPress widgets source

For my own good as much as yours, here’s the skinny:

First things first – the copypasta edition:

<?php
/*
Plugin Name: Widget Example
Plugin URI: http://yourcodegarage.com/blog
Description: Sample Widget Code
Author: Peter Butler
Author URI: http://yourcodegarage.com/blog/
*/

// Hook into wordpress at the "widgets_init" stage.  We need this to get things going.
// We're calling mywidget_init, which will register the widget with wordpress.
add_action("widgets_init", "mywidget_init");

// This is our init function - it's going to register our new widget,
// and if we so please, create a control for it.
function mywidget_init()
{
  // This line is required - it cactually registers the widget for use on
  // the widgets admin page, and it contains the code to display on the
  // front end when the widget is enabled.
  register_sidebar_widget('My Custom Widget', 'custom_widget');
  register_widget_control('My Custom Widget', 'custom_widget_control', '500', '500');
}

// This is the function called by register_sidebar_widget.
// This is where the action happens - WordPress calls this function to actually display
// the widget in the dynamic sidebar on the front end.
// Note the $args parameter - this is required for the sidebar variables
// ($before_widget, etc) to work properly!
function custom_widget($args) {
  // Make sure to extract $args.
  extract($args);

  // Get the options we set in the widget control (remove this line if there arent any).
  $custom_widget_options = get_option('custom_widget_options');
  ?>
  <?php
  //echo the html that should display before the widget as set by register_sidebar().
	echo $before_widget;
  ?>

    <?php  echo $before_title;?>
      <?php echo $custom_widget_options['title']; ?>
    <?php echo $after_title; ?>

    <?php echo $custom_widget_options['text']; ?>
  <?php echo $after_widget; ?>
<?php
}

// This is the callback function for our widgets control -
// here we'll keep the code to allow the user to set the widget options.
function custom_widget_control() {
  // Check if the option for this widget exists - if it doesnt, set some default values
  // and create the option.
  if(!get_option('custom_widget_options'))
  {
    add_option('custom_widget_options', array('title'=>'Custom Text Widget', 'text'=>'This the widget text'));
  }
  $custom_widget_options = $custom_widget_newoptions = get_option('custom_widget_options');

  // Check if new widget options have been posted from the form below -
  // if they have, we'll update the option values.
  if ($_POST['custom_widget_title']){
    $custom_widget_newoptions['title'] = $_POST['custom_widget_title'];
  }
  if ($_POST['custom_widget_text']){
    $custom_widget_newoptions['text'] = $_POST['custom_widget_text'];
  }

  if($custom_widget_options != $custom_widget_newoptions){
    $custom_widget_options = $custom_widget_newoptions;
    update_option('custom_widget_options', $custom_widget_options);
  }
  // Display html for widget form
  ?>
  <p>
    <label for="custom_widget_title">Title:<br />
      <input
      id="custom_widget_title"
      name="custom_widget_title"
      type="text"
      value="<?php echo $custom_widget_options['title']; ?>"/>
    </label>
  </p>
  <p>
    <label for="custom_widget_text">Text:<br />
      <textarea rows=10 cols=25
      id="custom_widget_text"
      name="custom_widget_text" ><?php echo $custom_widget_options['text']; ?></textarea>
    </label>
  </p>
  <?php
}  

Download the example plugin here

It’s commented fairly well, so that should be a good starting point. For those of you who want a little more explanation, read on…

Tell WordPress Your Widget Exists

First things first – we need wordpress to see that our widget is out there just waiting to be implemented.  To accomplish this, we’ll hook into the widgets_init action like this:

add_action("widgets_init", "mywidget_init");

Now, when wordpress calls the widgets_init action, our widget initiation function (mywidget_init()) will get called.  Read more about actions here.

The function mywidget_init is our callback function in that particular action.  When this function gets called, we want to register our widget, as well as our widget control – like this:

function mywidget_init()
{
register_sidebar_widget('My Custom Widget', 'custom_widget');
register_widget_control('My Custom Widget', 'custom_widget_control');
}

The first line registers the widget with wordpress – we’re calling the wordpress function register_sidebar_widget(), which takes these parameters:

function register_sidebar_widget($name, $output_callback, $classname = ”)

  • $name – The widgets name.  Displayed as the title of the widget on the widget page.
  • $output_callback – Function called to actually display the widget for the user on the frontend.
  • $classname – Sets the class of the widget on the frontend.  Useful for styling specific widgets with CSS.  Ends up defaulting to $output_callback, which is generally just as useful.

The second line registers our widget control.  The widget control function will be what allows the user to change any options for the widget on the widgets page on the backend.  Here’s a closer look at the register_widget_control() function:

function register_widget_control($name, $control_callback, $width = ”, $height = ”)

  • $name – Again, this is the widgets name.  It’s important to make sure that the name entered here matches the name you used in register_sidebar_widget – it appears that this string is the only thing that connects them (see what I did there?).  If you can’t figure out why your widget wont stop saying “There are no options for this widget.”, check here first.
  • $control_callback – This is the function we’ll use to display the options, as well as update any values we need to change based on the user’s input on the admin side.  This function contains code for any the face time your widget will get on the back end.
  • $width – An interesting tidbit – I didnt know this (or height) existed before I had a look in the widgets source code.  Setting a width value will expand (but not shrink) the width of your widget options box.  Great if your widget needs a particularly wide control box for entering blocks of text, or something similar.
  • $height – Same as width (well, not exacty the same.  Im assuming you’ve figured out what this one does).
widewidget

A particularly wide widget. Make them as wide as you like with the width parameter.

Creating a configuration box

Now we’re ready to create our configuration box for the widget – this is what will be displayed on the backend, and allow the user to choose any options you make available.  We’ll be using the function we specified in register_widget_control() – custom_widget_control().

To briefly run through this function:

if(!get_option('custom_widget_options'))
{
add_option('custom_widget_options', array('title'=>'Custom Text Widget', 'text'=>'This the widget text'));
}
$custom_widget_options = $custom_widget_newoptions = get_option('custom_widget_options');

First, we get the option we’re going to use to store the configuration infomation for this widget. If it doesnt exist (meaning that this is the first time the widget code has been run, so our plugin has likely just been installed), we’ll create it with some default values. I like to try to keep all the configuration values stored in just one option field, so I prefer to put multiple variables into an array, and serialize them for storage in the database (update – wordpress handles the serializing/unserializing for you with the function maybe_serialize. Read more about it here.)

if ($_POST['custom_widget_title']){
$custom_widget_newoptions['title'] = $_POST['custom_widget_title'];
}
if ($_POST['custom_widget_text']){
$custom_widget_newoptions['text'] = $_POST['custom_widget_text'];
}

if($custom_widget_options != $custom_widget_newoptions){
$custom_widget_options = $custom_widget_newoptions;
update_option('custom_widget_options', $custom_widget_options);
}

Next, we check if values have been posted from the widget configuration form (which we’ll create in a minute). If the values we’re looking for have been posted, we know the user is updating the widget, so we update our wordpress option with the new values.

<p>
<label for="custom_widget_title">Title:<br />
<input
id="custom_widget_title"
name="custom_widget_title"
type="text"
value="<?php echo $custom_widget_options['title']; ?>"/>
</label>
</p>
<p>
<label for="custom_widget_text">Text:<br />
<textarea rows=10 cols=25
id="custom_widget_text"
name="custom_widget_text" ><?php echo $custom_widget_options['text']; ?></textarea>
</label>
</p>

Lastly, we display the actual html form for the widget configuration, making sure to display the values from our option. Putting it all together, here is the function:

function custom_widget_control() {
// Check if the option for this widget exists - if it doesn't, set some default values
// and create the option.
if(!get_option('custom_widget_options'))
{
add_option('custom_widget_options', array('title'=>'Custom Text Widget', 'text'=>'This the widget text'));
}
$custom_widget_options = $custom_widget_newoptions = get_option('custom_widget_options');

// Check if new widget options have been posted from the form below -
// if they have, we'll update the option values.
if ($_POST['custom_widget_title']){
$custom_widget_newoptions['title'] = $_POST['custom_widget_title'];
}
if ($_POST['custom_widget_text']){
$custom_widget_newoptions['text'] = $_POST['custom_widget_text'];
}

if($custom_widget_options != $custom_widget_newoptions){
$custom_widget_options = $custom_widget_newoptions;
update_option('custom_widget_options', $custom_widget_options);
}
// Display html for widget form
?&gt;
<p>
<label for="custom_widget_title">Title:<br />
<input
id="custom_widget_title"
name="custom_widget_title"
type="text"
value="<?php echo $custom_widget_options['title']; ?>"/>
</label>
</p>
<p>
<label for="custom_widget_text">Text:<br />
<textarea rows=10 cols=25
id="custom_widget_text"
name="custom_widget_text" ><?php echo $custom_widget_options['text']; ?></textarea>
</label>
</p>
}

Displaying your widget

Lastly, we’ve got to display the widget.   We’ll need to use the function we called from register_sidebar_widget(), in this case custom_widget.

The first thing we need to make sure of is that we pass in, and extract the variable $args, like this:

function custom_widget($args) {
// Make sure to extract $args.
extract($args);

The widget will display without passing in args, but its necessary, because this is what holds some vital information for our widget. In this particular example, $args holds this information:

Array
(
[name] => Right Sidebar
[id] => Right Sidebar
[before_widget] =>
<li id="my-custom-widget" class="widget custom_widget"> [after_widget] =></li>
[before_title] =>
<h3 class="widgettitle">[after_title] =></h3>
[widget_id] => my-custom-widget
[widget_name] => My Custom Widget
)

picture-2The most important bits that $args holds are the sidebar variables – before_widget, after_widget, before_title, and after_title. Without these, the widget isnt going to display properly. I’ve wasted countless hours (on multiple occasions) trying to figure out why my widget isnt displaying correctly, only to realize that I forgot to pass $args in.

Next, we set up the variables the widget needs to use to display – again, we’ve got them in an array, which is serialized and held in the wp_options database table. To access it, we use get_option(option name).

$custom_widget_options = get_option('custom_widget_options');

Now, it’s just a matter of displaying whatever the widget was intended to display – simple html and php will do the trick here. Make sure to echo $before_widget and $after_widget surrounding the actual content, and $before_title and $after_title surrounding the title. Doing so keeps your widget’s styling in line with the rest of the sidebar.

<?php echo $before_widget;?>

<?php  echo $before_title;?>
<?php echo $custom_widget_options['title']; ?>
<?php echo $after_title; ?>

<?php echo $custom_widget_options['text']; ?>
<?php echo $after_widget; ?>

Putting it all together, here is the widget output function:

function mywidget_init()
{
// This line is required - it cactually registers the widget for use on
// the widgets admin page, and it contains the code to display on the
// front end when the widget is enabled.
register_sidebar_widget('My Custom Widget', 'custom_widget');
register_widget_control('My Custom Widget', 'custom_widget_control', '500', '500');
}

// This is the function called by register_sidebar_widget.
// This is where the action happens - WordPress calls this function to actually display
// the widget in the dynamic sidebar on the front end.
// Note the $args parameter - this is required for the sidebar variables
// ($before_widget, etc) to work properly!
function custom_widget($args) {
// Make sure to extract $args.
extract($args);

// Get the options we set in the widget control (remove this line if there arent any).

$custom_widget_options = get_option('custom_widget_options');
?>
<?php
//echo the html that should display before the widget as set by register_sidebar().
echo $before_widget;
?>

<?php  echo $before_title;?>
<?php echo $custom_widget_options['title']; ?>
<?php echo $after_title; ?>

<?php echo $custom_widget_options['text']; ?>
<?php echo $after_widget; ?>
<?php
}

And that’s it! Your widget is ready for action. Now get out there and make a widget!

Example Plugin Source

WordPress magazine theme