Reputation: 75
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>
Upvotes: 1
Views: 1135
Reputation: 60463
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
Upvotes: 1
Reputation: 2252
your redirect is wrong
return $this->redirect([
'controller' => 'yourController',
'action' => 'yourAction',
$yourData]
);
see the Cookbook for more information on this topic
Upvotes: 0