1

I am trying to pass datetime variables into my exportcsv method to generate .csv file with data from indicated time period.

Both variables are associative arrays that look like this:

[
 'beginning' => [
    'year' => '2016',
    'month' => '06',
    'day' => '23',
    'hour' => '11',
    'minute' => '15'
  ],
  'end' => [
    'year' => '2016',
    'month' => '06',
    'day' => '29',
    'hour' => '11',
    'minute' => '15'
   ]
]

When I try to pass variables I get an error with this message (yep, I've got the same two warnings):

Warning (2): rawurlencode() expects parameter 1 to be string, array given [CORE\src\Routing\Route\Route.php, line 574]

Warning (2): rawurlencode() expects parameter 1 to be string, array given [CORE\src\Routing\Route\Route.php, line 574]

rawurlencode() is a basic PHP function and this is the line 574:

$pass = implode('/', array_map('rawurlencode', $pass));

It looks like some problem with URL rewriting, but frankly I don't know how to fix it. Any ideas?

exportcsv method in EventsController

public function exportcsv($beginning = null, $end = null)
{
 if ($this->request->is('post')) {
  $beginning = $this->request->data['Export']['beginning']; 
  $end = $this->request->data['Export']['end'];              

  return $this->redirect([$beginning, $end]);
 }

 if (!$beginning && !$end) {
  return $this->render();
 }

 $this->response->download('export.csv');
$data = $this->Events->find('all')
                          ->select([
                            'title',
                            'created',
                            'description',
                            'ended',
                            'working_hours',
                            'price',
                            'username' => 'Users.name',
                            'statusname' => 'Statuses.name',
                            'employeename' => 'Employees.name'
                          ])
                          ->leftJoinWith('Statuses')
                          ->leftJoinWith('Users')
                          ->leftJoinWith('Employees')
                          ->where(["created BETWEEN " . $beginning . " AND " . $end])
                          ->autoFields(true)
                          ->toArray();
$_serialize = 'data';
$_delimiter = chr(9); //tab
$_extract = ['title', 'created', 'description', 'ended', 'working_hours', 'price', 'username', 'statusname', 'employeename'];
$this->set(compact('data', '_serialize','_delimiter', '_extract'));
$this->viewBuilder()->className('CsvView.Csv');
return;
}

exportcsv.ctp view:

<div class="events form large-6 medium-4 columns content">
  <?= $this->Form->create('Export'); ?>
  <?= $this->Form->input('beginning', array('type'=>'datetime', 'interval' => 15, 'label' => 'Beginning:')); ?>
  <?= $this->Form->input('end', array('type'=>'datetime',  'interval' => 15, 'label' => 'End:')); ?>
  <?= $this->Form->button(__('Add')) ?>
  <?= $this->Form->end() ?>
</div>
5
  • where is rawurlencode() or line 574? Commented Jul 1, 2016 at 13:12
  • It looks like rawurlencode() is a basic PHP function. This is the aforementioned line: $pass = implode('/', array_map('rawurlencode', $pass)); Commented Jul 1, 2016 at 13:36
  • why don't you include this line in your code? update your question with this code Commented Jul 1, 2016 at 13:38
  • 1
    So you've noticed that you can't pass arrays... how about trying to pass strings instead, ie build proper datetime strings from your separate values!? Side note: Your where() conditions are prone to SQL injections! You'd better use expressions or proper manual bindings! stackoverflow.com/questions/26430259/… Commented Jul 1, 2016 at 16:23
  • @ndm Thank you very much for your reply. I was hoping that there is another way to resolve this problem, but this also works. Also, thank you for reminding me of security issues, it's very important. Please add this comment as an answer and I'll accept it. Commented Jul 2, 2016 at 8:26

2 Answers 2

1

You cannot pass arrays in a URL array, the router doesn't support that. Also you need to additionally pass Instead, convert your single values to proper datetime strings, you could easily do that via the DateTimeType class, something like

if ($this->request->is('post')) {
    $beginning = $this->request->data('Export.beginning');
    $end = $this->request->data('Export.end');

    $type = \Cake\Database\Type::build('datetime');
    $beginning = $type->marshal($beginning)->format('Y-m-d H:i:s');
    $end = $type->marshal($end)->format('Y-m-d H:i:s');

    return $this->redirect([
        $beginning,
        $end
    ]);
}

Also, as already mentioned in the comments, you need to fix your where() call, as currently it has an SQL injection vulnerability. The keys of key => value items, as well as value only items, are not going to be bound, but inserted into the query directly!

Cakes expression builder ships with methods to safely generate BETWEEN expressions:

->where(function(\Cake\Database\Expression\QueryExpression $exp) use ($beginning, $end) {
    return $exp->between('Events.created', $beginning, $end);
});

See also

Sign up to request clarification or add additional context in comments.

Comments

0

your redirect is wrong

return $this->redirect([
    'controller' => 'yourController', 
    'action' => 'yourAction', 
    $yourData]
);

see the Cookbook for more information on this topic

1 Comment

Thank you for your reply. I tried to change my redirect to something like this: return $this->redirect(['controller' => 'Events', 'action' => 'exportcsv', $beginning, $end]); but it gives the same error and when I tried this: return $this->redirect(['controller' => 'Events', 'action' => 'exportcsv', [$beginning, $end]]); nothing happens. It didn't start to download the file and just reload the page so I assume that values are not assigned to $beginning and $end.

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.