5

I'm creating a module for a website, and to get the module parameters I do something like this:

//-- Get a parameter from the module's configuration
$company1_enable = $params->get('company1_enable');
$company1_name = $params->get('company1_name');
$company1_logo = $params->get('company1_logo');
$company1_image = $params->get('company1_image');
$company1_description = $params->get('company1_description');

But this module must support ~40 companies, meaning I would have to repeat this code 40 times, only changing the number after "company" ($company2_enable = $params->get('company2_enable');, $company3_enable = $params->get('company3_enable'); etc. )

Is there any way to use a loop on the $params object in order to do this more effectively?

4
  • Is there a separate (duplicate of the) module for each company? Or do you have 40 input fields in the options, 1 for each company?
    – Lodder
    May 13, 2015 at 16:00
  • It's a single module with 40 sets of fields (enable, name, logo, image, description for each company). Not very user friendly, I admit, but it's not for JED...
    – johanpw
    May 13, 2015 at 16:05
  • To be honest, in the end, you're still going to have to call the variable for each parameter, so unless you're going to be using the variable more than once, you could simply call them as they are, rather than defining them. Having said that, are you planning on looping through each company and display the data for each one (same display structure for each one)?
    – Lodder
    May 13, 2015 at 16:11
  • Actually, I use a loop to call the parameters: <?php for ($i = 1; $i < 40; $i++) { if (${'company' . $i . '_enable'} === "1") { /* do something up to 40 times */ }}. Maybe I'll end up getting the parameters manually for now, I'm just curious to see if there's a better way to handle many parameters.
    – johanpw
    May 13, 2015 at 16:14

3 Answers 3

4

I'll go a little more in-depth with the repeatable form fields method.

Firstly, I would use 1 repeatable form field for all names, another for all logos and so on. So here would be the form field for the company name:

<field 
    name="company_name" 
    type="Repeatable" 
    icon="list" 
    label="Company Name"
    default='{"name":["Company 1", "Company 2", "etc.."]}'>
    <fields name="params">
        <fieldset hidden="true" name="company_name_modal" repeat="true">
            <field name="name"
                label="Image"
                type="text" />
        </fieldset>
    </fields>
</field>

In your helper.php, add the following to go through the json encoded form fields:

class ModMyModuleHelper
{
    public function group_by_key($array) 
    {
        $result = array();

        foreach ($array as $sub) 
        {
            foreach ($sub as $k => $v) 
            {
                $result[$k][] = $v;
            }
        }
        return $result;
    }    
}

In your mod_mymodule.php file, you will need to call the helper and the function, like so:

require_once dirname(__FILE__) . '/helper.php';

$helper = new ModMyModuleHelper;

// Get names
$json_names = $params->get('company_name');
$names      = $helper->group_by_key( json_decode($json_names, true) );

Then in your default.php, you can add your foreach loop:

foreach ($names as $index => $value) 
{                   
    echo '<p>' . $value[0] . '</p>';
}

I kind of prefer this method as you only need to duplicate the code for the company logo, image and description, rather than 40 times (for each individual company).

Hope this helps in some way, shape, or form

9
  • 1
    Great explanation of repeatable fields. I ended up doing something similar based on your code. But I disagree on using separate repeatable fields for names, logos, etc. It would be to complicated to keep the fields synchronized (would you remember what company you added at line #33 when trying to add the corresponding logo...?)
    – johanpw
    May 30, 2015 at 0:43
  • I have read this with interest as I'm doing something similar, but i am grouping all of the fields together. Would this be possible? I assume using the example you could add more <field>s to the <fieldset>. I also am using a repeatable subform as I felt this was better than creating a modal as it's an extra click. Is there an advantage of using one over the other?
    – Eoin
    Dec 5, 2017 at 23:27
  • 1
    @Eoin The newer subform fields are somewhat more flexible and stable. I believe the issue with the older form fields was opening a modal within a modal, for example a repeatable form that had a "media" field (which opens a modal). Personally I prefer the old repeatable fields. I prefer having a modal as opposed to all the options taking up a tonne of space on the page, so I ended up forking them and shipping it with my own extension. Repeatable fields will be removed in J4, so I'd probably suggest starting with subform fields.
    – Lodder
    Dec 6, 2017 at 0:26
  • 1
    @Eoin - The code above probably won't work in J4 as repeatable form fields have been removed in J4 ;) I'll setup some subform fields tonight if I get time and try to answer your new question
    – Lodder
    Dec 6, 2017 at 16:44
  • 1
    @Eoin - The serve the same purpose but are 2 different scripts. Glad it's working on J4 though :)
    – Lodder
    Dec 7, 2017 at 11:29
3

if you using joomla 3.2+ you can use repeatable field or if you are using 3.1 and older it's recommended to create your own field contains array of fields.

so you end up with $params->get('company'); and this will be returning whole set for companies.

1
  • 1
    Even though repeatable form field were introduced in J3.2, I would not recommend using them unless you're running J3.4, where some bugs were fixed.
    – Lodder
    May 13, 2015 at 23:02
3

I would like to preface this answer with the statement this is not the ideal solution for storing and retrieving a dynamic list of parameters. The "proper" way would be to use a custom table in your Joomla database.

To answer your question, if you know the number of companies the way to utilize a loop to retrieve your params would be like so:

$companies = array();
$company_count = 40;

for ($i = 1; $i <= $company_count; $i++)
{
    $companies[$i] = (object) array(
        'enable' => $params->get('company' . $i . '_enable', null);
        'name' => $params->get('company' . $i . '_name', null);
        'logo' => $params->get('company' . $i . '_logo', null);
        'image' => $params->get('company' . $i . '_image', null);
        'description' => $params->get('company' . $i . '_description', null);
    );
}

//Access company information by index from 1 to 40  
$companies[1]->enable;
$companies[1]->name;
$companies[1]->logo;
$companies[1]->image;
$companies[1]->description;

If you don't know the number of params, things get a little more complicated. You would need to use a a do...while loop checking for a null result being returned:

$companies = array();
$continue = true;
$count = 0;

do
{
    $count++;
    $company = (object) array(
        'enable' => $params->get('company' . $count . '_enable', null);
        'name' => $params->get('company' . $count . '_name', null);
        'logo' => $params->get('company' . $count . '_logo', null);
        'image' => $params->get('company' . $count . '_image', null);
        'description' => $params->get('company' . $count . '_description', null);
    );

    if (empty($company->enable)
    {
        $continue = false;
    }
    else
    {
        $companies[$count] = $company;
    }

} while ($continue)

I have not tested any of the code, but the core concepts are there. I would HIGHLY suggest taking Lanah's advice and using the repeatable field if your using version 3.4.x or create and use a custom database table if your version is lower.

Good luck!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.