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?