The Joomla! Community Magazine™

Joomla! 3.0 Extension Development Series: Writing The Core

Written by | Friday, 01 March 2013 00:00 | Published in 2013 March
In the previous articles we covered setting the stage and beginning the component structure. In this tutorial we will be focusing on the details, writing those functions and files that are core to this extension and actually making the extension start to work and hopefully start unifying the entire component and accomplishing the overall goal.

Step 0: Fix an Espresso

You’re going to need a strong cup of coffee today. In this tutorial we will be covering the details of the models and views needed for the Lendr component series we’ve begun in previous tutorials. If you’re just joining this series, I recommend reading the first article, and then follow up with the initial setup article before continuing with this tutorial. Done with those articles? Ready for the next? Make sure you are ready to go by having your system setup and your code editor fired up ready to begin writing code. And don’t forget your espresso.

Step 1: Model File Details and Functions

Now that we’ve gotten our base files created and started writing our models we need to get into the good stuff. The first thing to do is to sort out the models we will be writing to and the functions that need to be added. Here is a brief overview of those models and functions:

Basic Files and Functions Needed
ModelFunctions
Default save
delete
set
get
getItem
listItems
getState
getTotal
getPagination
Book _buildQuery
_buildWhere
Wishlist _buildQuery
_buildWhere
Profile _buildQuery
_buildWhere
Library _buildQuery
_buildWhere
Waitlist _buildQuery
_buildWhere
Review _buildQuery
_buildWhere

Once we’ve defined a brief overview of the models and functions we’ll need we can begin writing the models. It’s very important to keep the following principle in mind during this process. Our list is fluid and dynamic. We are able to return to our list and add or remove functions as necessary. Don’t be afraid to revisit this list repeatedly as we progress and evaluate things. It’s possible we can simplify by adding a function to a particular model, or maybe we need to rewrite a more abstract function which we can add to the default model. One thing is sure, we don’t want to rewrite the same code over and over, the minute we find we’re starting down that path it’s time to consider how we abstract the code to a common model. Let’s start writing our models.

Step 2: Write the Models

There are a handful of models which make up this Lendr component but we don’t have the time to write all of them out here. We’ll focus on several key models that will help to demonstrate the bulk of the component and leave a few of the secondary models in the associated GitHub repository for you to review on your own. We’ll start by writing the book model. As I began thinking where to start coding I decided to start with the most specific and working out to the library model and then the profile model. The reason for this is simple. The book is the smallest unit, a library is made up of books and a profile then contains a library. I trust that helps you understand why we begin with the book model and work out from there. The very first model we’ll look at will be the default model. We use the default model to store some basic functions that we want to have available in all our models and since we write Object Oriented code we don’t want to re-write the same functions in each model.

Model Files
default.php
book.php
library.php
profile.php

Step 3: Incorporate Additional Resources

As we write this component there are certain aspects where it would be nice to incorporate third party features rather than reinventing the wheel. We have been able to simplify our styling and layouts by utilizing the Bootstrap classes available with Joomla! 3. Other handy resources that can be used include, Gravatar and Open Library. If you are unfamiliar with these tools you can read more about them on their respective websites. Below is a brief explanation of how they are used in Lendr.

Gravatar

Gravatar provides a simple way to retrieve an image or avatar associated with an email address. Lendr makes use of this to display profile pictures in an incredibly straightforward way. You will see the code necessary to make it happen when we write the view layouts in the step below.

Open Library

Open Library provides a great way to retrieve a book cover specific to an ISBN. This allows us to easily include a cover with each book without the hassle of maintaining storage space, image uploads etc. Open Library has several fields which can be used to reference the book cover and return the image, Lendr makes use of the ISBN which is part of the Add Book form found below. You will find the code in the layouts below.

Step 4: Start View Layouts and Styles

The first thing we do will be to return to the entry point for the component. This is the default controller as we reference it within the root lendr.php file. After writing out our models it’s clear we need to update where the user starts. We have changed the following line of code in the default.php controller:

joomla_root/components/com_lendr/controllers/default.php

$layoutName   = $app->input->getWord('layout', 'list');

This will now send the user to the list view of the profiles. That’s the first view we’ll look at. In our views folder we have a profile folder with the following structure in it:

Folder Structure

profile
  tmpl
    _entry.php
    index.html
    list.php
    profile.php
  html.php
  index.html
  phtml.php

Writing the Files

We will look first at the html.php file. This file is the default type we referenced by Joomla! and the current naming conventions. We saw the basic structure of these files in the previous article.

Individual Files

html.php

Aside: Because we have called the view helper it is worth reviewing that file now.

view.php

Returning now to the original html view file, we can see the parameters we pass to the view helper load function. First, we tell the helper which view folder we wish to use, next the layout to be used, and lastly in these cases, we return the page format type. For a variety of reasons we have created a new file and called it phtml.php to represent partial html.php. We have used this file instead of the standard html view because of the various additional functions currently being called within the html.php file. Because in most cases we simply want a basic render function for partial templates we don’t want the overhead associated with the standard html file. While there are other methods for handling problems like this, having a different file for the view will help organize things and also provide an easy location should additional functions relevant only to partial templates be necessary.

phtml.php
_entry.php
list.php
profile.php

Remaining layouts

We’ve reviewed all the layouts in the profile tab but through the process we’ve found additional views called to be rendered within the profile layout. For the sake of the length of this article we will not list each view and the code found within. Instead, you can view the code associated with each of these view directly in the GitHub repository.

Step 5: Javascript and CSS

