bitandblack/word-extract
Extract and process words from text by minimum length. Get matching words as an array or apply a callback to transform each extracted word within the original string. Simple PHP library installable via Composer.
Install the package via Composer:
composer require bitandblack/word-extract
First Use Case: Extract words with a minimum length from a string (e.g., user-generated content, blog posts, or search queries).
use BitAndBlack\WordExtract\WordExtractor;
// Initialize with minimum word length (e.g., 5 characters)
$extractor = new WordExtractor(5);
// Extract words from a string
$words = $extractor->getWords('Laravel is an amazing PHP framework');
/*
Output:
[
'amazing', // 7 chars
'framework' // 9 chars
]
*/
Where to Look First:
WordExtractor class: Core functionality for extraction and word handling.getWithWordsHandled() to transform words (e.g., wrap in HTML, log, or validate).Use getWords() to filter words by minimum length in:
$extractor = new WordExtractor(4);
$keywords = $extractor->getWords('The quick brown fox jumps over the lazy dog');
/*
Output:
[
'quick', 'brown', 'fox', 'jumps', 'lazy', 'dog'
]
*/
Process extracted words dynamically (e.g., logging, sanitization, or enrichment):
$handler = fn(string $word) => "<strong>{$word}</strong>";
$highlighted = $extractor->getWithWordsHandled(
'Laravel is powerful',
$handler
);
/*
Output: "Laravel is <strong>powerful</strong>"
*/
Register as a singleton for app-wide access:
// app/Providers/AppServiceProvider.php
public function register(): void {
$this->app->singleton(WordExtractor::class, fn() =>
new WordExtractor(config('word-extractor.min_length'))
);
}
Access via dependency injection:
public function __construct(private WordExtractor $extractor) {}
Create a facade for cleaner syntax:
// app/Facades/WordExtractorFacade.php
public static function extract(string $text): array {
return resolve(WordExtractor::class)->getWords($text);
}
Usage:
$keywords = WordExtractorFacade::extract('Extract keywords here');
Batch-process files (e.g., logs, CSV exports):
// app/Console/Commands/ExtractKeywords.php
public function handle(): void {
$files = Storage::files('path/to/texts');
foreach ($files as $file) {
$content = file_get_contents($file);
$keywords = $this->extractor->getWords($content);
// Save or log $keywords
}
}
Preprocess incoming requests (e.g., extract keywords from form data):
// app/Http/Middleware/ExtractKeywords.php
public function handle(Request $request, Closure $next) {
$keywords = $this->extractor->getWords($request->input('content'));
$request->merge(['keywords' => $keywords]);
return $next($request);
}
Trigger extraction on model events (e.g., created for blog posts):
// app/Listeners/ExtractPostKeywords.php
public function handle(Created $event) {
$keywords = $this->extractor->getWords($event->post->content);
$event->post->update(['keywords' => json_encode($keywords)]);
}
Store min_length in config/word-extractor.php:
return [
'min_length' => env('WORD_EXTRACT_MIN_LENGTH', 5),
];
Access via:
$extractor = new WordExtractor(config('word-extractor.min_length'));
Mock the extractor in Laravel tests:
// tests/Feature/KeywordExtractionTest.php
public function test_extracts_keywords() {
$extractor = Mockery::mock(WordExtractor::class);
$extractor->shouldReceive('getWords')
->with('Test content')
->andReturn(['Test', 'content']);
$this->app->instance(WordExtractor::class, $extractor);
// Test your logic...
}
Unicode/Non-Latin Characters:
café, über).mb_split() or use preg_split('/\p{L}+/u').$words = preg_split('/\p{L}+/u', $text, -1, PREG_SPLIT_NO_EMPTY);
Hyphenated Words:
state-of-the-art → state, of, the, art).Performance with Large Texts:
Dependency on bitandblack/helpers:
bitandblack/helpers (v2.0+), which may introduce hidden dependencies.helpers for conflicts (e.g., global functions overriding Laravel’s).Edge Cases in Word Splitting:
don't → don, t) or contractions may split unintentionally.PHP 8.2+ Requirement:
Log Extracted Words:
$words = $extractor->getWords($text);
Log::debug('Extracted words', ['words' => $words]);
Validate Input:
Ensure input is a string to avoid TypeError:
if (!is_string($text)) {
throw new InvalidArgumentException('Input must be a string');
}
Test with Edge Cases:
$testCases = [
'Unicode: café, über', // Fails without Unicode support
'Hyphenated: state-of-the-art', // Splits hyphens
'Contractions: don\'t, can\'t', // Splits apostrophes
'Numbers: 12345', // Treats as word if ≥ min_length
];
Profile Performance: Use Laravel Debugbar or Xdebug to measure extraction time for large texts.
Custom Word Splitting:
Override the default splitWords() method:
class CustomWordExtractor extends WordExtractor {
protected function splitWords(string $text): array {
return preg_split('/\W+/', $text, -1, PREG_SPLIT_NO_EMPTY);
}
}
Add Stopword Filtering: Extend the class to exclude common words:
class StopwordAwareExtractor extends WordExtractor {
private array $stopwords = ['the', 'and', 'is'];
public function getWords(string $text): array {
$words = parent::getWords($text);
return array_filter($words, fn($word) => !in_array(strtolower($word), $this->stopwords));
}
}
Integrate with Laravel Cache: Cache extraction results for repeated queries:
public function getWords(string $text): array {
$cacheKey = 'word_extract:' . md5($text);
return Cache::remember($cacheKey, now()->addHours(1), function() use ($text) {
return parent::getWords($text);
});
}
Add Language Support:
Use mb_split() for multilingual text:
protected function splitWords(string $text): array {
return mb_split('/\p{L}+/u', $text, -1, MB_SPLIT_NO_EMPTY);
}
Default min_length:
The package has no default; always specify a value in the constructor or config.
Case Sensitivity:
Extraction is case-sensitive (e.g., Laravel and laravel are treated as different words).
Workaround: Normalize case before extraction:
$ext
How can I help you explore Laravel packages today?