0

I'm not sure that i've written something intelligibile in the title either.

I'll try to explain with some codes line. First some information. I'm working with CakePhP and this problem comes up while creating the arrays for the actions allowed.

Long story short, i'm using an ACL to check whenever a page is loaded if the current user has access to the actions available on that page. This is an example:

//Controller
$role = $this->User->Role;
    $role->id = $this->Auth->user('Role.id');
    $actionsMenu = array();

    $actionsMenu['Files'] = array(
        'label' => 'Manage Files',
        'controller' => 'project_files',
        'action' => 'index',
        'parameters' => $id,
        'authorized' => $this->Acl->check($role, 'ProjectFiles')
    );
    $actionsMenu['Groups'] = array(
        'label' => 'Manage Groups',
        'controller' => 'groups',
        'action' => 'index',
        'parameters' => $id,
        'authorized' => $this->Acl->check($role, 'Groups')
    );

In the view I just loop and if the "authorized" is set to true, i'll print the related button.

Now, the problem rise when i've more that one parameter to pass. This is another snippet that follows the one up there:

//Controller [following]
$this->Project->id = $id;
    if ($this->Project->field('archived')) {
        $actionsMenu['Archiviation'] = array(
            'label' => 'Restore',
            'controller' => 'projects',
            'action' => 'archiviation',
            'parameters' => array($id, 0),
            'authorized' => $this->Acl->check($role, 'controllers/Projects/archiviation')
        );
    } else {
        $actionsMenu['Archiviation'] = array(
            'label' => 'Archive',
            'controller' => 'projects',
            'action' => 'archiviation',
            'parameters' => array($id, 1),
            'authorized' => $this->Acl->check($role, 'controllers/Projects/archiviation')
        );
    }

This is what you can find in the views:

//View
<div class="actions">
<h3><?php echo __('Actions'); ?></h3>
<ul>
    <li><?php echo $this->Html->link(__('<- Projects Management'), array('action' => 'index')); ?></li>
    <li>&nbsp;</li>
    <?php foreach($actionsMenu as $action) : ?>
        <?php if($action['authorized']) : ?>
            <li><?php echo $this->Html->link(__($action['label']), array('controller' => $action['controller'], 'action' => $action['action'],
                    is_array($action['parameters']) ? implode(', ', $action['parameters']) : $action['parameters']
                    )); ?></li>
        <?php endif; ?>
    <?php endforeach; ?>
</ul>

I thought the array format was the most CakePhP friendly way to pass the values just to discover that in case of multiple parameters, cake tend to prefer an associative array. The problem here is that CakePhP read that implode as a whole parameter composed by a string.

This is an example:

<!--HTML-->
<a href="/projects/archiviation/14%2C%200">Restore</a>

What I want to achieve is that the values separated by the comma should be read as different variables.

Honestly I never run in a situation like this and I've neither idea of what to look for on google to find something fitting (being a non-native english speaking isn't helping) so any suggestion is welcome.

Edit1

To clarify, the code listed in the second box (starting with Controller [following]) is the one that is causing problems.

The previous box just build the array with a single parameters that match the simple structure of CakePhP for building link but the second block will need to pass a second parameter. If the values was static one could simply type something like this:

//CakePhP HTML::Link
echo $this->Html->link(
'text of link',
array(
    'controller' => 'controller_name', 
    'action' => 'action_name',
    'parameter1', 'parameter2'
));

If I send the list of parameters as string, Cake are considering them a single parameter, reading it like (string)("'parameter1', 'parameter2'").

The same happens with the code i've written above in which i'm converting the array of values to string with implode().

So what I'm asking for, is if there a function, option or practice that I'm missing.

Edit2

As the user user221931 pointed out, the CakePhP function should support multiple parameters as array in the form of array('parameter1', 'parameter2', 'paramenterN').

So i've tried just removing the is_array() check and simply pass the value of $action['parameters']. The view section now look like this:

<?php echo $this->Html->link(__($action['label']), array(
                        'controller' => $action['controller'],
                        'action' => $action['action'],
                        //is_array($action['parameters']) ? implode(', ', $action['parameters']) : $action['parameters']
                        $action['parameters']
                        )); ?>

But i've got a warning as follows:

rawurlencode() expects parameter 1 to be string, array given

Going to open the context of the warning, seems like CakePhP is reading the information provided as follows:

$params = array(
    'controller' => 'projects',
    'action' => 'archiviation',
    'plugin' => null,
    'pass' => array(
        (int) 0 => array(
            (int) 0 => '1',
            (int) 1 => (int) 1
        )
    ),
    'named' => array()
)

Honestly I'm lost here.

I've tried changing the second value of the array to a string too and passing an associative array instead of a numeric just to try something obvious but the error persist and the link comes out truncated without parameters.

2
  • Can you give an example of exactly what you're trying to achieve for a given set of data? Commented Jan 6, 2015 at 11:53
  • I've added some clarification (I hope) to the question Commented Jan 6, 2015 at 15:03

1 Answer 1

1

The correct format to use Html::link()

echo $this->Html->link(
    'text of link',
    array(
        'controller' => 'users', //Or any controller name
        'action' => 'view', //Or any action
        1, //Several parameters
        'test1', //go here
        'test2'
    )
);

If you don't know the number of parameters beforehand, you only need to array_merge your fixed array with the array of dynamic parameters.

Assuming $arrayOfParameters holds array('test1', 'test2', 'test3')

$urlArray = array_merge(
    array('controller' => 'users', 'action' => 'view'),
    $arrayOfParameters
);

echo $this->Html->link('text of link', $urlArray);

Additionally you could implode your array of parameters as a url, i.e:

$urlString = implode('/', $arrayOfParameters); //creates a string 'test1/test2/test3'

    echo $this->Html->link('text of link', array(
        'controller' => 'users',
        'action' => 'view',
        $urlString //One parameter that will be looking as many
    ));
Sign up to request clarification or add additional context in comments.

6 Comments

My first version had the values passed has an array but it didn't work. Maybe I just mistyped something. I'll try again later and eventually curse myself for being such an idiot.
I tried just passing the array as is, array($id, 0) for example, but got an error. I'm going to update the question for the sake of readability.
I updated my answer for the correct way to do it, which I tested in a fresh application. If this doesn't work for you in your original code, please try a fresh project and see if it does. You might have changed your routes or added something else.
Yes, that's how it works. But if I've the number of parameters to be dynamic the only way to to that is with a loop. The problem in which I run and tried to explain was: How i'm going to write 1, 'test1', 'testN' in a way that PhP understand that it's part of the functions? The problem is that to build the parameters in that way i've to print the comma too, but the interpreter have to understand that the comma is not part of the values but a parameter's separator.
Ok, so you want dynamic url parameters. That's all you should have said instead of 2 scroll downs of information. There are two ways, I'll be updating my answer.
|

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.