如何从锂记录集中的所有实体中删除特定字段? [英] How do you remove specific fields from all entities of a record set in Lithium?
问题描述
我正在使用MySQL
作为所有模型的数据库连接适配器.我有一个带有索引函数的下载模型和控制器,该函数根据从请求传递的类型来呈现HTML
表或CSV
文件.我也有一个CSV
媒体类型来处理数据数组,该数组按预期方式工作(将数组键作为标头输出,然后为每行数据输出数组值).
I am using MySQL
as the database connection adapter for all my models. I have a downloads model and controller with an index function that renders either an HTML
table or a CSV
file depending on the type passed from the request. I also have a CSV
media type to handle an array of data, which is working as expected (outputs array keys as headers then array values for each row of data).
我希望执行相同的查找查询,但是如果要呈现CSV
文件,则从记录集中删除ID
字段.您会注意到,即使下载ID不在fields数组中,也正在获取下载ID,因此仅根据请求类型更改fields数组是行不通的.
I wish to do the same find query but then remove ID
fields from the record set if a CSV
file is going to be rendered. You'll notice that the download ID is being fetched even though it is not in the fields array, so simply changing the fields array based on the request type will not work.
我已经在下载控制器的索引操作中尝试了以下操作:
I have tried the following in the index action of my downloads controller:
<?php
namespace app\controllers;
use app\models\Downloads;
class DownloadsController extends \lithium\action\Controller {
public function index() {
// Dynamic conditions
$conditions = array(...);
$downloads = Downloads::find('all', array(
'fields' => array('user_id', 'Surveys.name'),
'conditions' => $conditions,
'with' => 'Surveys',
'order' => array('created' => 'desc')
));
if ($this->request->params['type'] == 'csv') {
$downloads->each(function ($download) {
// THIS DOES NOT WORK
unset($download->id, $download->user_id);
// I HAVE TRIED THIS HERE AND THE ID FIELDS STILL EXIST
// var_dump($download->data());
// exit;
return $download;
});
return $this->render(array('csv' => $downloads->to('array')));
}
return compact('downloads');
}
}
?>
我认为实体对象上有一个__unset()
魔术方法,当您在实体字段上调用标准PHP
unset()
函数时会调用该方法.
I thought there was an __unset()
magic method on the entity object that would be called when you call the standard PHP
unset()
function on an entity's field.
如果有一个$recordSet->removeField('field')
函数,那很好,但我找不到它.
It would be great if there was a $recordSet->removeField('field')
function, but I can not find one.
任何帮助将不胜感激.
推荐答案
也许您应该执行$downloads = $downloads->to('array');
,使用for循环迭代数组,从每一行中删除这些字段,然后返回该数组.如果您需要做很多事情来做同样的事情,则可以设置一个自定义的媒体处理程序,该处理程序可以更改数据而无需控制器中的逻辑.
Perhaps you should do $downloads = $downloads->to('array');
, iterate the array with a for loop, remove those fields from each row, then return that array. If you have to do this same thing for a lot of actions, you could setup a custom Media handler that could alter the data without needing logic for it in your controller.
看看此示例在Lithium Media类单元测试中.
Take a look at this example in the Lithium Media class unit test.
通过使用自定义处理程序,您还可以完全避免控制器中包含太多逻辑.此示例还根据数据中的键自动生成标题行.
You can also avoid having much logic for it in your controller at all through the use of a custom handler. This example also auto-generates a header row from the keys in your data.
在config/bootstrap/media.php
中:
Media::type('csv', 'application/csv', array(
'encode' => function($data, $handler, $response) {
$request = $handler['request'];
$privateKeys = null;
if ($request->privateKeys) {
$privateKeys = array_fill_keys($request->privateKeys, true);
}
// assuming your csv data is the first key in
// the template data and the first row keys names
// can be used as headers
$data = current($data);
$row = (array) current($data);
if ($privateKeys) {
$row = array_diff_key($row, $privateKeys);
}
$headers = array_keys($row);
ob_start();
$out = fopen('php://output', 'w');
fputcsv($out, $headers);
foreach ($data as $record) {
if (!is_array($record)) {
$record = (array) $record;
}
if ($privateKeys) {
$record = array_diff_key($record, $privateKeys);
}
fputcsv($out, $record);
}
fclose($out);
return ob_get_clean();
}
));
您的控制器:
<?php
namespace app\controllers;
use app\models\Downloads;
class DownloadsController extends \lithium\action\Controller {
public function index() {
$this->request->privateKeys = array('id', 'user_id');
// Dynamic conditions
$conditions = array(...);
$downloads = Downloads::find('all', array(
'fields' => array('user_id', 'Surveys.name'),
'conditions' => $conditions,
'with' => 'Surveys',
'order' => array('created' => 'desc')
));
return compact('downloads');
}
}
?>
这篇关于如何从锂记录集中的所有实体中删除特定字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!