如何从锂记录集中的所有实体中删除特定字段? [英] How do you remove specific fields from all entities of a record set in Lithium?

查看:130
本文介绍了如何从锂记录集中的所有实体中删除特定字段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