We use cookies to improve your experience. No personal information is gathered and we don't serve ads. Cookies Policy.

ExpressionEngine Logo ExpressionEngine
Features Pricing Support Find A Developer
Partners Upgrades
Blog Add-Ons Learn
Docs Forums University
Log In or Sign Up
Log In Sign Up
ExpressionEngine Logo
Features Pro new Support Find A Developer
Partners Upgrades
Blog Add-Ons Learn
Docs Forums University Blog
  • Home
  • Forums

Help with plugin please? - Having trouble with a loop - I think?

Development and Programming

Mark Bowen's avatar
Mark Bowen
12,637 posts
17 years ago
Mark Bowen's avatar Mark Bowen

Hi there,

Just wondering if anyone could help me with a little something here. I suppose I had best explain what I am trying to do first and then I will show what I have so far.

I have a need for an exceptionally (and I do mean exceptionally) simple shopping cart. The way it will work is that entry_ids of items will get added to a session variable with pipe (|) characters between them. I am pretty sure I have this bit covered.

I then have this in a template :

{exp:shopping_cart parse="inward"}

{exp:weblog:entries weblog="default_site" entry_id="{entry_ids}"}
<h3>{title}</h3>
{embed="tests/shopping-cart-prices" entry_id="{entry_id}"}
{qty}
{/exp:weblog:entries}

{/exp:shopping_cart}

This is then the code for the shopping_cart plugin :

pi.shopping_cart.php

<?php

$plugin_info = array(
    'pi_name'            => 'Shopping Cart',
    'pi_version'        => '1.0.0',
    'pi_author'            => 'Mark Bowen',
    'pi_author_url'        => 'http://www.markbowendesign.com/',
    'pi_description'    => 'Simple shopping cart',
    'pi_usage'            => Shopping_cart::usage()
);


class Shopping_cart {
    var $return_data = '';

    function Shopping_cart()
    {

        global $TMPL, $DB, $SESS, $FNS;        
        $tagdata = $TMPL->tagdata;
        $ids = "11|12|13|11";
        $entry_ids = explode("|", $ids);
        $unique_ids = array_unique($entry_ids); 

        foreach ($unique_ids as $entry_id)
        {
        $output .= $entry_id.'|';
        }
        $tagdata = $TMPL->swap_var_single('entry_ids', $output, $tagdata);
        $this->return_data = $tagdata;

    }

// ----------------------------------------
//  Plugin Usage
// ----------------------------------------
function usage()
{
ob_start(); 
?>




<?php
$buffer = ob_get_contents();
    
ob_end_clean(); 

return $buffer;
}
// END
}
?>

At the moment the $ids=”11|12|13|11” variable is acting as though it is my session variable just for testing purposes. What I want to do is to take each unique entry_id from that variable and :

1 - Use it to power the weblog tag to spit out the entries title and any other information and, 2 - Spit out the cost of the item, quantity added and total cost

