composer require laravel/scout
composer require teamtnt/tntsearch
composer require teamtnt/laravel-scout-tntsearch-driver
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
静的ページを全文検索させるインデックスを作成する
php artisan make:command IndexStaticPages
<?php
// app/Console/Commands/IndexStaticPages.php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Services\StaticPageIndexer;
class IndexStaticPages extends Command
{
protected $signature = 'search:index-static-pages {directory?}';
protected $description = 'Index static HTML files for full-text search';
public function handle()
{
$directory = $this->argument('directory') ?? public_path();
$this->info("Indexing HTML files from: {$directory}");
$indexer = new StaticPageIndexer();
$result = $indexer->indexHtmlFiles($directory);
$this->info("Successfully indexed {$result['count']} HTML files");
}
}
マイグレーションファイルの作成
php artisan make:migration add_table_static_pages --table=static_pages
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
/**
* 静的HTMLページテーブルのマイグレーション
* TNTSearch + Laravel Scout対応
* Laravel 7対応版
*/
class CreateStaticPagesTable extends Migration
{
/**
* マイグレーション実行
*/
public function up()
{
Schema::create('static_pages', function (Blueprint $table) {
$table->id();
// ファイル情報
$table->string('file_path', 500)->unique()->comment('ファイルの絶対パス');
$table->string('url', 500)->index()->comment('WebアクセスURL');
$table->unsignedBigInteger('file_size')->default(0)->comment('ファイルサイズ(バイト)');
$table->timestamp('last_modified')->nullable()->comment('ファイル最終更新日時');
// メタ情報
$table->string('title', 500)->index()->comment('ページタイトル');
$table->text('description')->nullable()->comment('メタディスクリプション');
$table->text('keywords')->nullable()->comment('メタキーワード');
$table->string('language', 10)->default('ja')->index()->comment('言語コード');
$table->string('charset', 50)->default('UTF-8')->comment('文字エンコーディング');
// コンテンツ(全文検索対象)
$table->longText('content')->comment('HTMLから抽出したテキストコンテンツ');
// タイムスタンプ
$table->timestamps();
// インデックス
$table->index(['title', 'language'], 'idx_title_language');
$table->index(['last_modified', 'updated_at'], 'idx_modified_times');
$table->index(['file_size'], 'idx_file_size');
$table->index(['url', 'language'], 'idx_url_language');
});
// 全文検索用インデックス(MySQLの場合)
if (config('database.default') === 'mysql') {
// Laravel 7では個別にSQL実行
DB::statement('ALTER TABLE static_pages ADD FULLTEXT fulltext_title_content (title, content)');
DB::statement('ALTER TABLE static_pages ADD FULLTEXT fulltext_title (title)');
DB::statement('ALTER TABLE static_pages ADD FULLTEXT fulltext_content (content)');
DB::statement('ALTER TABLE static_pages ADD FULLTEXT fulltext_description (description)');
}
// テーブルコメント
DB::statement("ALTER TABLE static_pages COMMENT = '静的HTMLページの全文検索用インデックステーブル'");
}
/**
* マイグレーション巻き戻し
*/
public function down()
{
Schema::dropIfExists('static_pages');
}
}
マイクレーションの実行
php artisan migrate
実行
php artisan search:index-static-pages ディレクトリ名フルパス --dry-run --recursive