-1

I have a private function to return an array of options, those options indicate a callback and other options such as template, form, etc. Here the code:

  /**
         * @return array
         */
        private function options()
        {

            $options = [
                'general'       => [
                    'form'           => GeneralConfigType::class,
                    'template'       => 'general.html.twig',
                    'title'          => 'Configuración General',
                    'ignoreFields'   => ['slider', 'social'],
                    'uploadedFields' => [],
                    'callbacks'      => ['generalData']
                ],
                'business'      => [
                    'form'           => ConfigurationType::class,
                    'template'       => 'business.html.twig',
                    'title'          => 'Configuración de Empresa',
                    'ignoreFields'   => [],
                    'uploadedFields' => ['image','favicon','login_icon','sidebar_icon'],
                    'callbacks'      => ['businessImage']
                ],
      ];

            return $options;
}

Now here is my doubt, in addition to indicate the function you have to execute in the key callback, Can I pass on the variables I'm going to need in that callback? I've tried several ways and they haven't worked.

Example:

Before:

'callbacks'      => ['generalData']

After:

In this example I'm assigning the '$', but I could do it if the only string, I'm just looking for a way to pass to the callback the variables it needs and no more.

'callbacks'      => ['generalData' => '$configurationData, $configuration, $form, $request']

And this code would be where everything would be executed in other method:

    if (!empty($options[ 'callbacks' ])) {
       foreach ($options[ 'callbacks' ] as $callback => $variables) {
          $this->$callback($variables);         
       }           
    }
jcarlosweb
  • 846
  • 1
  • 14
  • 30

3 Answers3

1

If I understand you correctly, you want to store the name of the variable in the array of options and then use that variable in the callback function.

When I've done this type of thing, I find it easier to just store the variable name as text and leave out the $ from the name stored in the array. I then use a variable variable when retrieving it.

Either way, I think you need a little more code on the execution side. One more loop:

if (!empty($options[ 'callbacks' ])) {
   foreach ($options[ 'callbacks' ] as $callback => $variables) {
       foreach($variables as $variable){ // extra loop to get the variables
           $this->$callback[$$variable];
           // This is where it gets tricky, and depends on how you wish to format.  
           // The variables are currently part of an array, thus the array notation 
           // above.  By using the stored name only, and a variable variable, you 
           // should be able to get to the var you need
      }         
   }           
}
Watercayman
  • 7,970
  • 10
  • 31
  • 49
  • Yes, I can do that store the variables without the "$", but in the example you give me I'm running the callback as many times as I have variable and I only want to run it once, I try to do with my problem/question, is to try to pass to the callback only the variables it needs. – jcarlosweb Jan 06 '19 at 11:48
0

@jcarlosweb, what you need to do is very simple. The short answer is that it can be done using the [call_user_func_array()][1] method.

In the context of your example, the callbacks could be rearranges in the following way ...

'callbacks'      => ['generalData' => [$configurationData, $configuration, $form, $request]

Basically, the array keys will be the name of the function to call, and the corresponding array values will be a array of the values of each parameter that is accepted but the callback function. Doing it this way is important because you need to capture the value of the parameters while they are in scope. And this will avoid using eval().

Using the callbacks can be as simple as ...

$options = options();
foreach ($options['callbacks'] as $callback => $params) {
    $result = call_user_func_array($callback, $params);
    // Do something with $result if necessary
}
asiby
  • 3,229
  • 29
  • 32
  • The problem with this is that those variables are not declared in the options are declared in where I call the callback. – jcarlosweb Jan 06 '19 at 11:41
0

I finally got it with the function compact http://php.net/manual/en/function.compact.php

Here's the code:

First I select the variables I need in my options:

'callbacks' => ['businessImage' => ['configurationData', 'configuration', 'form', 'request']]

Second I call the variables with compact, but I had to use extract here because if I didn't configurationData variable wasn't modified, which I don't understand since I had previously referenced it.

if (!empty($options[ 'callbacks' ])) {
       foreach ($options[ 'callbacks' ] as $callback => $variables) {
           $variables =  compact($variables);
           $this->$callback($variables);
           extract($variables);
      }
 }

Third callback applied and referenced:

/**
 * @param array $params
 * @return array $configurationData
 */
private function businessImage(&$params)
{
    extract($params,EXTR_REFS);

    // more code here ......

    $configurationData[ "image" ]   = $originalImageName;
    $configurationData[ "favicon" ] = $originalFaviconName;
    $configurationData[ "login_icon" ] = $originalLoginIconName;
    $configurationData[ "sidebar_icon" ] = $originalSidebarIconName;


    return $configurationData;
}

This works correctly in my website, but as I said before I do not understand why I have to call back the function extract, if I have already passed it referenced in the same callback as you see in my last code.

jcarlosweb
  • 846
  • 1
  • 14
  • 30