RESTful new Custom Search API by Google

Google has announced new API for Custom Search. It is currently in Labs. It is always confusing for me to what API is for what use. Google has lots of search API for different usage. Google already has this API for Custom Search.

[This code has been committed to GitHub.]

The new API is little different. It gives you access to its REST service endpoint. It has one URL and few parameters to access REST service. The result comes in two formats: JSON and Atom. Below is the PHP code to get started using new JSON/Atom Custom Search API.

The code presented here can give you Atom based result and JSON based result as well. It depend on you in what way you want your result. Both format output title, url and snippet from the search result. It can easily be extended to add more values from returned result. Final output (title, url, and snippet) comes in an easy to use Array. You need to loop through it the way you want. Just make sure you escape the values using either htmlspecialchars() or htmlentities() for security reason.

You need an API key and Custom search key. Get API key from Google Console: https://code.google.com/apis/console/?api=customsearch#project:219500252280:overview. Get custom search key from: http://www.google.com/cse/

First utility file used in main class:


function getSearchResult ( $url )
{
	$options = array(
		CURLOPT_RETURNTRANSFER => true,
		CURLOPT_HEADER         => false,
		CURLOPT_FOLLOWLOCATION => true,
		CURLOPT_ENCODING       => '',
		CURLOPT_AUTOREFERER    => true,
		CURLOPT_MAXREDIRS      => 2,
		CURLOPT_SSL_VERIFYPEER => false // if making https req and do not care of ssl/https certificate then set it off
	);
	$ch  = curl_init( $url );
	curl_setopt_array( $ch, $options );
	$content	= curl_exec( $ch );
	$err		= curl_errno( $ch );
	$errmsg		= curl_error( $ch );
	$info		= curl_getinfo( $ch );
	curl_close( $ch );
	$output['errno']   = $err;
	$output['errmsg']  = $errmsg;
	$output['content'] = $content;
	return $output;
}

The below code should basically split into three PHP pages. But I have written it in one. Do not worry seeing long code. It is easy to understand once you read it.


<?php
require './util.php';
interface SearchFormatStrategy {
	function getData(Google_Search $search);
}
class JSONStrategy implements SearchFormatStrategy {
	// Request JSON formatted search response
	public	function  getData(Google_Search $searchRes) {
		$params = array('key' => $searchRes::API_KEY,
						'cx' => $searchRes::CX,
						'q' => $searchRes->getQuery(),
						'alt'=>'json'
						);
		$url = $searchRes::BASE_URL . '?' . http_build_query($params, '', '&');
		$response = getSearchResult($url);
		//print_r($response);
		if ($response['errno'] == 0) {
			$responseArr =  json_decode($response['content']);
		}
		else {
			echo 'Error! Trouble somewehre. <br>' . $response['errmsg'];
		}
		foreach ($responseArr->items as $item) {
			// $item->htmlTitle, $item->snippet
			$outputArr[] =  array($item->title, $item->link, $item->htmlSnippet);
		}
		return $outputArr;
	}
}
class ATOMStrategy implements SearchFormatStrategy {
	// Request ATOM formatted search response
	public	function  getData(Google_Search $searchRes) {
		$params = array('key' => $searchRes::API_KEY,
						'cx' => $searchRes::CX,
						'q' => $searchRes->getQuery(),
						'alt'=>'atom'
						);
		$url = $searchRes::BASE_URL . '?' . http_build_query($params, '', '&');
		$response = getSearchResult($url);
		if ($response['errno'] == 0) { // no error
			return $this->_blogFeed($response['content']);
		}
		else {
			echo 'Error! Trouble somewehre. <br>' . $response['errmsg'];
		}
	}
    private function _blogFeed($rssXML)
    {
	libxml_use_internal_errors(true);
        $doc = simplexml_load_string($rssXML);
		$xml = explode("n", $rssXML);
		if (!$doc) {
			$errors = libxml_get_errors();
			foreach ($errors as $error) {
				echo $this->display_xml_error($error, $xml);
			}
			libxml_clear_errors();
		}
        if(count($doc) == 0) return;
		$docArr = json_decode(json_encode($doc),true);
		$entries = $docArr['entry'];
        foreach($entries as $item)
        {
		   $this->title		=	$item['title'];
		   $this->link		=	$item['link']['@attributes']['href'];
		   $this->summary	=	$item['summary'];
            $post = array(
				'title'=>		$this->title,
				'link' =>		$this->link,
				'summary' =>	$this->summary
			);
            $this->posts[] = $post;
        }
		return $this->posts;
    }
       // This I copied from somewhere
	public function display_xml_error($error, $xml)
	{
		$return  = $xml[$error->line - 1] . "n";
		$return .= str_repeat('-', $error->column) . "^n";
		switch ($error->level) {
			case LIBXML_ERR_WARNING:
				$return .= "Warning $error->code: ";
				break;
			 case LIBXML_ERR_ERROR:
				$return .= "Error $error->code: ";
				break;
			case LIBXML_ERR_FATAL:
				$return .= "Fatal Error $error->code: ";
				break;
		}
		$return .= trim($error->message) .
				   "n  Line: $error->line" .
				   "n  Column: $error->column";
		if ($error->file) {
			$return .= "n  File: $error->file";
		}
		return "$returnnn--------------------------------------------nn";
	}
}
class Google_Search {
	CONST BASE_URL	= 'https://www.googleapis.com/customsearch/v1';
	CONST API_KEY	= 'your api key';
	CONST CX		= 'custom search engine key';
	private $query = '';
	public function __construct ($queryTerm_) {
		$this->setQuery($queryTerm_);
	}
	public function getData(SearchFormatStrategy $strategyObject) {
		return $strategyObject->getData($this);
	}
	public function setQuery ($queryTerm_) {
		$this->query = $queryTerm_;
	}
	public function getQuery () {
		return $this->query;
	}
}
$google = new Google_Search('Bihar Election');
echo '<pre>';
// each array value should be encoded in production env.
print_r($google->getData(new JSONStrategy));
echo '<hr>';
//print_r($google->getData(new ATOMStrategy));
//$google->setQuery('PHP');
//print_r($google->getData(new ATOMStrategy));

I hope you find this guide as enjoyable to read as I did to create. Subscribe to feed or join me on Facebook for a regular update.

  • # 1 - by Jonathan

    hi satya. i’ve set up a “server” using Uniform Server, and placed the combined file into the server’s /www folder. on running, it doesn’t seem to show. i added a ?> to the end of the 2nd code block as i found out there wasn’t a closing bracket for the <?php

    i'm getting a blank page upon opening the php file, located at localhost:80/php/test.php

    is there anything which i've missed out? i could send you the php file which i've combined.

  • # 2 - by Jonathan

    sorry for the double post, what is the util.php for? do i need to have that file in the same directory as the test.php? if so, where would i be able to obtain it? thanks! :)

  • # 4 - by Walker

    I get an error at line 37

    Undefined property: stdClass::$items
    Invalid argument supplied for foreach()

    and on the return
    Undefined variable: outputArr

Comment pages
1 2 3162
Comments are open for an year period. Please, write here on Facebook page.