Implementing Full-Text search in Laravel



In this tutorial I will go over implementing Full-Text search in Laravel 4 .
Those who have used Laravel 3 in the past may remember that there used to be support for FULLTEXT indexes. This functionality has been removed in Laravel 4 but can still easily be implemented.

Be aware however that Full-Text search is not compatible with every database server, or may work differently. This is the main reason why it has been removed from Laravel 4. However if you use MySQL you will be able to use it without a problem!

What to know about Full-Text

MySQL has support for full-text indexing and searching:

  • A full-text index in MySQL is an index of type FULLTEXT.
  • Full-text indexes can be used only with MyISAM tables. (In MySQL 5.6 and up, they can also be used with InnoDB tables.) Full-text indexes can be created only for CHAR, VARCHAR, or TEXT columns.
  • FULLTEXT index definition can be given in the CREATE TABLE statement when a table is created, or added later using ALTER TABLE or CREATE INDEX.
  • For large data sets, it is much faster to load your data into a table that has no FULLTEXT index and then create the index after that, than to load data into a table that has an existing FULLTEXT index.

How to implement Full-Text search in Laravel

To start implementing Full-Text search in Laravel 4 we will have to take care of a few things:

  • If you are not using MySQL 5.6+ we must set the Database Engine to MyISAM instead of InnoDB.
  • We have to set up the migration and add the Full-Text index.
  • We must add a search function in our controller.

Migrating our table

Migrating our table is simple. We can use the following scheme to set up a posts table with the title and body columns as FULLTEXT index:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;

class CreatePostsTable extends Migration {

	/**
	 * Run the migrations.
	 *
	 * @return void
	 */
	public function up()
	{
		Schema::create('posts', function(Blueprint $table) {
			$table->engine = 'MyISAM'; // means you can't use foreign key constraints
			$table->increments('id');
			$table->string('title');
			$table->text('body');
			$table->timestamps();
		});

		DB::statement('ALTER TABLE posts ADD FULLTEXT search(title, body)');
	}

	/**
	 * Reverse the migrations.
	 *
	 * @return void
	 */
	public function down()
	{
		Schema::table('posts', function($table) {
	    	$table->dropIndex('search');
		});
		Schema::drop('posts');
	}

}

In the code above you can see we have also set the Storage Engine in the migration to MyISAM.
The FULLTEXT index is set after creating the table using an ALTER TABLE statement.



In the down() function we first drop the Full-Text index and then drop the table.

Adding a search function to our controller

Next we need to add a search function to our controller. We will be using a POST request for this. We name the function postSearch so that we can route to it appropriately.

public function postSearch()
{
	$q = Input::get('query');

	$posts = $this->post->whereRaw(
		"MATCH(title,body) AGAINST(? IN BOOLEAN MODE)", 
		array($q)
	)->get();

	return View::make('posts.index', compact('posts'));

}

Now for example, if your query parameter would be “testing”, you would get the following MySQL query:

SELECT * FROM `posts` WHERE MATCH(title,body) AGAINST('testing' IN BOOLEAN MODE);

In this example I also take the result and pass it to my index view. You could just as well use a different view.

Adding the route and modifying the view

We set up our route like this:

Route::post(
    'posts/search', 
    array(
        'as' => 'posts.search', 
        'uses' => 'PostsController@postSearch'
    )
);

And we can create a simple form in a view like this:

<div class="search">
	{{ Form::model(null, array('route' => array('posts.search'))) }}
	{{ Form::text('query', null, array( 'placeholder' => 'Search query...' )) }}
	{{ Form::submit('Search') }}
	{{ Form::close() }}
</div>

All we need for this is a textfield with the parameter name set to query (or whatever you decided to pick as input name in your controller).

That’s it!

You have now learnt how to implement MySQL Full-Text search in Laravel 4.

If you liked this tutorial, be sure to show your love by sharing this post on your social networks.

Feel free to leave me some feedback or questions in the comments area.

Share the knowledge!
Share on Facebook0Tweet about this on Twitter0Share on Google+16Share on StumbleUpon625Share on Reddit0Share on LinkedIn0Share on TumblrBuffer this pageDigg this

Comments

You may also like...

Stay updated
Subscribe!