Download the PHP package phpcpd-next/phpcpd without Composer

On this page you can find all versions of the php package phpcpd-next/phpcpd. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package phpcpd

phpcpd-next

Token-based copy/paste detection for PHP 8.5+ — a maintained successor to phpcpd, with reorder-tolerant (Type-3) detection.

A maintained, dependency-free successor to the archived sebastianbergmann/phpcpd. It finds duplicated code — and, unlike most copy/paste detectors, it ships three complementary detection engines so it can see exact copies, reordered clones, and gapped near-misses.

Drop-in replacement: the command is still phpcpd. Out of the box it runs Rabin-Karp + TokenBag (exact and reordered duplication); the classic Rabin-Karp-only behaviour is one flag (--rk) away. The deeper research engines are opt-in.

Features at a glance


Why another clone detector?

The common wisdom is that phpcpd only finds Type-1/2 (exact / renamed) clones. That was only ever true of its default engine. phpcpd-next exposes and extends the full picture:

Clone type Example Engine Availability
Type-1 exact identical code rabin-karp default
Type-3 reordered statements shuffled within a function tokenbag default
Type-3 gapped a statement inserted/deleted/changed suffixtree advanced (--algorithm)
Type-2 renamed same code, different identifiers any engine advanced (--fuzzy)

The two default engines run together on every phpcpd <dir> invocation. The Type-3-gapped and Type-2 capabilities are research-grade and opt-in (see Advanced engines).

The suffix-tree engine additionally flags inconsistent clones — near-miss copies that have diverged — which is where duplication tends to hide bugs (one copy patched, its sibling not).

Requirements

Zero Composer dependencies. Nothing from the PHPUnit/sebastian release train at runtime.

Installation

Install as a dev dependency from Packagist:

This installs the phpcpd binary to vendor/bin/phpcpd:

Or run it without adding it to your project, via Composer's global bin or a one-off:

From source:

Requires PHP 8.5+ with ext-dom and ext-mbstring. Zero runtime dependencies — nothing from the PHPUnit/sebastian release train is pulled in.

Quick start

phpcpd-next exits with status 1 when clones are found (or on error) and 0 when none are — so it works as a CI gate out of the box.

What a run looks like

Each clone is followed by a context-aware refactoring hint — the suggestion adapts to the clone (test scaffolding, a large block, a diverged near-miss, or a plain extract). The closing summary reports the duplicated-line percentage and the average/largest clone size. Add --verbose to print the duplicated source itself.

Detection engines

Default: Rabin-Karp + TokenBag

Every phpcpd <dir> run executes two engines and merges their results:

They are complementary: Rabin-Karp is precise about structure; the token bag tolerates shuffling. Pass --rk to run Rabin-Karp alone (faster, no reorder detection).

Advanced engines / research

These are opt-in via the (hidden) --algorithm flag and its tuning knobs. They are research-grade — powerful on the right corpus, but with higher false-positive rates on real-world code, which is why they are not in the default set or in --help.

Orphan detection (dead code)

Clones are duplicated code; orphans are unreachable code — a class, interface, trait, enum, or global function that nothing references. Same token engine, no parser, no AST, no runtime dependency.

Two modes:

Each finding is explained, not just listed:

Two confidence tiers, so the tool never nags you into deleting live code:

Tier Meaning Exit code
Definite Referenced nowhere; safe to delete. Non-zero (CI gate)
Possible A contract (interface / abstract) an out-of-tree package may implement, or a name that appears only in a string literal (a candidate for new $class / a DI-container id). Zero (report only)

What it won't false-alarm on — framework entry points are reachable even when unreferenced:

Scope, honestly. Orphan detection stops at the type/function level — the "unreferenced file" case. Method- and property-level dead code needs whole-program type inference (which class does $this->handle() resolve to under inheritance and a DI container?); that is PHPStan + Psalm's job, and this token-based tool deliberately does not guess at it. What it does do — decide whether a named type or function is ever mentioned at all — it does safely: reference detection is generous by design, so it prefers to stay silent over flagging something that is used. Point it at a whole project (including bin/, entry scripts, and config) so legitimate roots are seen as referenced.

Laravel and other convention-driven frameworks. Treat orphan output as review candidates, not a delete list. Laravel reaches many classes with no by-name reference, and they fall into three buckets: [Controller::class, 'method'] routes, $listen/$subscribe arrays and app(Foo::class) all use ::class, which counts as a real reference; string-based references (string route actions, class names in config/, container bindings) are demoted to possibleas long as you scan those files too (routes/, config/); but convention/auto-discovery (policies, Livewire/Filament components, commands loaded via load(), model observers) leaves classes with no textual mention at all, and those will false-positive. This is exactly why orphans are advisory in the default run — scan the whole app, lean on the possible tier, and reach for --orphans (the gating mode) on code you control.

