0

我正在尝试在 Cake 中创建一个服装数据源。此服装数据源使用 HasOffers api(如果你们中的任何人熟悉它)。

该 API 的结构如下(取自 HasOffers API 文档):

$base = 'https://api.hasoffers.com/Api?';

$params = array(
    'Format' => 'json'
    ,'Target' => 'Offer'
    ,'Method' => 'findAll'
    ,'Service' => 'HasOffers'
    ,'Version' => 2
    ,'NetworkId' => 'my-network-id'
    ,'NetworkToken' => 'my-api-key'
    ,'filters' => array(
        'Offer.name' => array( 'LIKE' => 'My Offer' )
        ,'Offer.default_payout' => array( 'GREATER_THAN_OR_EQUAL_TO' => 10 )
    )
);

$url = $base . http_build_query( $params );

$result = file_get_contents( $url );

现在你可以看到很多参数被用来确保你得到正确的数据,并且你实际上被“允许”拉取数据。

回到蛋糕:

现在我按照Cake Documentation 数据源示例的教程开始创建自己的数据源

目前,我只对读取数据源感兴趣(即我不关心更新、创建或删除)。

为此,我做了以下事情:

<?php
App::uses('HttpSocket', 'Network/Http');

class HasOffersStat extends DataSource {

    /**
     * An optional description of your datasource
     */
    public $description = 'Has Offer stat';
    public $base = 'http://bloglicsystem.api.hasoffers.com/Api?';


    /**
     * Our default config options. These options will be customized in our
     * ``app/Config/database.php`` and will be merged in the ``__construct()``.
     */
    public $config = array(
        'Service' => 'HasOffers',
        'Version' => 2,
        'Format' => 'json',
        'NetworkID' => "my-network-id",
        'NetworkToken' => 'my-network-token',
        'APIDomain' => 'http://bloglicsystem.api.hasoffers.com/Api?'
    );

    /**
     * If we want to create() or update() we need to specify the fields
     * available. We use the same array keys as we do with CakeSchema, eg.
     * fixtures and schema migrations.
     */
    protected $_schema = array(
        'id' => array(
            'type' => 'integer',
            'null' => false,
            'key' => 'primary',
            'length' => 11,
        ),
        'name' => array(
            'type' => 'string',
            'null' => true,
            'length' => 255,
        ),
        'message' => array(
            'type' => 'text',
            'null' => true,
        ),
    );

    /**
     * Create our HttpSocket and handle any config tweaks.
     */
    public function __construct($config) {
        parent::__construct($config);
        $this->Http = new HttpSocket();
    }


    public function makeApiCall($params)
    {
        $params = array_merge($this->params, (array)$params);
        $api_response = json_decode(file_get_contents($this->base.$this->config. http_build_query($params)    ), true);
        return $api_response['response'];
    }

    /**
     * Since datasources normally connect to a database there are a few things
     * we must change to get them to work without a database.
     */

    /**
     * listSources() is for caching. You'll likely want to implement caching in
     * your own way with a custom datasource. So just ``return null``.
     */
    public function listSources($data = null) {
        return null;
    }

    /**
     * describe() tells the model your schema for ``Model::save()``.
     *
     * You may want a different schema for each model but still use a single
     * datasource. If this is your case then set a ``schema`` property on your
     * models and simply return ``$model->schema`` here instead.
     */
    public function describe($model) {
        return $this->_schema;
    }

    /**
     * calculate() is for determining how we will count the records and is
     * required to get ``update()`` and ``delete()`` to work.
     *
     * We don't count the records here but return a string to be passed to
     * ``read()`` which will do the actual counting. The easiest way is to just
     * return the string 'COUNT' and check for it in ``read()`` where
     * ``$data['fields'] === 'COUNT'``.
     */
    public function calculate(Model $model, $func, $params = array()) {
        return 'COUNT';
    }

    /**
     * Implement the R in CRUD. Calls to ``Model::find()`` arrive here.
     */
    public function read(Model $model, $queryData = array(), $recursive = null) {
        /**
         * Now we get, decode and return the remote data.
         */
        $params = array(
            'Format' => 'json',
            'Target' => 'Report'
        );

        $res = $this->makeApiCall($params);
        return array($model->alias => $res);
    }
  }

然后在我的 app/config/database.php 我添加了以下几行:

    public $HasOfferStat = array(
    'datasource' => 'HasOffersStat',
    'NetworkID' => "my-network-id",
    'NetworkToken' => 'my-network-key',
    'APIDomain' => 'http://bloglicsystem.api.hasoffers.com/Api?'
);

现在很有趣,这确实有效!我的模型和数据源之间的链接正在工作,但是我需要一些帮助!

有了蛋糕魔术,我应该能够从我的控制器执行以下操作:

$this->MyModel->find('all');

但是我不太明白这将如何工作?我需要在我的数据源中创建什么才能使魔术蛋糕方法起作用?

4

1 回答 1

2

这取决于您是否需要关心这些“魔术”查找方法,“魔术”发生在模型中(请参阅Model::find()Model::buildQuery()和方法) Model::_readDataSource()Model::_find*()根据查找类型生成适当的查询。

数据源在方法中接收这些查询read,并且必须评估并正确使用它们,就像在链接的示例中一样。

所以这一切都取决于你的具体需求,如果你需要根据查找类型做一些特殊的事情,那么你总是可以检查Model::$findQueryType你的read方法并采取适当的行动。

另请参阅CakePHP Datasources Plugin,它适用于 Cake 1.3,但是您应该明白这一点。

于 2013-09-02T13:11:12.420 回答