Skip to content

Commit

Permalink
Implemented CSVResponse. Updated readme to reflect.
Browse files Browse the repository at this point in the history
  • Loading branch information
Sean Moore committed Jun 7, 2013
1 parent 8c064ba commit 1a2b187
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 52 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,17 @@ GET /example?q=(popular:true)&offset=1&limit=2&fields=(name,location,prince)
}
```

The envelope can be suppressed for responses via the 'envelope=false' query paramter. This will return just the record set by itself as the body, and the meta information via X- headers.

Often times, database field names are snake_cased. However, when working with an API, developers
genreally prefer JSON fields to be returned in camelCase (many API requests are from browsers, in JS).
This project will by default convert all keys in a records response from snake_case to camelCase.

This can be turned off for your API by setting the JSONResponse's function "convertSnakeCase(false)".

**CSV**

CSV is the other implemented handler. It uses the first record's keys as the header row, and then creates a csv from each row in the array.
CSV is the other implemented handler. It uses the first record's keys as the header row, and then creates a csv from each row in the array. The header row can be toggled off for responses.

```
name,location,princeName
Expand Down
21 changes: 3 additions & 18 deletions index.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,26 +201,11 @@
return;
}
else if($app->request->get('type') == 'csv'){
$records = $app->getReturnedValue();

// Headers for a CSV
header('Content-type: application/csv');
header('Content-Disposition: attachment; filename="'.time().'.csv"');
header('Pragma: no-cache');
header('Expires: 0');

// We write directly to out, which means we don't ever save this file to disk.
$handle = fopen('php://output', 'w');

// The keys of the first result record will be the first line of the CSV (headers)
fputcsv($handle, array_keys($records[0]));

// Write each record as a csv line.
foreach($records as $line){
fputcsv($handle, $line);
}
$records = $app->getReturnedValue();
$response = new \PhalconRest\Responses\CSVResponse($app->getDI());
$response->useHeaderRow(true)->send($records);

fclose($handle);
return;
}
else {
Expand Down
46 changes: 46 additions & 0 deletions responses/CSVResponse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php
namespace PhalconRest\Responses;

class CSVResponse extends Response{

protected $headers = true;

public function __construct($di){
parent::__construct($di);
}

public function send($records){

$response = $this->di->get('response');
// Headers for a CSV
$response->setHeader('Content-type', 'application/csv');

// By default, filename is just a timestamp. You should probably change this.
$response->setHeader('Content-Disposition', 'attachment; filename="'.time().'.csv"');
$response->setHeader('Pragma', 'no-cache');
$response->setHeader('Expires', '0');

// We write directly to out, which means we don't ever save this file to disk.
$handle = fopen('php://output', 'w');

// The keys of the first result record will be the first line of the CSV (headers)
if($this->headers){
fputcsv($handle, array_keys($records[0]));
}

// Write each record as a csv line.
foreach($records as $line){
fputcsv($handle, $line);
}

fclose($handle);

return $this;
}

public function useHeaderRow($headers){
$this->headers = (bool) $headers;
return $this;
}

}
40 changes: 7 additions & 33 deletions responses/JSONResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public function __construct($di){

public function send($records){

$response = $this->di->get('response');

// If the query string 'envelope' is set to false, do not use the envelope.
// Instead, return headers.
$request = $this->di->get('request');
Expand All @@ -33,12 +35,13 @@ public function send($records){
);
$message['records'] = $records;
} else {
//TODO: HTTP headers in palce of envelope
$response->setHeader('X-Record-Count', count($records));
$response->setHeader('X-Status', 'SUCCESS');
$message = $records;
}

$this->di->get('response')->setJsonContent($message);
$this->di->get('response')->send();
$response->setJsonContent($message);
$response->send();

return $this;
}
Expand All @@ -53,33 +56,4 @@ public function useEnvelope($envelope){
return $this;
}

/**
* In-Place, recursive conversion of array keys in snake_Case to camelCase
* @param array $snakeArray Array with snake_keys
* @return no return value, array is edited in place
*/
private function arrayKeysToSnake($snakeArray){
foreach($snakeArray as $k=>$v){
if (is_array($v)){
$v = $this->arrayKeysToSnake($v);
}
$snakeArray[$this->snakeToCamel($k)] = $v;
if($this->snakeToCamel($k) != $k){
unset($snakeArray[$k]);
}
}
return $snakeArray;
}

/**
* Replaces underscores with spaces, uppercases the first letters of each word,
* lowercases the very first letter, then strips the spaces
* @param string $val String to be converted
* @return string Converted string
*/
private function snakeToCamel($val) {
return str_replace(' ', '', lcfirst(ucwords(str_replace('_', ' ', $val))));
}


}
}
28 changes: 28 additions & 0 deletions responses/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,32 @@ public function __construct($di){
$this->setDI($di);
}

/**
* In-Place, recursive conversion of array keys in snake_Case to camelCase
* @param array $snakeArray Array with snake_keys
* @return no return value, array is edited in place
*/
protected function arrayKeysToSnake($snakeArray){
foreach($snakeArray as $k=>$v){
if (is_array($v)){
$v = $this->arrayKeysToSnake($v);
}
$snakeArray[$this->snakeToCamel($k)] = $v;
if($this->snakeToCamel($k) != $k){
unset($snakeArray[$k]);
}
}
return $snakeArray;
}

/**
* Replaces underscores with spaces, uppercases the first letters of each word,
* lowercases the very first letter, then strips the spaces
* @param string $val String to be converted
* @return string Converted string
*/
protected function snakeToCamel($val) {
return str_replace(' ', '', lcfirst(ucwords(str_replace('_', ' ', $val))));
}

}

0 comments on commit 1a2b187

Please sign in to comment.