Product Decisions This Supports
- Feature: automatic categorization of user-generated content. Support ticket triage, email routing, listing categorization, content moderation flags, lead scoring. The package gives a trainable multinomial naive Bayes classifier in pure PHP — no external ML service, no Python runtime, no per-request inference cost beyond local CPU.
- Build vs. buy. The realistic alternatives are (a) pay for a hosted classification API (AWS Comprehend, Google NL, OpenAI-class LLM calls), (b) run a Python microservice with scikit-learn, or (c) ship a rules/keyword engine. This package occupies the "ship something this sprint, zero infra" slot. It is the correct choice when classification volume is moderate, latency budget is tight, and data cannot leave the app's infrastructure.
- Roadmap sequencing. Good stepping stone before a real ML platform investment. Ships a working classifier, generates labelled training data as a by-product of usage, and keeps the interface small enough to swap out later. Treat it as a 1–2 quarter bridge, not a permanent architecture bet.
- Use cases that fit cleanly: spam/abuse pre-filtering, inbound email intent routing, support ticket priority tagging, product/category suggestion from free text, sentiment bucketing on short reviews. Use cases that do not fit: anything needing contextual or semantic understanding (multi-turn intent, entity extraction, summarisation), long documents, or classes with heavy overlap and thin training data.
- Scope guardrail. This is a classifier library, not a platform. No model versioning, no drift monitoring, no retraining pipeline, no evaluation harness. Product must budget for those as in-house work — they are not in the box.
When to Consider This Package
Adopt when most of the following hold:
- You are on Laravel/PHP and want classification to live in the monolith — no new service, no new deploy target, no new on-call surface.
- Your classes are reasonably separable and you can supply a few hundred to a few thousand labelled examples per class. Accuracy degrades predictably as classes overlap; naive Bayes' independence assumption is a real limit on nuanced categories.
- You need per-item inference in single-digit milliseconds and want to avoid network hops to a third-party API.
- Data residency, cost-per-call, or vendor-approval friction rules out hosted APIs.
- You want a baseline number quickly. A trained naive Bayes model is often the cheapest way to establish "is this problem even tractable?" before committing engineering headcount.
Look elsewhere when:
- You need semantics, not token statistics — transformers/embeddings or an LLM API will outperform this on intent, sentiment nuance, and short or ambiguous text.
- You need multilingual robustness without building per-language tokenisation yourself.
- You need structured extraction (names, dates, amounts) rather than bucketing.
- You need online learning at high throughput or models large enough that PHP memory and serialisation become the bottleneck.
- You require vendor-backed SLAs, security review artefacts, or a support contract.
Version note for 2.0.2: the release only widens the brick/math constraint from ^0.18 to ^0.18 || ^0.20. This is not a feature or a breaking change, but it is the one thing that matters for adoption: projects on Laravel 11/12 or PHP 8.4 that already pull brick/math 0.20 (via ramsey/uuid, money libraries, or Laravel internals) previously hit a Composer conflict. That constraint is now resolved on 2.x. If you evaluated an earlier 2.0.x and bounced on dependency resolution, re-run composer require — it should now install cleanly. Pin to ^2.0.2 rather than a floating constraint so the peer range stays predictable.
How to Pitch It (Stakeholders)
To executives (one paragraph): We can add automatic text classification — routing, tagging, moderation pre-screening — without buying an ML platform, hiring a data scientist, or sending customer data to a third party. It is a small, mature PHP library that runs inside our existing Laravel application, so there is no new infrastructure, no per-request API spend, and no new vendor to onboard or security-review. Cost is measured in engineering days, not contract values. It is deliberately scoped as a first classifier, not a final one: it establishes a baseline accuracy number and starts accumulating the labelled data any future ML investment would need anyway. If we later outgrow it, the swap is contained to one service class.
To engineering: Pure-PHP multinomial naive Bayes, installs via Composer, trains and predicts in-process. No queue, no Redis, no Python sidecar. Training fits naturally into an artisan command; predictions are synchronous and fast enough to run inline. Persist the trained model (the package serialises the classifier) so you retrain on a schedule rather than per request. Keep the classifier behind an interface — Classifier::classify(string $text): string — so the implementation is replaceable. The 2.0.2 release is a dependency-only change that widens the brick/math peer constraint to accept 0.20, which unblocks installs on newer Laravel stacks that already depend on it; pin ^2.0.2, run the test suite, and treat it as a low-risk patch. Do not expect accuracy parity with embedding-based approaches on nuanced or short text — set expectations accordingly and instrument precision/recall per class from day one.