Compiling Sphinx on Mac OS X

December 27th, 2011 by Eric Cope

We are looking into using Sphinx on a project and needed to get it installed on our local machines, Macbook Pros, for exploration. Sphinx does not ship Mac binaries, so we had to compile it. We had XCode previously installed. If you want the MySQL to connect, you need to download the source files to the version of MySQL you are running.

The first step is to run Cmake from within the MySQL source directory. Specifically, it generates a mysql_version.h file from mysql_version.h.in.  You probably have to download Cmake.

 cmake -DBUILD_CONFIG=mysql_release

You only need to make the MySQL client libraries, so cd into libmysql directory

cd libmysql
make

This will compile and link the necessary files into a libary for Sphinx to use.

Once these complete successfully, now you can follow sphinx’s compilation directions.

./configure --prefix=/Applications/sphinx/2.0.3/sphinx-2.0.3 --with-mysql-includes=/Applications/sphinx/2.0.3/mysql-5.5.9/include --with-mysql-libs=/Applications/sphinx/2.0.3/mysql-5.5.9/libmysql
make

You can see I downloaded the Sphinx and MySQL 5.5.9 sources to a directory buried in the Applications directory. I specified the includes directory as well as the client directory. Change these to your paths as needed. When its complete, you should have a bunch of new directories and files in the –prefix path. searchd is the search daemon in the bin directory.

Now, its off to try and leverage Sphinx!

UPDATE: I want to point out that you should typically compile the thread safe versions if the MySQL client. The Cmake script configures to compile both, thread safe and thread unsafe. I assume sphinx uses the thread-safe libraries, or at least knows its using unsafe versions on purpose. Hit tip to Chris Sebastian.

 

PHP Implementation of Haversine Computation

December 17th, 2011 by Eric Cope

We needed to compute the distance between two points on the Earth using longitude and latitude from Google’s Geocode API service. We use PHP, but there was no reference to a PHP implementation of the Haversine Equation, so I made one. I needed miles, but if you need another unit, just replace $earth_radius with the appropriate value. Enjoy!

public function distance($long_1,$lat_1,$long_2,$lat_2)
{
$earth_radius = 3963.1676; // in miles

$sin_lat   = sin(deg2rad($lat_2  - $lat_1)  / 2.0);
$sin2_lat  = $sin_lat * $sin_lat;

$sin_long  = sin(deg2rad($long_2 - $long_2) / 2.0);
$sin2_long = $sin_long * $sin_long;

$cos_lat_1 = cos($lat_1);
$cos_lat_2 = cos($lat_2);

$sqrt      = sqrt($sin2_lat + ($cos_lat_1 * $cos_lat_2 * $sin2_long));

$distance  = 2.0 * $earth_radius * asin($sqrt);

return $distance;
}
 

Making a Push Notification Server

December 8th, 2011 by Eric Cope

We had a need to test locally an endpoint of a SaaS Push Service. We did not want to rely on the SaaS for testing, so we needed a way to generate an equivalent push locally. This method requires a PECL extension, pecl_http. On a side note, I had to download the PHP source files to my MAMP installation, but that’s another story.

Once pecl_http was installed, it was very easy.


<?php
if(isset($_POST['data'])){
$data = $_POST['data'];
$info = '';
$response = http_post_data('http://localhost/path/to/endpoint', $data,array(0,$info));
echo $response;
}
?>
<html><body>
<form action="#" method="post">
<textarea name="data" rows="10" cols="40"><?php echo stripslashes($_POST['data']); ?></textarea><br />
<input type="submit"></input><br />
</form>
</body></html>

Its as easy as that. You can serialize, json, xml, your data before you send it, then interpret it when you receive it. Of course, be sure to santize your inputs!

 

PHP Exceptions and CodeIgniter

December 8th, 2011 by Eric Cope

I’ve been toying around with PHP’s Exceptions for a number of years now. I never found a clean way to integrate them into my CodeIgniter codebases, until now. I learned about PHP’s SPL Exception library recently as well, so it was a bit of a motivator.

I updated my models and libraries to throw exceptions, rather than my custom error structures. Here is an example model.

class some_model extends CI_Model {
	public function add()
	{
		some_logic();
		if($some_error == TRUE){
			throw new Exception('my exception message',1234);
		}
		more_logic();
		if($some_other_error == TRUE){
			throw new Exception('my 2nd exception message',1234);
		}
		return my_response();
	}
}

Now in my controller, I put:

class MY_Controller extends CI_Controller
{
	public function controller_method()
	{
		$this->load->model('some_model');
		try {
			some_more_logic();
			$expected_response = $this->some_model->add();
			more_logic_assuming_expected_response_is_valid($expected_response);
		} catch (Exception $e) {
			do_behavior_for_exceptions();
		}
	}
}

In my controller method, I wrap the entire controller code in a try/catch loop to catch systematic errors, like database errors, function input validation errors, and other fatal errors. If I have other reasons to throw an exception, then I can add additional try/catch blocks.

Also, because exceptions are classes, you can extend them and perform common logic from within the exception’s constructor when its thrown.

For more information, see the PHP manual, or give us a holler.

 

PHPUnit’s CodeCoverage and CodeIgniter

December 4th, 2011 by Eric Cope

We have not figured out how to integrate PHPUnit well into our projects, especially when CI’s unit test library is so handy. However, I did take the time to try using PHPUnit’s CodeCoverage metric. However, in order to get it to work, I had to blacklist the CI system directory (the application directory is outside the system directory). It took some debugging, but here is how to do that.

To black list a directory:

$filter  = new PHP_CodeCoverage_Filter;
$filter->addDirectoryToBlacklist('/path/to/system');
$filter->addDirectoryToBlacklist('/path/to/app/logs');
$coverage = new PHP_CodeCoverage(null,$filter);

You have to create a new CodeCoverage_Filter object, add the blacklisted directories, then pass that object to the PHP_CodeCoverage constructor.

I still want to determine why I had to blacklist the system directory. But until then, this is good and generating the reports I am looking for.