Installation:
composer require crwlr/query-string
Basic Usage:
use Crwlr\QueryString\Query;
// From string
$query = new Query('foo=bar&baz[]=qux');
$array = $query->toArray(); // ['foo' => 'bar', 'baz' => ['qux']]
// From array
$query = new Query(['foo' => 'bar', 'baz' => ['qux']]);
$string = $query->toString(); // 'foo=bar&baz%5B0%5D=qux'
First Use Case:
Parse and reconstruct query strings from Laravel Request objects:
use Illuminate\Http\Request;
use Crwlr\QueryString\Query;
$requestQuery = new Query(request()->query->all());
$modifiedQuery = $requestQuery->set('page', 2)->toString();
Query class methods (set(), get(), has(), remove(), toArray(), toString()) for core functionality.Parse Laravel Request query strings into structured arrays:
$query = new Query(request()->query->all());
$page = $query->get('page', 1); // Default fallback
$filters = $query->get('filter', []); // Nested arrays
Build query strings for redirects or API calls:
$query = new Query(['page' => 2, 'sort' => ['name', 'asc']]);
$url = route('products.index', ['query' => $query->toString()]);
Handle multi-select or repeated fields (e.g., tags[]=php&tags[]=laravel):
$query = new Query(request()->post());
$tags = $query->get('tags', []); // ['php', 'laravel']
Normalize external query strings (e.g., Google Fonts):
$externalQuery = new Query('family=Roboto&family=Open+Sans');
$normalized = $externalQuery->toArray(); // ['family' => ['Roboto', 'Open Sans']]
Bind the Query class to Laravel’s container for global use:
// app/Providers/AppServiceProvider.php
use Crwlr\QueryString\Query;
public function register()
{
app()->bind(Query::class, function () {
return new Query(request()->query->all());
});
}
Usage:
$query = app(Query::class);
Extend Laravel’s Request class with query string helpers:
// app/Providers/AppServiceProvider.php
use Illuminate\Http\Request;
use Crwlr\QueryString\Query;
public function boot()
{
Request::macro('queryString', function () {
return new Query($this->query->all());
});
}
Usage:
$query = request()->queryString();
$page = $query->get('page', 1);
Validate query strings in Laravel’s FormRequest:
use Crwlr\QueryString\Query;
use Illuminate\Foundation\Http\FormRequest;
class ProductRequest extends FormRequest
{
public function rules()
{
$query = new Query($this->query->all());
return [
'page' => ['required', 'integer', Rule::when(
$query->has('sort'),
fn () => 'max:100'
)],
];
}
}
toArray() with Query to maintain key-value order (unlike http_build_query).foo[bar][]=baz) for complex structures.toString() (e.g., spaces → + or %20).get() with fallback:
$query->get('page', 1); // Returns 1 if 'page' is missing
Duplicate Keys Without Brackets:
foo=bar&foo=baz defaults to ['foo' => 'baz'] (last value wins).[] notation (foo[]=bar&foo[]=baz) or rely on v1.0.2+ behavior (auto-converts to array).toArray() output to verify structure.Malformed Strings:
&foo=bar or foo=bar& may cause parsing errors.trim() or validate input:
$query = new Query(trim($_GET['query']));
Nested Array Indices:
foo[bar][]=baz may not serialize as expected in older versions.$query->set('foo[bar][0]', 'baz');
URL Encoding Inconsistencies:
toString() may encode + as %20 or (space).str_replace('+', ' ', $query->toString());
$query = new Query('foo=bar&baz[]=qux');
dump($query->toArray()); // ['foo' => 'bar', 'baz' => ['qux']]
$array = $query->toArray();
$string = $query->toString();
assert($query->fromString($string)->toArray() === $array);
// Empty values
$query = new Query('foo='); // ['foo' => '']
// Trailing &
$query = new Query('foo=bar&'); // ['foo' => 'bar']
php -v before use.Query in cached views, serialize with toArray():
cache()->put('query', $query->toArray());
$query = new Query(['foo' => 'bar baz'], [
'encoder' => fn ($value) => str_replace(' ', '-', $value),
]);
$query = new Query(['foo' => null]);
$string = $query->toString(); // 'foo=' (not omitted)
Query with events (e.g., beforeSet, afterToString) via traits or decorators.toString().toArray() loads the entire query into memory; use get() for selective access.http_build_query/parse_str for critical paths:
$time = microtime(true);
$query->toString();
echo microtime(true) - $time; // ~0.0001s for 100 keys
Request methods (e.g., query()) to prevent conflicts.toArray() for query string parameters in routes:
Route::get('/products', function (Query $query) {
return Product::where('name', 'like', '%' . $query->get('search') . '%')->get();
})->bind('query');
Query objects in JSON responses:
How can I help you explore Laravel packages today?