Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Sliceable Stringy Laravel Package

danielstjules/sliceable-stringy

Stringy is a PHP string manipulation library with full multibyte support, offering a fluent API for camelCase, snake_case, slugs, truncation, and more. The sliceable variant adds JavaScript-style string slicing.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install with Composer. The package is on Packagist as danielstjules/sliceable-stringy and pulls in danielstjules/stringy as its base class. Pin the version in composer.json so a future Packagist change can't surprise you:

    composer require danielstjules/sliceable-stringy:^1.0
    

    Since the last release was 2014, treat it as a vendored, unmaintained dependency: commit composer.lock and be prepared to fork if you need PHP 8 fixes.

  2. Where to look first.

    • src/SliceableStringy.php — the whole feature lives here; it extends Stringy and adds slice parsing.
    • tests/ — the fastest way to confirm exact syntax (brackets vs. bare start:stop, step support, negative-index behaviour). Read the tests before trusting the README.
    • The parent danielstjules/stringy README for the ~60 string methods you inherit for free (chars, upper, contains, etc.).
  3. First use case. Anywhere you currently hand-roll substr($s, $start, $stop - $start) with offset math — especially when the range itself is user-supplied (report column ranges, template expressions, log-slice tools, fixed-width file parsing). Python-style slicing turns that into a single, readable call:

    use SliceableStringy\SliceableStringy;
    
    $s = SliceableStringy::create('Hello World');
    
    echo $s->slice('[0:5]');   // "Hello"
    echo $s->slice('[-5:]');   // "World"
    echo $s->slice('[::2]');   // "HloWrd"
    

Implementation Patterns

Basic positive and negative ranges. The whole point is that start is inclusive, stop is exclusive, and negatives count from the end — exactly like Python.

$s = SliceableStringy::create('abcdefghij');

$s->slice('[2:4]');    // "cd"
$s->slice('[:3]');     // "abc"
$s->slice('[7:]');     // "hij"
$s->slice('[-3:]');    // "hij"
$s->slice('[-6:-3]');  // "efg"

Step slicing. A third segment steps through the string; a negative step reverses it.

$s->slice('[::2]');    // "acegi"
$s->slice('[1::3]');   // "beh"
$s->slice('[::-1]');   // "jihgfedcba"

Chain with inherited Stringy methods. Because SliceableStringy is a Stringy, you can slice and then continue with the rich API rather than dropping back to raw strings:

$initials = SliceableStringy::create($fullName)
    ->slice('[0:1]')
    ->upper();

Wrap it in an application service. Never let slice syntax leak into every call site. Put the parsing behind one small class so you can swap the implementation later (see Gotchas):

final class FieldRangeExtractor
{
    public function extract(string $value, string $range): string
    {
        return SliceableStringy::create($value)->slice($range)->__toString();
    }
}

Inject this adapter where you need it, and write a contract test against it with a data provider covering [0:1], [:-1], [::2], [100:], [-1:0], etc. That test suite becomes your safety net when you eventually migrate off this package.

Templating / user-facing syntax. If you're exposing ranges to users (e.g. a Twig filter or a saved report config), validate the expression before calling slice(), because out-of-range and malformed input handling is where the library is weakest:

if (!preg_match('/^\[-?\d*:-?\d*(?::-?\d+)?\]$/', $range)) {
    throw new InvalidArgumentException("Invalid slice: {$range}");
}

Fixed-width parsing. Combine slicing with Stringy::chars() or repeated calls when parsing flat files:

$record = SliceableStringy::create($line);
$id   = $record->slice('[0:8]');
$name = $record->slice('[8:38]');

Gotchas and Tips

  • It's abandoned (last release 2014). The author archived Stringy in favour of symfony/string, and this package followed. Don't build new architecture on it without a migration plan; do use it for a short, well-tested utility class.
  • PHP 8 compatibility is not guaranteed. The 2014 codebase predates scalar type hints, ??, and many deprecations in mb_* and Stringy. Test on your target PHP version before committing; if it breaks, fork and patch the one class you actually use.
  • Multibyte handling depends on the parent. Verify whether slicing uses mb_substr (bytes/characters mismatch is a classic bug). Add a test with UTF-8 input like 'héllo' and with emoji before trusting it in user-facing code.
  • Slice semantics are close to Python, not identical. Test edge cases explicitly: [5:2] (empty?), [::0] (error?), [100:] (empty string?), and whitespace inside brackets. The parser may silently return '' on malformed input instead of throwing.
  • Syntax quirks. Confirm from the tests whether brackets are required ('[1:3]') or optional ('1:3'), and whether the parser accepts spaces ('[1 : 3]'). Pick one form in your codebase and validate against it.
  • Performance. Every slice() call runs a regex/parse over the expression. For hot loops (parsing thousands of lines), precompute integer offsets once and call substr/mb_substr directly, or cache the parsed slice object per expression.
  • Decouple early. Write your own RangeSlicer interface now with a SliceableStringy implementation behind it. When you migrate to symfony/string (which has slice() and splice()), or a 10-line substr helper, you swap one class instead of hunting call sites.
  • Debugging. When a range returns something unexpected, var_dump((string) $s) alongside strlen($s) — the length is usually the culprit (bytes vs. characters, or a trailing newline from the source file).
  • Licence. MIT, so vendoring a patched copy into src/ or a forks/ directory is legally fine — and is often the pragmatic answer for a 47-star, decade-old dependency.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package