Embed it the same way as clone detection:

Output formats

The console report is human-readable and always printed; add --verbose to print the duplicated source of each clone. Machine-readable reports are written to a file in parallel:

Format Flag For
Console (text) (default) humans; add --verbose for the duplicated snippet
PMD-CPD XML --log-pmd=<file> Jenkins, SonarQube, and other PMD-CPD consumers
JSON --log-json=<file> scripts and custom dashboards (tool, version, summary, clones[])
SARIF 2.1.0 --log-sarif=<file> GitHub Code Scanning / the Security tab

You can request several at once. SARIF maps inconsistent clones to warning and exact clones to note, so the bug-bearing duplication surfaces at a higher severity.

GitHub Code Scanning

Clones then appear as annotations in the PR and in the repository's Security tab. (Swap in --algorithm=suffixtree if you also want gapped/inconsistent clones surfaced.)

Options

The full set shown by phpcpd --help:

Advanced / research flags

Parsed but hidden from --help — research-grade, see Advanced engines:

Framework presets

A preset is a named bundle of sensible defaults — scan paths, file suffixes, and exclude patterns — for a given framework. It is pure configuration: no runtime dependency, no change to how detection works, so it stays faithful to the zero-dependency, deterministic core. Presets exist because every framework has predictable noise (generated caches, scaffolded CRUD, migration boilerplate) that buries real findings; a preset encodes that knowledge once.

Explicit flags always win: a preset seeds the defaults, then --exclude and --suffix append to it and --min-lines / --min-tokens override it. Passing a directory overrides the preset's default paths (its excludes still apply):

Preset Scans Skips
laravel app routes database config vendor, node_modules, storage, bootstrap/cache, public, *.blade.php, database/migrations, IDE-helper files

Presets are declared in one place (src/Presets.php); adding a framework is a single Preset entry that the CLI, --help, and the headless API all pick up.

Laravel via Artisan (optional)

There is no Laravel runtime dependency in phpcpd-next, and there does not need to be — --preset=laravel is the integration. If you want php artisan ergonomics, a few lines in your app wire the headless API (below) into a command; no extra package required:

Embedding phpcpd-next (headless mode)

Tools that want clone detection in-process — a PHPUnit assertion, an Artisan command, a custom CI script — call the headless API instead of shelling out to the binary. It finds files, runs the same engine the CLI uses, and returns the raw CodeCloneMap; there is no banner, no argv parsing, and no file I/O, so it is safe to call repeatedly in one process.

PHPUnit integration

Make duplication a regression test: a clone introduced in a pull request turns the build red, with the offending locations printed in the failure message. Drop in the shipped trait:

On failure:

The trait and the underlying DuplicationConstraint live in integration/phpunit/, autoloaded under LucianoPereira\PhpcpdNext\PHPUnit\ once phpcpd-next is a require-dev of your project. phpcpd-next dogfoods it: its own tests/SelfDryTest.php uses this exact trait to keep src/ duplication-free across all three engines.

Incremental caching (CI)

--cache stores the run's results keyed by a fingerprint of the configuration and a manifest of every scanned file's hash. On a re-run with the same files and config, detection is skipped entirely and the cached result is replayed (the run prints (cache hit)). Any changed, added, or removed file is a miss and triggers a full re-scan. Different algorithm/threshold combinations get separate cache entries, so they never collide.

Mount the cache directory with actions/cache to carry it between CI runs:

Per-file incremental index (--incremental)

--cache is all-or-nothing: a single changed file invalidates the whole run. --incremental (Rabin–Karp only) is finer-grained — it persists each file's tokenization keyed by a content hash, and on a re-run re-tokenizes only the files that changed, replaying the rest straight from the index. The run prints what it did, e.g. (incremental index: 412 reused, 3 scanned).

The result is identical to a full scan — only the work differs — so it stays correct as files come and go between runs. Use it on large codebases where most files are untouched between CI runs; mount the same .phpcpd-cache directory with actions/cache as above. (Requested with another algorithm, the flag is ignored and the run falls back to the coarse --cache.)

Lineage and license

phpcpd-next is a fork of sebastianbergmann/phpcpd, created by Sebastian Bergmann and archived in

  1. The original copyright is retained throughout; this fork is maintained by Luciano Federico Pereira. Licensed under BSD-3-Clause — see LICENSE.

The diff-by-diff story of the modernisation and the new detection capabilities lives in paper. Contributions are welcome under the CONTRIBUTING.md.


All versions of phpcpd with dependencies

PHP Build Version
Package Version
Requires php Version >=8.5
ext-dom Version *
ext-mbstring Version *
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package phpcpd-next/phpcpd contains the following files

Loading the files please wait ...