Articles


Our first module, part 8: displaying a history of bids

In this part we will add a new tag to display a list of bids placed for an auction. We’ll call it {exp:auction:history} so we need to add a new function in mod.auction.php called history.

It was useful for the summary tag to be able to run within a channel entries tag as this would be how we would often want to use it to (ie, to display lists of auctions).

However, it is good practise in ExpressionEngine not to nest tags inside others if possible.

Nested tags can lead to you inadvertently using a large number of database queries. A tag that is included inside another tag that loops over a number of iterations will be run multiple times. Depending on the complexity of the internal tag this could be a very bad thing.

From a template processing point of view it can also lead to variable scope clashes if both tags use the same variable. EE automatically generates some variables if you use the $this->EE->TMPL->parse_variables function, such as {count}, {total_results} and {switch} and if you nest tags then it is impossible to control which version of the variable will be used (it will always be the value from the outer tag).

So where possible it is best to design tags that can be used on their own. With this in mind the history tag will be designed to used outside the channel entries tag.

<h4>History</h4>
<
table>
    <
thead>
        <
tr>
            <
th>Bidder</th>
            <
th>Amount</th>
            <
th>When</th>
        </
tr>
    </
thead>
    <
tbody>
    
{exp:auction:history url_title="{segment_3}"}
        {if no_results}
<tr><td colspan="3">No bids yet</td></tr>{/if}
        
<tr {if count==1}class="highlighted"{/if}>
            <
td>{screen_name}</td>
            <
td>&pound;{bid_amount}</td>
            <
td>{bid_date format="%D, %M %j, %Y"}</td>
        </
tr>
    
{/exp:auction:history}
    
</tbody>
</
table

The history tag will be used on single entry pages, that is, pages where only a single auction is displayed rather than a list of them. These pages will be identified by having either the auction entry’s entry id or url title in the page’s URL.

We can then use the segment variables to identify which auction’s history to display. To keep the tag flexible we’ll make it optional whether we use entry id or url title.

To get the auction’s entry_id from the entry’s url_title, we’ll need to join the exp_channel_titles table.

We also want to include some details about the bidder, so we need to join the members table to fetch the user’s screen name.

Joining tables

The $query->result_array() function returns an array of results which is exactly how $this->EE->TMPL->parse_variables likes it, so it easy to produce the final results of.

This leaves us with the final history function of:

public function history() {
    
    
// Find the url title of the auction to add the form for
    
$url_title $this->EE->TMPL->fetch_param('url_title');

    
// Find the url title of the auction to add the form for
    
$entry_id $this->EE->TMPL->fetch_param('entry_id');

    
// Check that one of them is used
    
if( $entry_id === FALSE && $url_title === FALSE {
        
return "";
    
}

    
// Find list of bids for this auction
    
$this->EE->db->select"exp_auction.bid_amount, 
        exp_auction.bid_date, 
        exp_members.member_id, 
        exp_members.screen_name, 
        exp_members.username, 
        exp_members.email" 
);
    
$this->EE->db->from"auction" );        
    
$this->EE->db->join"exp_members"
        
"exp_members.member_id = auction.member_id" );
    if( 
$entry_id !== FALSE {
        
// we have the entry_id, so we don't need exp_channel_titles table
        
$this->EE->db->where"auction.entry_id"$entry_id );
    
else {
        
// we have the url_title, so we need exp_channel_titles table
        // to find the entry_id
        
$this->EE->db->join"exp_channel_titles"
            
"exp_channel_titles.entry_id = auction.entry_id" );
        
$this->EE->db->where"exp_channel_titles.url_title"$url_title );            
    
}
    $this
->EE->db->order_by"bid_date desc" );        
    
$query $this->EE->db->get();
    
    
// If no results are found...
    
if( $query->num_rows() == {
        
// ... return the {if no_results} ... {/if} conditional
        
return $this->EE->TMPL->no_results;
    
}
    
    
// Put history data in an array and return the parsed the tag data
    
$data $query->result_array();
    
$tagdata $this->EE->TMPL->tagdata;
    return 
$this->EE->TMPL->parse_variables$tagdata$data );

 

Comments

I thought I had this working fine, but I’m actually running into a weird issue. The summary tag returns the correct bids, with the correct bid date and bid amount, but the member part is not working. It’s always showing the same member for each bid, no matter what tag I use - username, member_id, etc. Please help!

Posted by Matt on November 21, 2012

Scratch that last comment. Realize now the tag can’t be placed within the channel entries tag

Posted by Matt on November 21, 2012

Everyone knows you have done a great work? Can you add one more chapter to show history in the admin side.

Posted by Shiju S S on March 22, 2013

I love your tutorials.  EE and CodeIgniter have been a little difficult for me to pick up, but you know how to break everything down and explain what is going on very well, and in a way I can understand. 

Thanks for the tuts, I like your style, keep ‘um coming!

Posted by Robertsjr2000 on April 9, 2013

In case anyone is having trouble getting the bid amount to show, exp_auction.bid_amount needs to be included in the SELECT statement as well.

Also, is there a reason for using the “exp_” table prefixes in the SELECT statement and then not in the FROM or JOIN statements?

Cheers

Posted by Pseudoclass on April 15, 2013

could someone post a copy of the *complete* working module. As a Newb to EE I am not succeeding at getting it to work, and can not see where I am going wrong.

Many thanks !

Posted by Vince on April 26, 2013

Hi Vince,

I threw my module files up here for you to take a look at: https://github.com/matt-diehl/ExpressionEngine-auction

I have a small bit of extra (most likely poorly-written) code in there that returns a message if the bid is too low, so hopefully that doesn’t add any confusion. If you’d like the template code, I can probably throw that up as well.

P.S. EE-Recipes, I noted all credit should go to you, but if you’d prefer this not be posted on GitHub, I’m happy to oblige.

Posted by Matt on April 26, 2013

Hi Matt -  you are a gentleman ! Yup ... if you can throw up the templatye code as well then that would make life even better ! 
This is the ONLY tutorial on module development which is meaningful to a newb .. forget the EE tutorial !

Note to all Newbs:  I found the oversight in the tutorial code, which caused me to call for help. Chpt 5, “adding a form” - the template code is missing the entry_id which of course results in the TMP-> fetch_param to fail, the return =”“, and the form fails to appear.  I’ll post this on chpt 5 as well.

Many Thanks !!

Posted by Vince on April 27, 2013

Vince, I posted a sample template here:

https://github.com/matt-diehl/ExpressionEngine-auction/blob/master/examples/index.html

I won’t claim this is perfect by any means, but hopefully it’s helpful for you.

And here it is in action: http://bruunstudios.com/auction/flood

Posted by Matt on April 27, 2013

Outstanding Tutorial - Please Please add the chapter on the Admin CP.

Posted by vince on April 30, 2013

Hi - Does anyone have any tutorial resources from any author on how to build the CP backend ??? The EE docs are useless.

Many Thanks !

Posted by vince on May 2, 2013

+1 for an Admin CP chapter!

Posted by Matt on November 9, 2013

Just wanted to say that this tutorial has been incredibly valuable to me. I’d love to see more of this kind of content and would even be willing to pay for access if need be!

Posted by Jim Pannell on March 14, 2014

Great series of articles!

Posted by Greg on April 13, 2014

Add a comment

(Your email address will not be displayed on the site, but will be used for your gravatar)

Notify me of follow-up comments?