Php 如何从Limition中记录集的所有实体中删除特定字段?

Php 如何从Limition中记录集的所有实体中删除特定字段?,php,recordset,lithium,Php,Recordset,Lithium,我正在使用MySQL作为我所有型号的数据库连接适配器。我有一个下载模型和控制器,带有一个索引函数,根据请求传递的类型呈现HTML表或CSV文件。我还有一个CSVmedia类型来处理数据数组,该数组按预期工作(将数组键作为标题输出,然后为每行数据输出数组值) 我希望执行相同的查找查询,但如果要呈现CSV文件,则从记录集中删除ID字段。您会注意到下载ID正在被提取,即使它不在fields数组中,因此根据请求类型简单地更改fields数组将不起作用 我在下载控制器的索引操作中尝试了以下操作: <

我正在使用MySQL作为我所有型号的数据库连接适配器。我有一个下载模型和控制器,带有一个索引函数,根据请求传递的类型呈现
HTML
表或
CSV
文件。我还有一个
CSV
media类型来处理数据数组,该数组按预期工作(将数组键作为标题输出,然后为每行数据输出数组值)

我希望执行相同的查找查询,但如果要呈现
CSV
文件,则从记录集中删除
ID
字段。您会注意到下载ID正在被提取,即使它不在fields数组中,因此根据请求类型简单地更改fields数组将不起作用

我在下载控制器的索引操作中尝试了以下操作:

<?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');
    }

}
?>
<?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');
    }

}
?>

我认为在实体对象上有一个
\u unset()
魔术方法,当您调用实体字段上的标准
PHP
unset()
函数时,会调用该方法

如果有一个
$recordSet->removeField('field')
函数就好了,但我找不到


任何帮助都将不胜感激。

也许你应该做
$downloads=$downloads->to('array')
,使用for循环迭代该数组,从每行中删除这些字段,然后返回该数组。如果您必须为许多操作执行相同的操作,您可以设置一个自定义媒体处理程序,该处理程序可以更改数据,而不需要控制器中的逻辑

看看锂媒体类单元测试

通过使用自定义处理程序,还可以避免在控制器中有太多的逻辑。此示例还自动从数据中的键生成标题行

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() {

        // 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');
    }

}
?>
<?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');
    }

}
?>

为什么不动态设置
$fields
数组

public function index() {
    $type = $this->request->params['type'];
    //Exclude `user_id` if request type is CSV
    $fields = $type == 'csv' ? array('Surveys.name') : array('user_id', 'Surveys.name');
    $conditions = array(...);
    $with = array('Surveys');
    $order = array('created' => 'desc');

    $downloads = Downloads::find('all', compact('conditions', 'fields', 'with', 'order'));
    //Return different render type if CSV
    return $type == 'csv' ? $this->render(array('csv' => $downloads->data())) : compact('downloads');
}

在本例中,您可以看到我是如何为您的CSV处理程序发送数组的,否则将是
$downloads
记录集对象进入视图。

我重新阅读了您的问题,显然您已经知道自定义媒体处理程序。但无论如何,我希望这能给你一些想法。谢谢你,我很快会尝试一下,让你知道它是如何进行的,但它看起来确实像一个更干净的解决方案。谢谢你!只有一件事,通过使用
lithium\util\Set::flatte()
“将多维数组折叠为单个维度,为每个数组元素的键使用分隔的数组路径,即
array(array('Foo'=>array('Bar'=>Far'))
变成
array('0.Foo.Bar'=>Far')
”@韭菜我把代码放在Github上-。您打算在哪里使用“展平”?在
$data
上?如果你制作了一个已编辑版本的链接,则发布一个链接。这仍然会获取下载ID,目的是删除所有ID字段,而不仅仅是用户ID字段。