Cakephp datasource for valves steam api
The steam api is something i’ve been working with recently as i occasionally do projects for a gaming community. If you don’t know what steam is its basically a piece of software that allows you to download games, play them, chat with friends, browse the web and more. As i develop alot of websites using cakephp, i decided i should create a datasource to use the steam api. If you would prefer to use the api manually yourself there are full details on how to use it here. In order to be able to use the datasource and any of the steam api you will need to get an api key. You can do so by visiting http://steamcommunity.com/dev/apikey and logging in with your steam account. Once you have that we can get started on our cake app. First up open up your database config file /app/config/database.php and add the following code in there, make sure to enter in your steam api key you just requested.
<?php
class DATABASE_CONFIG {
var $steam = array(
'datasource' => 'steam',
'apikey' => 'yoursteamapikeygoeshere',
);
}
?>
These are the connection details just like any database connection or any other datasource we may need a way to authenticate before we can use it. In this case we have an api key to allow us access. Next up we need to add the steam datasource so create a new file called steam_source.php and save it at /app/models/datasources/steam_source.php
<?php
App::import('Core', 'HttpSocket');
class SteamSource extends DataSource {
function __construct($config) {
$this->connection = new HttpSocket("http://api.steampowered.com");
parent::__construct($config);
}
public function listSources() {
return array('steamnews','steamplayers','steamachievements');
}
public function read($model, $queryData = array())
{
$results = array();
switch($model->useTable)
{
case "steamnews":
if (!isset($queryData['conditions']['appid'])) {
$queryData['conditions']['appid'] = 440;
}
if (!isset($queryData['conditions']['count'])) {
$queryData['conditions']['count'] = 10;
}
if (!isset($queryData['conditions']['maxlength'])) {
$queryData['conditions']['maxlength'] = 0;
}
$url = "/ISteamNews/GetNewsForApp/v0001/";
$url .= "?appid={$queryData['conditions']['appid']}&count;={$queryData['conditions']['count']}&maxlength;={$queryData['conditions']['maxlength']}&format;=json";
$response = json_decode($this->connection->get($url), true);
$results[$model->useTable] = array();
foreach($response['appnews']['newsitems']['newsitem'] as $data)
{
$results[$model->useTable][] = $data;
}
break;
case "steamplayers":
if (!isset($queryData['conditions']['steamids'])) {
$queryData['conditions']['steamids'] = array("76561197960435530");
}
$steamids = implode($queryData['conditions']['steamids'], ',');
$url = "/ISteamUser/GetPlayerSummaries/v0001/";
$url .= "?key={$this->config['apikey']}&steamids;={$steamids}&format;=json";
$response = json_decode($this->connection->get($url), true);
$results[$model->useTable] = array();
foreach($response['response']['players']['player'] as $data)
{
$results[$model->useTable][] = $data;
}
break;
case "steamachievements":
if (!isset($queryData['conditions']['gameid'])) {
$queryData['conditions']['gameid'] = 440;
}
$url = "/ISteamUserStats/GetGlobalAchievementPercentagesForApp/v0001/";
$url .= "?gameid={$queryData['conditions']['gameid']}&format;=json";
$response = json_decode($this->connection->get($url), true);
$results[$model->useTable] = array();
foreach($response['achievementpercentages']['achievements']['achievement'] as $data)
{
$results[$model->useTable][] = $data;
}
break;
}
return $results;
}
public function create($model, $fields = array(), $values = array())
{
return false;
}
public function describe($model) {
return $model->_schema;
}
}
?>
This datasource file covers requesting the data from the api and outputting it in a format we are familiar with. In order to be able to use this new datasource we need to have some models for each particular section. I use a steamnews, steamplayers and steamachievements models. As shown below. /app/models/steamnews.php
<?php
class Steamnews extends AppModel {
public $useDbConfig = 'steam';
function schema() {
$this->_schema = array(
'id' => array('type' => 'integer'),
'title' => array('type' => 'string'),
'url' => array('type' => 'string'),
'author' => array('type' => 'string'),
'contents' => array('type' => 'text'),
'feedlabel' => array('type' => 'string'),
'date' => array('type' => 'date'),
'feedname' => array('type' => 'string'),
);
return $this->_schema;
}
}
?>
/app/models/steamplayer.php
<?php
class Steamplayer extends AppModel {
public $useDbConfig = 'steam';
function schema() {
$this->_schema = array(
'steamid' => array('type' => 'String'),
'personaname' => array('type' => 'String'),
'profileurl' => array('type' => 'String'),
'avatar' => array('type' => 'String'),
'avatarmedium' => array('type' => 'String'),
'avatarfull' => array('type' => 'String'),
'personastate' => array('type' => 'integer'),
'communityvisibilitystate' => array('type' => 'integer'),
'profilestate' => array('type' => 'integer'),
'lastlogoff' => array('type' => 'integer'),
'commentpermission' => array('type' => 'integer'),
'realname' => array('type' => 'String'),
'primaryclanid' => array('type' => 'String'),
'timecreated' => array('type' => 'integer'),
'gameid' => array('type' => 'integer'),
'gameserverip' => array('type' => 'String'),
'gameextrainfo' => array('type' => 'String'),
'cityid' => array('type' => 'String'),
'loccountrycode' => array('type' => 'String'),
'locstatecode' => array('type' => 'String'),
'loccityid' => array('type' => 'String'),
);
return $this->_schema;
}
}
?<
/app/models/steamachievements.php
>?php
class Steamachievements extends AppModel {
public $useDbConfig = 'steam';
function schema() {
$this->_schema = array(
'name' => array('type' => 'String'),
'percent' => array('type' => 'Integer'),
);
return $this->_schema;
}
}
?<
Once we have everything setup in our app we can access the data like we would with any other model. Here are some examples i created in a quick test controller i made.
<?php
class TestsController extends AppController {
var $name = 'Tests';
var $uses = array('Steamnews','Steamplayer','Steamachievements');
function index()
{
# Find all steam news articles (default is to show 10 news with full content length and for game tf2)
pr($this->Steamnews->find('all'));
# Find all the News items For a game by supplying gameid the number of news items and content length to return.
pr($this->Steamnews->find('all',array('conditions'=>array('appid'=>440,'count'=>3,'maxlength'=>300))));
# Find all the PlayerSummaries (because api requires steamid default is robin walker)
pr($this->Steamplayer->find('all'));
# Find all the PlayerSummaries by supplying steam ids
pr($this->Steamplayer->find('all',array('conditions'=>array('steamids'=>array("76561197994235337","76561198034180652")))));
# Find all the Global Achievement Percentages For a game
pr($this->Steamachievements->find('all'));
$this->autoRender = false;
exit();
}
}
?>
Heres an example of the kind of output you will get back using the steamnews
Array
(
[steamnews] => Array
(
[0] => Array
(
[gid] => 1.1778970971792E+18
[title] => Team Fortress 2 raises $300k for Japan
[url] => http://store.steampowered.com/news/externalpost/eurogamer/1177897097179204650
[is_external_url] => 1
[author] =>
[contents] => Last week Valve started offering Team Fortress 2 players three different pieces of limited edition in-game headwear, with all proceeds going to the post-tsunami relief effort in Japan. According to a message on the official Team Fortress 2 site, the promotion has now raised a whopping $300,000. "Wow...
[feedlabel] => Eurogamer
[date] => 1301515440
[feedname] => eurogamer
)
[1] => Array
(
[gid] => 1.1778970971697E+18
[title] => Hat-tipping: Team Fortress 2 Hats For Japan sale raises $300,000
[url] => http://store.steampowered.com/news/externalpost/pcgamer/1177897097169747774
[is_external_url] => 1
[author] =>
[contents] => Good work, you hat-craving, conditionally-generous gentlemen and women. Valve's charity drive that began last Thursday has already produced more than $300,000 in aid to Japan by way of the American Red Cross. The items--three hats and a few of noise-maker consumables--are available until April 6.
[feedlabel] => PC Gamer
[date] => 1301447491
[feedname] => pcgamer
)
[2] => Array
(
[gid] => 1.177897097168E+18
[title] => Hats For Help
[url] => http://store.steampowered.com/news/externalpost/tf2_blog/1177897097168037565
[is_external_url] => 1
[author] =>
[contents] => Wow. Seriously, people, WOW. We knew you had it in you, but we're still amazed you've raised over $300,000 so far. Take a BOW, TF2 community -- because that is an incredible, frankly astounding, amount of money from a dedicated number of gamers, to one heck of a lot of people in some real need right...
[feedlabel] => TF2 Blog
[date] => 1301434740
[feedname] => tf2_blog
)
)
)
You can download all the files used in this example here. UPDATE This project is now available on git hub https://github.com/davidejones/steam-cakephp
Its just a datasource, so all it does is make access to the data the same as regular cakephp models so you can do simple queries using the model->find
Yes it will work with cakephp and steam api alone however this was made some time ago so some adjustments may need to be made to work with the latest cakephp and if the api has changed.
If i get some time i will try and create an updated version.
Mine’s not working, this is what it says on Cake’s home.
Your version of PHP is 5.2.8 or higher.
Your tmp directory is writable.
The FileEngine is being used for core caching. To change the config edit APP/Config/core.php
Your database configuration file is present.
Notice (8): Undefined index: message [APP/View/Pages/home.ctp, line 107] Cake is NOT able to connect to the database.
The datasource configuration “default” was not found in database.php