Part 1 of the above is working as I am using the $unique_ids = array_unique($entry_ids) part to get rid of any duplicate values and these then get passed inward to the weblog tag enabling me to get at any information stored in the particular weblog entry. I then have the {embed="tests/shopping-cart-prices" entry_id="{entry_id}”} and the code for that template which has this :

{exp:simple_commerce:purchase entry_id="{embed:entry_id}" success="site/success" cancel="site/index"}
<strong>{item_sale_price}</strong>
{/exp:simple_commerce:purchase}

so that I can retrieve the cost of the item and show that on the screen. This is all working fine but I was hoping that instead of embedding a template I could do all of this within my plugin using DB queries.

I tried just getting the cost back by placing a database query to find out the item_regular_price from the exp_simple_commerce_items table by placing the query inside the

foreach ($unique_ids as $entry_id)

part of my code above but I could never get it to swap the variable in my template - {cost} with each different cost. It would just use the last (or was it first) cost and place it in for all items.

I then have the problem of quantity, sub-total and total.

Clearer question 😉 To re-iterate and to probably put things a lot easier as I probably haven’t really explained myself all that well in simplest terms what I have is this :

1 - A session variable which holds the entry_ids of items that have been added to the cart. $ids=”11|12|13|11”. This would mean two of item 11, one of item 12 and one of item 13. I do already have this session variable and I can get items added to it so that bit is more or less covered - haven’t figured how to minus an item but I will figure that out for myself.

I then want to take each of these entry_ids and first of all use them within the enclosed weblog tag (this is working at the moment - can’t believe I even got that far 😉 ) to spit out the item information.

Then I want to have {cost}, {qty} and {total} variables within the weblog tag that I can exchange using the swap_var_single. The {cost} variable will simply be the item_regular_price. The {total} will only show the once (just can’t get my head around how to do that one but I suppose it would be great if I could use the {if count == total_results} conditional in the weblog to get that one, I just haven’t been able to figure that out at all yet!) and then the {qty} variable would just be however many times the entry_id appeared in the $ids=”11|12|13|11” session variable.

Putting all of this together though is proving a lot more harder than I thought. I can see in my mind what I want to do but getting it into code is proving quite difficult. I am quite proud of how far I have got so far but really could do with a helping hand to get the rest of the distance in my journey.

Thanks for any help on this.

Best wishes,

Mark

       
Mark Bowen's avatar
Mark Bowen
12,637 posts
17 years ago
Mark Bowen's avatar Mark Bowen

Okay,

Reading back through this it even has me confused 😉 so thought I would try to bring it down to the absolute basics in case anyone wants to lend a hand.

What I would like is something like this :

Session variable holding the following data - “11|12|13|11”. These are just entry_id’s which will then be passed into the weblog entry below :

Template Code

{exp:shopping_cart parse="inward"}

{exp:weblog:entries weblog="default_site" entry_id="{entry_ids}"}
<h3>{title}</h3>
{cost}
{qty}
{sub_total}
{total}
{/exp:weblog:entries}

{/exp:shopping_cart}

Not sure if the parse=”inward” is needed for what I want though.

So basically each unique entry_id from the session variable will be sent to the weblog tag which will allow me to spit out the item details and then from within my plugin I want to find out the price of the item which is stored in the Simple Commerce table and swap out that information with the {cost} variable which is between the weblog tags. The {total} I guess would be handled with something like :

{if count == total_results}
{total}
{/if}

which would allow the total to only show the once. If there’s a better way of doing this then would love to know. The {qty} and {sub_total} variables would come from somehow finding out how many of each entry_id there were in the session variable so in the case above :

11|12|13|11

this would spit out a quantity of 2 for entry_id 11 and 1 for the other entries. Inside the plugin I can then just times the quantity by the cost to get the sub_total amount.

Hopefully this has explained what I am after a little better? 😉

Hope someone can help on this if at all possible.

Thanks in advance.

Best wishes,

Mark

       
Mark Bowen's avatar
Mark Bowen
12,637 posts
17 years ago
Mark Bowen's avatar Mark Bowen

Hi again,

Just having another thought about this I’m wondering now do I have my plugin wrapped in the right way. At the moment I have this :

{exp:shopping_cart parse="inward"}

{exp:weblog:entries weblog="default_site" entry_id="{entry_ids}"}
<h3>{title}</h3>
{cost}
{qty}
{sub_total}
{total}
{/exp:weblog:entries}

{/exp:shopping_cart}

Maybe perhaps it should be this instead ?

{exp:weblog:entries weblog="default_site" entry_id="{entry_ids}"}

{exp:shopping_cart parse="inward"}
<h3>{title}</h3>
{cost}
{qty}
{sub_total}
{total}
{/exp:shopping_cart}

{/exp:weblog:entries}

Again not sure I would need the parse=”inward” bit now though

My thinking is because at the moment it seems to me like all the weblog entry_ids are being sent into the weblog tag at once and I don’t think that it is actually using my plugin each time. I’m really not too sure either way but would love it if someone could just let me know which way would be best to go about all of this.

Any help would be really appreciated on this one.

Best wishes,

Mark

       
gridonic's avatar
gridonic
231 posts
17 years ago
gridonic's avatar gridonic
{exp:weblog:entries weblog="default_site" entry_id="{entry_ids}"}

{exp:shopping_cart parse="inward"}
<h3>{title}</h3>
{cost}
{qty}
{sub_total}
{total}
{/exp:shopping_cart}

{/exp:weblog:entries}

Hi Mark, I don’t think you can use this like this, because the {entry_ids} part has to be in between your plugin tags looking at the source.

Did you have a look at the weblog entries tag hooks to manipulate / add variables or functions to the weblog entries tag?

http://expressionengine.com/developers/extension_hooks/weblog_entries_tagdata http://expressionengine.com/developers/extension_hooks/weblog_entries_tagdata_end

       
Mark Bowen's avatar
Mark Bowen
12,637 posts
17 years ago
Mark Bowen's avatar Mark Bowen

Hiya,

Thanks for the links. Oops with the code that I showed above it should have been more like this :

{exp:weblog:entries weblog="default_site"}

{exp:shopping_cart}
<h3>{title}</h3>
{cost}
{qty}
{sub_total}
{total}
{/exp:shopping_cart}

{/exp:weblog:entries}

I was thinking that (there aren’t going to be all that many products / items anyway) that I could have the weblog tag which will try to spit out all the entries but then the plugin will only allow the entry to be spat out if certain conditions are met - the condition being if the current entry_id that the weblog tag is trying to spit out is actually stored in the session variable.

Would that be at all possible?

Regarding the links you show above they would be for use in an extension wouldn’t they? Unfortunately I’ve never really had any luck at all with extensions as it really does all go over my head. Do you have any pointers as to how I would go about doing this with those then?

Thanks for all the help you have been giving me lately, all very much appreciated.

Best wishes,

Mark

       
Mark Bowen's avatar
Mark Bowen
12,637 posts
17 years ago
Mark Bowen's avatar Mark Bowen

Okay then another question if I may? 😉

I just made a very very quick plugin and exceptionally simple where basically I am going to spit out everything I need just using the plugin, no usage of the weblog tag for now. Something like this :

{exp:shopping_cart}
{replace_me}
{replace_me_too}
{/exp:shopping_cart}

The code for the plugin is :

<?php

$plugin_info = array(
    'pi_name'            => 'Shopping Cart',
    'pi_version'        => '1.0.0',
    'pi_author'            => 'Mark Bowen',
    'pi_author_url'        => 'http://www.markbowendesign.com/',
    'pi_description'    => 'Simple shopping cart',
    'pi_usage'            => Shopping_cart::usage()
);


class Shopping_cart {
    var $return_data = '';

    function Shopping_cart()
    {

        global $TMPL;
        $ids = "11|12|13|11";
        $entry_ids = explode("|", $ids);
        $unique_ids = array_unique($entry_ids);

        foreach ($unique_ids as $entry_id)
        {
        $tagdata .= $TMPL->tagdata;
        $tagdata = $TMPL->swap_var_single('replace_me', $entry_id, $tagdata);
        $tagdata = $TMPL->swap_var_single('replace_me_too', $entry_id, $tagdata);
        }
        $this->return_data = $tagdata;

    }


// ----------------------------------------
//  Plugin Usage
// ----------------------------------------
function usage()
{
ob_start(); 
?>





<?php
$buffer = ob_get_contents();
    
ob_end_clean(); 

return $buffer;
}
// END
}
?>

At the moment as you can see all this will do is output :

11
12
13

to the html.

The question I have with this is simply : I have placed the $tagdata .= $TMPL->tagdata; within the foreach loop. Is this okay to do? The only reason I ask is because otherwise I could only get the plugin to throw out one set of information 11 and the others were I guess lost in the ether 😉

I know that I need to loop over them to get them to spit out correctly and as far as I can tell this is working fine. I just ask as I just want to see if this can be done in a better way but still get me the same result?

Secondly, I’m pretty sure it’s possible as I have seen it in the documentation where I have my :

$tagdata = $TMPL->swap_var_single('replace_me', $entry_id, $tagdata);
$tagdata = $TMPL->swap_var_single('replace_me_too', $entry_id, $tagdata);

I guess that there is a quicker way than me writing out each single variable each time. I tried to get my head around the documentation on that one but was a little confused. I think I may be able to get it hopefully though but just thought I would ask in case there is an easy way for it to be explained to me. I think I got so hung up on getting this bit to work (hopefully it is okay to do it the way I have done?) that everything else just flew over my head!!

Once I know that what I am doing here is okay to do, I mean placing the :

$tagdata .= $TMPL->tagdata;

within the foreach loop then I will get onto figuring out how to get at all my variables without my having to write them out each time (unless someone knows an easy way to explain that to me - I don’t want the code given to me I would rather do that myself but just need to understand it all first 😉 ).

After that I do have another question which I can’t get my head around at all but that can wait for another time 😉

Thanks again for any help on this it really is very much appreciated.

Best wishes,

Mark

       
Mark Bowen's avatar
Mark Bowen
12,637 posts
17 years ago
Mark Bowen's avatar Mark Bowen

Okay one more question if I may? 😉

How do you go about spitting out a count variable from within a plugin?

Say I want something like this :

{exp:shopping_cart}
{count}
{/exp:shopping_cart}

Let’s just say for now that the plugin spits this out to the page :

1
2
3

What I would like to be able to do is something like this :

{exp:shopping_cart}
{count}
{if count == "3"}
This was the last item
{/if}
{/exp:shopping_cart}

so that I get :

1
2
3
This was the last item

Anyone any ideas at all?

Thanks.

Best wishes,

Mark

       
Daniel Walton's avatar
Daniel Walton
553 posts
17 years ago
Daniel Walton's avatar Daniel Walton
global $FNS, $TMPL;

// Items (read whatever) I want to loop through on my template
$items_to_process = array(
    array(
        'item_id'    => '10',
        'item_name'    => 'Item One'
    ),
    array(
        'item_id'    => '56',
        'item_name'    => 'Some Item'
    ),
    array(
        'item_id'    => '73',
        'item_name'    => 'Oops'
    ),
);

$total_results = count($items_to_process);
$count = 1;
$tagdata = $TMPL->tagdata;
$output = '';

foreach($items_to_process AS $vars)
{
    // Add some specific variables to the vars array
    $vars['total_results'] = $total_results,
    $vars['count'] = $count


    // Make a 'floating' copy of tagdata, so that we don't overwrite it
    $temp = $tagdata;

    // Iterate each 'var' and replace it on our floating copy
    foreach($vars AS $var => $val)
    {
        $temp = $TMPL->swap_var_single($var, $val, $temp);
    }

    // Parse the conditionals, using our vars, ready for the template parser
    $temp = $FNS->prep_conditionals($temp, $vars);

    // Append our floating copy to the output string
    $output .= $temp;

    // Increment count
    $count++;
}

return $output;

Note, without checking I cannot remember the argument order for $FNS->prep_conditionals(), so, if the above doesn’t work it may just be that you need to swap the two variables around.

       
Mark Bowen's avatar
Mark Bowen
12,637 posts
17 years ago
Mark Bowen's avatar Mark Bowen

Hiya,

Sorry for the bump but was just wondering if some kind soul could help me out on this one at all?

With my last post it may have looked like I just wanted to find out the last item but that definitely isn’t the case. I simply would like to be able to have a count variable sent along with each set of data that I spit out.

If I spit out a count variable using :

$tagdata = $TMPL->swap_var_single('count', $count, $tagdata);

then I can use this if I do this :

{if "{count}" == "3"}
Content here for third data set
{/if}

but I know that this is not the correct thing to do. Any help with getting a conditional into my plugin would be great thanks. I have done conditionals before but really only single ones such as :

{if this_is_true}
Do this
{if:else}
Do this instead
{/if}

but that is just a single conditional, what I really really need is a count.

Thanks for any help on this. I did take a look into the mod.query.php file and found this code :

foreach ($query->result as $count => $row)
{
$tagdata = $TMPL->tagdata;

$row['count']            = $count+1;
$row['total_results']    = $total_results;

/** ----------------------------------------
/**  Conditionals
/** ----------------------------------------*/
        
$tagdata = $FNS->prep_conditionals($tagdata, $row);

Hope it’s okay to show this code as it doesn’t give too much of the core code away I hope? If not then please do feel free to delete that part.

I think this might be doing the kind of thing I want but not entirely certain. Any help with this would be greatly appreciated.

Best wishes,

Mark

       
Daniel Walton's avatar
Daniel Walton
553 posts
17 years ago
Daniel Walton's avatar Daniel Walton

Mark, see my above code.

The outer loop merely goes through each ‘set of data’. These sets of data are each of the 3 arrays within the items_to_process array.

Right at the start you can see i’m adding the current ‘count’ to the individual item array ‘$vars’, in addition to the total results.

So, each time the outer loop iterates we have this in $vars: ‘item_name’ => ‘Blah..’ ‘item_id’ => ‘Etc..’ ‘count’ => ‘Foo’ ‘total_results’ => ‘Bar’

The benefit of adding all of our variables that we want available to the template into a single array ($vars) is that we can simply loop through this array inside of the outer loop, swapping them out programmatically rather than individually.

One thing you might need to watch out for is that the variable ‘count’ and ‘total_results’ may conflict with the other modules/plugins that you use your plugin alongside. SO perhaps prefix all of your variables with ‘myplugin_’.

You could do this in one fell swoop, after you have finished adding elements to your vars array, like so:

reset($vars);
while(list($key, $val) = each($vars))
{
    $vars['myplugin_'.$key] = $val;
    unset($vars[$key]);
}

Leaving you with:

‘myplugin_item_name’ => ‘Blah..’ ‘myplugin_item_id’ => ‘Etc..’ ‘myplugin_count’ => ‘Foo’ ‘myplugin_total_results’ => ‘Bar’

Which is alot less likely to conflict with other processes.

After the template variables have all been swapped around, you can see that the floating data is sent off to prep_conditionals along with the vars array, meaning that all of the variabels you made available to your template, are also available to be used in conditionals.

Are you still stuck?

       
Mark Bowen's avatar
Mark Bowen
12,637 posts
17 years ago
Mark Bowen's avatar Mark Bowen

Hi Daniel,

Oops sorry I think I must have been posting my last post at the time that you had posted the one you have shown above my last post so I missed it. Will look over what you have posted.

Thanks ever so much for helping out on this one. Will let you know how I get on. The help is really appreciated on this one, thanks.

Best wishes,

Mark

       
Mark Bowen's avatar
Mark Bowen
12,637 posts
17 years ago
Mark Bowen's avatar Mark Bowen

Hi Daniel,

I think I must be thick or something, have been trying this code out all day but just keep on getting errors and nothing is working. I think I can see what you are doing but it just won’t work for me. I have tried moving items around, re-naming them and all sorts but I just keep on getting errors.

My code so far is :

<?php
$plugin_info = array(
    'pi_name'            => 'Shopping Cart',
    'pi_version'        => '1.0.0',
    'pi_author'            => 'Mark Bowen',
    'pi_author_url'        => 'http://www.markbowendesign.com/',
    'pi_description'    => 'Simple shopping cart',
    'pi_usage'            => Shopping_cart::usage()
);


class Shopping_cart {
    
    var $return_data = '';

    function Shopping_cart()
    {
    global $TMPL, $DB, $SESS, $FNS;        

    // Items (read whatever) I want to loop through on my template
    $items_to_process = array(
        array(
            'item_id'    => '10',
            'item_name'    => 'Item One'
        ),
        array(
            'item_id'    => '56',
            'item_name'    => 'Some Item'
        ),
        array(
            'item_id'    => '73',
            'item_name'    => 'Oops'
        ),
    );

    $mb_total_results = count($items_to_process);
    $mb_count = 1;
    $tagdata = $TMPL->tagdata;
    $mb_output = '';
    $vars = '';
    $val = '';

    foreach($items_to_process as $vars)
    {
        // Add some specific variables to the vars array
        $vars['mb_total_results'] = $mb_total_results;
        $vars['mb_count'] = $mb_count;
    
    
        // Make a 'floating' copy of tagdata, so that we don't overwrite it
        $temp = $tagdata;
    
        // Iterate each 'var' and replace it on our floating copy
        foreach($vars as $var => $val)
        {
            $temp = $TMPL->swap_var_single($var, $val, $temp);
        }
    
        // Parse the conditionals, using our vars, ready for the template parser
        $temp = $FNS->prep_conditionals($vars, $temp);
    
        // Append our floating copy to the output string
        $mb_output .= $temp;
    
        // Increment count
        $mb_count++;
    }
    
    return $mb_output;
    
    }


// ----------------------------------------
//  Plugin Usage
// ----------------------------------------
function usage()
{
ob_start(); 
?>





<?php
$buffer = ob_get_contents();
    
ob_end_clean(); 

return $buffer;
}
// END
}
?>

Unfortunately if I place the {item_id}, {item_name}, {mb_count} or {mb_total_results} into a template between the plugin tags I just get errors. The latest ones being :

Notice: Array to string conversion in /Applications/MAMP/htdocs/eecart/admin/core/core.functions.php on line 2538 Warning: preg_match_all() expects parameter 2 to be string, array given in /Applications/MAMP/htdocs/eecart/admin/core/core.functions.php on line 2561 Notice: Array to string conversion in /Applications/MAMP/htdocs/eecart/admin/core/core.functions.php on line 2538 Warning: preg_match_all() expects parameter 2 to be string, array given in /Applications/MAMP/htdocs/eecart/admin/core/core.functions.php on line 2561 Notice: Array to string conversion in /Applications/MAMP/htdocs/eecart/admin/core/core.functions.php on line 2538 Warning: preg_match_all() expects parameter 2 to be string, array given in /Applications/MAMP/htdocs/eecart/admin/core/core.functions.php on line 2561

Not really too sure what I am doing wrong now?

Sorry about all of this but was just wondering if you had any time to see what I am doing wrong?

Thanks again for any help you can spare on this.

Best wishes,

Mark

       
Daniel Walton's avatar
Daniel Walton
553 posts
17 years ago
Daniel Walton's avatar Daniel Walton

As I stated, I wasn’t sure which order the parameters are intended for the prep_conditionals function.

If you just swap “$temp = $FNS->prep_conditionals($vars, $temp);” for “$temp = $FNS->prep_conditionals($temp, $vars);” (I did stealth edit my original snippet) 😊

       
Mark Bowen's avatar
Mark Bowen
12,637 posts
17 years ago
Mark Bowen's avatar Mark Bowen

Hi Daniel,

Thanks for the update. I think I must still have something wrong somewhere though as now that has got rid of the errors but all I get now is a blank template when I view it. I have this code in the template :

{exp:shopping_cart}
Item ID - {item_id}
Item Name - {item_name}
<hr >
Count - {mb_count}
Total Results - {mb_total_results}
Count - {mb_count}
{if mb_count == "2"}
This is the second item
{/if}
{/exp:shopping_cart}

Do I have the wrong names for the variables? I thought that they would be {item_id}, {item_name}, {mb_count} and {mb_total_results}? I’m probably just doing something silly here and have gone too deep into the code and am now just missing the wood for the trees or something though? 😉

Thanks for your help on this though. I’m sure you’ll get me there in the end 😉 😊 😉

Best wishes,

Mark

       
Daniel Walton's avatar
Daniel Walton
553 posts
17 years ago
Daniel Walton's avatar Daniel Walton

Lets debug a little, see what’s going on. Why not print_r($vars) somewhere in the main loop?, this will show you what the inner loop is working through (and sending off to swap_var_single).

       
1 2

Reply

Sign In To Reply

ExpressionEngine Home Features Pro Contact Version Support
Learn Docs University Forums
Resources Support Add-Ons Partners Blog
Privacy Terms Trademark Use License

Packet Tide owns and develops ExpressionEngine. © Packet Tide, All Rights Reserved.