douzhigan1687 2013-09-02 04:22 采纳率: 0%
浏览 43
已采纳

CakePHP:如何在自定义数据源中实现查找类型?

I am trying to create a costum datasource in Cake. This costum datasource uses the HasOffers api (if any of you are familiar with it).

The structure of this API is as follow (taken from HasOffers API documentation):

$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 );

Now as you can see alot of parameters is used to make sure that you get the right data and that you are actually 'allowed' to pull the data.

Going back to cake:

Now i started out creating my own datasource by following the tutorial on Cake Documentation datasource example

For now, i am only interrested in reading from the datasource (i.e i dont care about update, create or delete).

For this purpose i did the following:

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

Then in my app/config/database.php i added the following lines:

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

Now funny enough this actually works! the link between my model and the datasource is working however i need some help!

with cake magic i should be able to do the following line from my controller:

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

However i don't quite understand how that would work? What do i need to create in my Datasource to make magic cake methods work?

展开全部

  • 写回答

1条回答 默认 最新

  • douxianji6104 2013-09-02 05:11
    关注

    It depends whether you need to care about these "magic" find methods, the "magic" happens in the model (see Model::find(), Model::buildQuery(), Model::_readDataSource() and the Model::_find*() methods), where appropriate queries are generated based on the find type.

    The datasource receives these queries in the read method, and has to evaluate and make proper use of them, just like in the linked example.

    So it all depends on your specific needs, if you need to do something special based on the find type, then you can always check Model::$findQueryType in your read method and act appropriately.

    See also the CakePHP Datasources Plugin, it's for Cake 1.3, however you should get the point.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
编辑
预览

报告相同问题?

手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部