0

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

我希望执行相同的查找查询,但如果要呈现文件,ID则从记录集中删除字段。CSV您会注意到即使下载 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');
    }

}
?>

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

如果有一个$recordSet->removeField('field')功能会很棒,但我找不到。

任何帮助将不胜感激。

4

2 回答 2

1

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

看看Lithium Media 类单元测试中的这个例子

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

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

}
?>
于 2013-06-19T22:28:41.850 回答
0

那么为什么不只是动态设置你的$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 处理程序发送数组,否则将是$downloadsRecordSet 对象进入视图。

于 2013-06-22T02:48:48.010 回答