exporter API(导出、输出器api)moodel3.3

Moodle【导出器】是接收数据并将其序列化为一个简单的预定义结构的类。它们确保输出的数据格式统一,易于维护。它们也用于生成外部函数的签名(参数和返回值)

外部函数定义在moodle/lib/externallib.php

在处理外部函数(Ajax,Web服务,...)和渲染方法时,我们经常遇到同一个对象被使用并从多个位置输出的情况。当这种情况出现时,我们的对象的代码会被重复序列化,或者变得不一致我们用【导出器】来解决这个问题,它清楚地定义了它输出的数据,并包含将输入数据转换成输出数据的逻辑,它可以自动生成外部函数所需的结构,如果需要导出新属性,则只需将其添加到导出器类中,并且【导出器】的所有用法都会自动继承此添加的属性

基类被定义在:moodle33\lib\classes\external\exporter.php

protected $related   用于避免DB查询的相关对象的列表

protected $data     这个输出器的数据 (值:stdClass|array//保存持久对象和相关对象

public function __construct($data, $related = array())   

//函数以适合于mustache模板的格式导出渲染器数据。这意味着原始记录是在to_record中生成的,但是,所有的字符串都是通过外部格式文本(或外部格式字符串)正确地传递的

final public function export(renderer_base $output)   

//函数猜测正确的上下文,返回到系统上下文

protected function get_context()    

//在导出时获得附加的值

protected function get_other_values(renderer_base $output)

//获取此导出器的读取属性定义。 Read属性将模型(persistent或stdClass)的默认属性与{@link self :: define_other_properties()}定义的属性相结合

final public static function read_properties_definition()

//获取用于创建和更新结构的导出器的属性定义,读取结构由以下方式返回:{@link self :: read_properties_definition()}

final public static function properties_definition()

//返回仅用于显示的附加属性列表

protected static function define_other_properties()

//返回属性列表。返回实例化导出器时所需的属性列表,以及它将同时导出的属性列表

protected static function define_properties()

//返回与此持久性相关的对象列表,只有在这里列出的对象可以缓存在这个对象中

protected static function define_related()

//获取上下文结构

final protected static function get_context_structure()

//获取格式字段名

final protected static function get_format_field($definitions, $property)

//得到结构格式

final protected static function get_format_structure($property, $definition, $required = VALUE_REQUIRED)

//返回创建的结构

final public static function get_create_structure()

//返回读取的结构
final public static function get_read_structure()

//从一组属性(递归)返回读取结构
final protected static function get_read_structure_from_properties($properties, $required = VALUE_REQUIRED, $default = null)

//返回更新的结构
final public static function get_update_structure()

定义属性

define_properties()方法返回实例化导出器时所需的属性列表,以及它将同时导出的属性列表

protected static function define_properties() {
    return array(
        'id' => array(
            'type' => PARAM_INT
        ),
        'username' => array(
            'type' => PARAM_ALPHANUMEXT
        ),
    );
}

这些属性将允许我们为外部函数生成一个创建更新结构,稍后再介绍

哦,如果你使用持久性,你不需要这样做:瞧瞧这个-导出和持久

如果你有一个持续的,你想要导出输出,所有的工作已经完成了。如果扩展class core\external\persistent_exporter,并添加方法define_class(),则所有持久性属性将自动添加到导出器

class status_exporter extends \core\external\persistent_exporter {
 
    /**
     * Returns the specific class the persistent should be an instance of.
     *
     * @return string
     */
    protected static function define_class() {
        return \some\namespace\status::class; // PHP 5.5+ only
    }
 
}

 

属性特性

每个属性都使用以下属性进行配置:

type
唯一的强制性属性。它必须是许多PARAM_ *常量之一,或者是一组属性。
default
未提供值时的默认值。未指定时,需要一个值。
null
无论是常量NULL_ALLOWED还是NULL_NOT_ALLOWED,都会告知是否接受空值。这个默认为NULL_NOT_ALLOWED。
optional
该财产是否可以完全省略。默认为false。
multiple
这个属性是否会有更多的条目。默认为false。

尽管这不是一个规则,但建议标准属性(通过与附加属性相反)仅使用上面的type属性,并且只使用PARAM_ *常量。

附加属性

附加属性的列表被视为额外的属性,不需要给导出器输出它们。它们是从提供的数据(以及相关的对象,后面会详细介绍)中动态生成的。例如,如果我们希望我们的导出器将URL提供给用户的配置文件,我们不需要开发者事先传递它,我们可以基于已经提供的ID生成它。


附加属性只包含在对象的读取结构(get_read_structureread_properties_definition)中,因为它们是动态生成的。不需要也不需要创建更新对象


/*
* * Return the list of additional properties. * @return array */ protected static function define_other_properties() { return array( 'profileurl' => array( 'type' => PARAM_URL ), 'statuses' => array( 'type' => status_exporter::read_properties_definition(), 'multiple' => true, 'optional' => true ), ); }

 

 

上面的代码片段定义了我们将始终在属性profileurl下导出一个URL ,并且我们将导出或不导出status_exporters的列表正如你所看到的,这个类型可以使用另一个导出器读取属性,它允许导出器被嵌套。

如果您定义了其他属性,则还必须添加逻辑来导出它们。这是通过将get_other_values(renderer_base $ output)方法添加到导出器来完成的。这是一个我们忽略状态的例子,因为它们是可选的

/**
 * Get the additional values to inject while exporting.
 *
 * @param renderer_base $output The renderer.
 * @return array Keys are the property names, values are their values.
 */
protected function get_other_values(renderer_base $output) {
    $profileurl = new moodle_url('/user/profile.php', ['id' => $this->data->id]);
    return [
        'profileurl' => $profileurl->out(false)
    ];
}

重要说明:其他属性不能覆盖标准属性,所以请确保名称不冲突。

相关的对象

 

有时我们需要出口商内部的更多信息来导出。这可能与上下文一样简单,但在导出其他属性时也可以使用其他对象尽可能避免调用API,或者在导出时查询数据库。出口商可以在循环中使用,因此后续查询可能会显着影响性能,因此需要相关的对象。

 

相关对象需要在出口商内部进行定义,即确保它们总是被提供并且是正确的类型。在一些情况下,通常当相关对象不存在时,它们可以被标记为可选的。例如,如果我们有一个问题导出器,可选的相关对象可能是同行评审者,因为我们并不总是有同行评审者。

 

使用方法protected static define_related(),如下所示。键是相关对象的任意名称,值是该类的完全限定名称。班级名称后面可以跟[]和/或分别表示这些对象的列表,以及一个可选的相关内容

/**
 * Returns a list of objects that are related.
 *
 * @return array
 */
protected static function define_related() {
    return array(
        'context' => 'context',                     // Must be an instance of context.
        'statuses' => 'some\\namespace\\status[]',  // Must be an array of status instances.
        'mother' => 'family\\mother?',              // Can be a mother instance, or null.
        'brothers' => 'family\\brother[]?',         // Can be null, or an array of brother instances.
    );
}

实例化时,我们将相关的对象给导出者,如下所示:

$data = (object) ['id' => 123, 'username' => 'batman'];
$relateds = [
    'context' => context_system::instance(),
    'statuses' => [
        new some\namespace\status('Hello'),
        new some\namespace\status('World!'),
    ],
    'mother' => null,
    'brothers' => null
];
$ue = new user_exporter($data, $relateds);

 

 

使用导出器

一旦我们有一个简约的出口商设置,这里是如何使用它。

class user_exporter extends core\external\exporter {
 
    /**
     * Return the list of properties.
     *
     * @return array
     */
    protected static function define_properties() {
        return array(
            'id' => array(
                'type' => PARAM_INT
            ),
            'username' => array(
                'type' => PARAM_ALPHANUMEXT
            ),
        );
    }
 
}

 

导出数据

$data = (object) ['id' => 123, 'username' => 'batman'];
 
// The only time we can give data to our exporter is when instantiating it.
$ue = new user_exporter($data);
 
// To export, we must pass the reference to a renderer.
$data = $ue->export($OUTPUT);

如果我们打印$data的内容,我们将获得这个:

stdClass对象
(
    [id] => 123
    [username] =>蝙蝠侠
)

现在,我同意这并不令人印象深刻。但是等到你阅读了关于自动格式化文本,以及在外部函数中的使用

 

①遵守文本格式规则:  如果我们在导出过程中必须通过$OUTPUT,那是因为我们正在为您自动处理文本格式。记住函数format_text()format_string()它们被用来对用户通常提交的内容应用过滤器,还可以将其从一些给定的格式转换为HTML。

导出时,导出器会查看所有属性类型当它找到PARAM_TEXT类型的属性时,它将使用format_string()但是,如果使用PARAM_RAW找到一个属性,并且存在另一个同名的属性,但以format结尾,则将使用format_text()如果您不熟悉在Moodle中输出文本的规则,请参阅输出函数最常用的PARAM_ *类型

 

'description' => array(
    'type' => PARAM_RAW,
),
'descriptionformat' => array(
    'type' => PARAM_INT,
),

添加上面的两个属性,让我们看看当用户的描述是以Markdown格式,然后导出它时会发生什么

$data = (object) [
    'id' => 123,
    'username' => 'batman',
    'description' => 'Hello __world__!',
    'descriptionformat' => FORMAT_MARKDOWN
];
$ue = new user_exporter($data, ['context' => context_user::instance(123)]);
$data = $ue->export($OUTPUT);

不出所料,这就是它出来的结果:

stdClass Object
(
    [id] => 123
    [username] => 蝙蝠侠
    [description] => <p>Hello <strong>world</strong>!</p>
    [descriptionformat] => 1   // Corresponds to FORMAT_HTML.
)

Psst ...我们已经在上面作弊了。你有没有注意到我们已经通过了导出器的上下文?我们通过了一个相关的对象

 

外部函数里

假设我们有一个外部函数get_users,它返回一个用户列表。现在我们只想导出用户ID和他们的用户名,所以我们将使用我们的导出器。我们要求我们的导出器为我们创造外部结构:

public static function get_users_returns() {
    return external_multiple_structure(
        user_exporter::get_read_structure()
    );
}

现在这样做了,我们必须使用我们的导出器来导出我们用户的数据

public static function get_users() {
    global $DB, $PAGE;
    $output = $PAGE->get_renderer('core');
    $users = $DB->get_records('user', null, '', 'id, username', 0, 10); // Get 10 users.
    $result = [];
    foreach ($users as $userdata) {
        $exporter = new user_exporter($userdata);
        $result[] = $exporter->export($output);
    }
    return $result;
}

最后,如果您有另一个外部函数来创建用户,则可以使用导出器来获取传入数据的结构。如果你希望你的外部函数需要更多的信息来创建你的用户这将有助于你的需求的增长。以下表示外部函数需要字段“username”在通过键“user”中传递。创建更新结构,包括所有的标准性能,而不是其他的附加属性请注意,创建结构不包括id属性。使用user_exporter :: get_update_structure()是否更新用户,从而接收ID。

public static function create_user_parameters() {
    return new external_function_parameters([
        'user' => user_exporter::get_create_structure()
    ]);
}
 
public static function create_user($user) {
    // Mandatory parameters validation.
    $params = self::validate_parameters(self::create_user_parameters(), ['user' => $user]);
    $user = $params['user'];
    ...
}

重要提示:在参数中使用时,导出器的结构必须总是被包含在另一个关键字的下方,高于我们所使用的用户否则这将不会灵活,并且可能不会为某些Web服务协议生成有效的结构

posted @ 2018-05-04 09:14  虚无缥缈的云  阅读(285)  评论(0编辑  收藏  举报