Download the PHP package doloto/big0nia without Composer

On this page you can find all versions of the php package doloto/big0nia. 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 big0nia

big0nia

CI Packagist Version PHP Version

Catches algorithmic-complexity and performance anti-patterns that PHPStan and Psalm don't check for.

A standalone static analysis tool for PHP and Symfony that automatically detects algorithmic-complexity (Big-O) issues and performance anti-patterns before they hit production: nested foreach/for loops that scale at O(n²) or O(n × m) because they're secretly an expensive collection join (including across a method/function call boundary), in_array()/array_search() calls inside a loop that turn a lookup into a linear scan, array_merge() calls that silently turn a loop into O(n²) by rebuilding the same array on every iteration, and sorts that redundantly re-sort data nothing in the loop ever changes.

big0nia is meant to run alongside PHPStan/Psalm, not replace them: they focus on type safety, bug patterns, and code smells, not algorithmic complexity.

Quick Start

That's it — no configuration file is required. See CLI reference for exit codes and options, or Configuration to exclude paths from analysis.

The problem it finds

This is O(users × orders): for every user, the whole $orders collection is scanned. big0nia reports:

array_merge() in a loop

array_merge() copies its entire first argument on every call, so this is O(n²) — for every item, the whole (growing) $result array is rebuilt. big0nia reports:

Only the self-referential accumulation pattern is flagged — the assigned variable must also appear as one of array_merge()'s own arguments, inside a foreach or canonical for loop (through if/elseif/else, but not into a nested loop, which is checked independently on its own). An array_merge() call that builds an unrelated value from other variables is not flagged, and the finding is suppressed under the same size-based rules as the nested-loop-join detector when the loop provably iterates a small fixed collection.

Repeated sorts in a loop

If $data is never modified inside the loop, sorting it again on every iteration is pure waste — it's already sorted after the first call. big0nia reports:

Only usort(), uasort(), and uksort() (the custom-comparator sorts) are checked, inside a foreach or canonical for loop (through if/elseif/else, but not into a nested loop, which is checked independently on its own). If the sorted variable is reassigned anywhere in the loop — including inside a nested loop — the sort is legitimate and not flagged, and the finding is suppressed under the same size-based rules as the other two detectors when the loop provably iterates a small fixed collection.

Linear scans inside a loop

in_array() and array_search() scan their entire haystack argument every time they're called, so calling one on every iteration of a loop is the same O(n × m) blowup as a nested-loop join — it just doesn't look like one, since there's no visible inner loop. big0nia reports:

isset(), array_key_exists(), and direct array-key access are never flagged — those are already O(1) hash lookups, which is exactly the fix this rule suggests. The finding is suppressed under the same size-based rules as the other detectors when the scanned collection provably has a fixed size, and when the loop itself is structurally bounded to a single pass by an unconditional break/return/throw.

How nested-loop-join detection works

For every foreach loop, and every canonical indexed for loop (for ($i = 0; $i < count($users); $i++) { ... $users[$i] ... } — exactly this form; anything else, like <=, a precomputed bound variable, or decrementing, is not recognized), big0nia:

  1. Finds a directly nested loop of the same kind — a foreach inside another foreach's body, or a canonical for inside another canonical for's body, seen through simple if guards but not through other loops, closures, or elseif/else branches. Mixed nesting (a for inside a foreach, or vice versa) is not detected.
  2. Finds a join comparison — an equality comparison (===, ==, !==, !=) between something rooted in the outer loop's item (the foreach value variable, or $collection[$index] for a for loop) and the inner loop's item, either as the whole if condition or combined with && at any depth, e.g. $user->getId() === $order->getUserId() && $order->isPaid().
  3. Classifies the size of both compared collections — an array literal used directly, a variable last assigned an array literal earlier in the same statement list, or $this->property / $this->method() resolved to a declared or constructor-promoted default array literal, or to a method body that is exactly one return <array literal>;. A property's default is only trusted if the property is never reassigned anywhere else in the class.
  4. Suppresses only when provably fixed-size — a finding is suppressed only when one of the two collections classifies as fixed-size: an array literal of any size (the property that matters is independence from input size, not smallness), a self::/static:: class constant array, or a literal-bound range() call. Everything else, including a collection it can't classify at all, is reported.

Interprocedural nested-loop joins

When the inner loop lives not in the outer loop's own body, but inside a method called from there — possibly in a different class or file — big0nia traces the call chain and reports the join:

big0nia reports:

The detector resolves six call patterns: typed properties ($this->service->method()), local variables assigned via new ($x = new Foo(); $x->method()), static calls (Foo::method()), free functions (helper()), and same-class calls via $this->method() or self::method(). static::/late static binding and parent:: are not resolved, since either could name a class this project doesn't have enough information to identify safely. For interface-typed properties, the project must have exactly one class that directly implements the interface. A local new-assigned variable's type is trusted only when nothing reassigns it afterward that this analysis can't fully see — a reassignment inside a conditional branch, for instance — otherwise the finding is silently dropped rather than guessed at. Only positional call arguments are matched — named arguments or spread/unpacked arguments break the chain entirely. The call chain can span multiple hops (up to a bounded depth), and the reported message names the full chain; the tip always names the file and line of the actual inner loop. Scope is foreach loops and canonical indexed for loops only — the same narrow set the intra-procedural detector already documents — and while loops are not yet supported for cross-call detection. Suppressions apply: a finding is reported only when both the outer and inner collections are not provably fixed-size (see "Suppresses only when provably fixed-size" above).

CLI reference

Configuration

big0nia looks for a big0nia.neon file in the current working directory. If none is found, every path passed on the command line is analysed in full.

Status

big0nia ships the nested-loop-join detector for foreach (NestedLoopJoinRule) and canonical indexed for loops (NestedForLoopJoinRule), including interprocedural detection when the inner loop lives across a method/function call boundary (InterproceduralLoopJoinRule), the self-referential array_merge()-in-a-loop detector (ArrayMergeInLoopRule), the loop-invariant repeated-sort detector (RepeatedSortInLoopRule), and the in_array()/array_search() linear-scan-in-a-loop detector (LinearScanInLoopRule). Fixed-size collections (array literals of any size, self::CONST/static::CONST array constants, and literal-bound range() calls) and loops structurally bounded to a single pass by an unconditional break/return/throw are recognized and excluded from every rule above. A big0nia.neon config file supports one key so far, ignore_paths (see Configuration above), to exclude vendor code or legacy modules from analysis entirely. Cross-call detection for while loops and more performance-anti-pattern rules (Doctrine N+1) are planned.

Contributing

Before opening a PR, run the same checks CI runs:

CI runs this matrix against PHP 8.2 and 8.3 on every push to main and every pull request (see .github/workflows/ci.yml).

License

MIT


All versions of big0nia with dependencies

PHP Build Version
Package Version
Requires php Version ^8.2
nette/neon Version ^3.4
nikic/php-parser Version ^5.0
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 doloto/big0nia contains the following files

Loading the files please wait ...