Dear Reader,

Back in March I had the opportunity to work on a project for Microsoft that is now coming to light. I was tasked with writing a PHP wrapper for the Bing API that Microsoft has been building. I’ve written API wrappers before and it is either a fun experience or it is a nightmare, depending on whether the API is easy to work with. I am pleased to report that the Bing Search API is well thought out and very easy to work with. For PHP developers, I am hoping that what I am about to show you makes it even easier.



QuickStart

Ok, if you don’t care for the rambling, here is everything you need to get going.

The steps are easy.

Grab the code and put it somewhere in your include path.

Get an application key. (They are free)

Write you a quick index.php that looks something like this:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 <html> <head> <title> Cal's Bing Search QuickTest</title> <body> <?PHP function __autoload ( $className ) { $fileName = strtr ( $className , '_' , DIRECTORY_SEPARATOR ) . ".php" ; include $fileName ; return ; } $apiKey = '' ; $o = new Msft_Bing_Search ( $apiKey ) ; $o -> setQuery ( 'zend framework' ) -> setWebCount ( 10 ) -> setSite ( 'calevans.com' ) -> setSource ( 'Web' ) -> setSource ( 'Image' ) -> setAdult ( 'Off' ) ; $raw = $o -> search ( ) ; echo "<h2>Raw</h2>" ; echo "<textarea cols='100' >" . $o -> getUrl ( ) . "</textarea><br />" ; if ( $o -> getFormat ( ) == 'json' ) { $result = json_decode ( $raw ) ; } else { $result = htmlspecialchars ( $raw ) ; } echo "<h2>Images</h2>" ; foreach ( $result -> SearchResponse -> Image -> Results as $value ) { printf ( '' , $value -> Url , $value -> MediaUrl ) ; } echo "<br />" ; echo "<h2>Links</h2>" ; foreach ( $result -> SearchResponse -> Web -> Results as $value ) { printf ( '%s<br />' , $value -> Url , $value -> Title ) ; } ?> </body> </html> <html> <head> <title> Cal's Bing Search QuickTest</title> <body> <?PHP function __autoload($className) { $fileName = strtr($className,'_',DIRECTORY_SEPARATOR).".php"; include $fileName; return; } $apiKey = ''; $o = new Msft_Bing_Search($apiKey); $o->setQuery('zend framework') ->setWebCount(10) ->setSite('calevans.com') ->setSource('Web') ->setSource('Image') ->setAdult('Off') ; $raw = $o->search(); echo "<h2>Raw</h2>"; echo "<textarea cols='100' >".$o->getUrl()."</textarea><br />"; if ($o->getFormat()=='json') { $result = json_decode($raw); } else { $result = htmlspecialchars($raw); } echo "<h2>Images</h2>"; foreach($result->SearchResponse->Image->Results as $value) { printf('',$value->Url,$value->MediaUrl); } echo "<br />"; echo "<h2>Links</h2>"; foreach($result->SearchResponse->Web->Results as $value) { printf('%s<br />',$value->Url,$value->Title); } ?> </body> </html>

If it works, you should see something that looks like this.

That is a simple example that will get you going and allow you to play with the code. Of course you have to get your API key first. Lines 13, 16, and 18 above are the ones you are going to want to play with. 13 being an API key; without that it won’t work. 16 is the search term, I know I have a couple of Zend Framework related posts on my blog so I used that. Line 18 is the domain limit. I only want to search for Zend Framerwork on my blog. Tinker with those a while and see what results you come up with.

Oh, you may have notices the autoLoader from lines 6-11. Feel free to remove that if you like but you will have to add in all the requires for the classes, subclasses and Exceptions. If you put the library in your path, the auto-loader will take care of making sure you have access to them all.

The API

The Bing API is very straightforward and most importantly, consistent in design. These two facts make it very easy to work with. Actually, there are several options that my wrapper doesn’t yet implement, For this first version, I stuck with the basic Search API but they have separate sub-APIs for Phonebook, News, Translation and others. I hope that future version of this wrapper will implement those.

The Wrapper

There are 37 methods in the wrapper and the vast majority of those are housekeeping methods like getters and setters. The heart of the wrapper is the search() method.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 /** * Attempts to execute the currently-specified search * * @return string The results from the query * @throws Msft_Bing_Search_Exception */ public function search ( ) { if ( empty ( $this -> appid ) ) { throw new Msft_Bing_Search_Exception ( 'Empty AppId' ) ; } if ( empty ( $this -> sources ) ) { $this -> sources [ ] = 'web' ; } $this -> url = $this -> buildUrl ( ) ; if ( $stream = @ fopen ( $this -> url , 'r' ) ) { $output = stream_get_contents ( $stream ) ; fClose ( $stream ) ; } else { throw new Msft_Bing_Search_Exception ( 'Problem opening stream' ) ; } // print all the page starting at the offset 10 return $output ; } // public function search() /** * Attempts to execute the currently-specified search * * @return string The results from the query * @throws Msft_Bing_Search_Exception */ public function search() { if (empty($this->appid)) { throw new Msft_Bing_Search_Exception('Empty AppId'); } if (empty($this->sources)) { $this->sources[]='web'; } $this->url = $this->buildUrl(); if ($stream = @fopen($this->url, 'r')) { $output = stream_get_contents($stream); fClose($stream); } else { throw new Msft_Bing_Search_Exception('Problem opening stream'); } // print all the page starting at the offset 10 return $output; } // public function search()

As you can see, we check to make sure we have a appId and throw an exception if we don’t. Then, if you’ve not set which sources to check (web,image,spell are currently implemented) we set a default of web.

We then build the URL, call the URL and either return the results back to you for processing or throw an exception because something went wrong.

That’s really all there is to using it. You can play around with the different options like setting ‘spell’ as a source.

Conclusion

The Bing API is easy to work with, powerful, and since Google doesn’t give you access to this information from an API, unique. The possibilities that this API presents are interesting and I’ll explore a couple in the future. The wrapper should get you started in working with it but as I said, it is not yet complete. If you need some of the features that have yet to be implemented, feel free to send me a patch. :) Most of all I hope you learn something form it. After all it is open source. :)

Until next time,

I <3 |K

=C=