The last piece we’ll look at in this article is the beginning of the Javascript and CSS associated with Lendr. Because Lendr uses Bootstrap and jQuery the modal window referenced in the previous step for adding a new book is included automatically and we don’t have to write any specific Javascript functions to accomplish that. There are quite a few parts of the system though where we will need to write specific javascript code and there will also be times when specific CSS styles will be necessary. We will add the following helper file to address styles and javascript.

joomla_root/components/com_lendr/helpers/style.php

<?php
// no direct access
defined('_JEXEC') or die('Restricted access');
 
class LendrHelpersStyle
{
  function load()
  {
    $document = JFactory::getDocument();
 
    //stylesheets
    $document->addStylesheet(JURI::base().'components/com_lendr/assets/css/style.css');
 
    //javascripts
    $document->addScript(JURI::base().'components/com_lendr/assets/js/lendr.js');
  }
}

Here we associate any css and javascript related to our component. This helper file resides in the helper folder and again follows the standard class naming convention for the component. This class is included automatically based on the namespace (loader) as defined in the root lendr.php file. We call this class from that same root file with the line of code:

joomla_root/components/com_lendr/lendr.php

//Load styles and javascripts
LendrHelpersStyle::load();

Now that we have javascript and CSS files included we can begin to add functions as we need them. The first function we’ll add is in relation to the new modal we’ve just created for adding a book.

After the add book form has been filled out the user submits the form through the “Add” button. When this button is clicked it fires the javascript action addBook();

joomla_root/components/com_lendr/assets/js/lendr.js

//add a book
function addBook()
{
  var bookInfo = {};
  jQuery("#bookForm :input").each(function(idx,ele){
    bookInfo[jQuery(ele).attr('name')] = jQuery(ele).val();
  });
 
  jQuery.ajax({
    url:'index.php?option=com_lendr&controller=add&format=raw&tmpl=component',
    type:'POST',
    data:bookInfo,
    dataType:'JSON',
    success:function(data)
    {
      if ( data.success ){
        jQuery("#book-list").append(data.html);
        jQuery("#newBookModal").modal('hide');
      }else{
 
      }
    }
  });
}

In this function we first use jQuery to create a bookInfo object which contains all of our form variables. Once we have those variables in a single form we begin creating an ajax submission, again using jQuery. Notice that we specify our URL details to include the controller, the format, and the tmpl (or template type). A few things to note here. Because Lendr is a Joomla! 3.x extension our controllers are single function controllers, meaning they all contain only one function (execute). The format is used to return only the data from the controller and the tmpl tells the Joomla! template which file (component.php or index.php) to use. We then describe the type of submission in this case POST. For the data we assign the bookInfo object we created earlier and for the type we specify JSON.

The controller (in this case add.php) will then handle taking the form submission, posting it to the correct model to be stored and then return the result. The result will be a JSON encoded array with a success variable being set. This controller is below:

joomla_root/components/com_lendr/controllers/add.php

<?php defined( '_JEXEC' ) or die( 'Restricted access' ); 
 
class LendrControllersAdd extends JControllerBase
{
  public function execute()
  {
 
    $return = array("success"=>false);
 
    $model = new LendrModelsBook();
    if ( $row = $model->store() )
    {
      $return['success'] = true;
      $return['msg'] = JText::_('COM_LENDR_BOOK_SAVE_SUCCESS');
 
      $bookView = LendrHelpersView::load('Book','_entry','phtml');
      $bookView->book = $row;
 
      ob_start();
      echo $bookView->render();
      $html = ob_get_contents();
      ob_clean();
 
      $return['html'] = $html;
    }else{
      $return['msg'] = JText::_('COM_LENDR_BOOK_SAVE_FAILURE');
    }
    echo json_encode($return);
  }
}
Note: ob_start(), ob_get_contents(), and ob_clean() are used so that we can render the partial template and return the resulting html to the javascript. to be added dynamically to the page.
Note: The result of this execute function is an echo of the JSON encoded return array. This is because we process this controller through AJAX.

Returning to the javascript function above we now can examine the results of the AJAX post and parse the response.

if ( data.success )
  {
    jQuery("#book-list").append(data.html);
    jQuery("#newBookModal").modal('hide');
  }else{
    ...
  }

Here we take the html (which we rendered in the controller and assigned to the html variable) and append it to the book list table body. We will also hide the modal upon success. Currently we have an empty “else” statement which we will fill in later with an appropriate message. This will be part of the finishing touches article yet to come later in this series.

Conclusion

Did you make it through? This article is a much more detailed and in-depth article than previous ones have been but should provide a fairly comprehensive approach to developing commercial level extensions in Joomla! 3 using established coding standards and also implementing new MVC functionality as well as other features unique to Joomla! 3.x. The next tutorial in this series will continue to fill out models and controllers, views and javascript as necessary to continue developing the extension.

I hope the above has been helpful as you create your own components for Joomla! and I hope you will contact us if you have questions or comments regarding any of the above. Parts of the above article were re-written multiple times as I sought the best method and clearest format for both code and layouts. I am aware there are aspects of this step that have not been walked through step-by-step (e.g. the book _entry layout with buttons). I am certainly willing to provide smaller breakout tutorials on those items should they be of interest and I receive comments requesting them. I look forward to the next article in this series where we will continue to add functionality to the component and add even more exciting features!

Download

Download the component as it exists to this point from the Github repository.

Download

Visit the full tutorial site: http://lendr.websparkinc.com/

In the next tutorial we will write more of the model and controller functionality.

Read 29220 times
Tagged under Developers, English
David Hurley

David Hurley

David Hurley is an open source advocate and travels most weeks of the year to speak around the world on topics of tech, PHP and open source software. He is the Community Manager for Joomla - the second largest content management system in the world. He is also a member of the Production Leadership Team and the Framework maintainers. David writes semi-obsessively at http://dbhurley.com and is an active partner in several businesses.