Weave Code
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

Psalm Laravel Package

vimeo/psalm

Psalm is a powerful PHP static analysis tool that finds type errors and bugs before runtime. Install via Composer, configure for your codebase, and run it locally or try the live demo at psalm.dev. Docs and integrations available for teams and CI.

View on GitHub
Deep Wiki
Context7

Fixing Code

Psalm is good at finding potential issues in large codebases, but once found, it can be something of a gargantuan task to fix all the issues.

It comes with a tool, called Psalter, that helps you fix code.

You can either run it via its binary

vendor/bin/psalter [args]

or via Psalm's binary:

vendor/bin/psalm --alter [args]

Safety features

Updating code is inherently risky, doing so automatically is even more so. I've added a few features to make it a little more reassuring:

  • To see what changes Psalter will make ahead of time, you can run it with --dry-run.
  • You can target particular versions of PHP via --php-version, so that (for example) you don't add nullable typehints to PHP 7.0 code, or any typehints at all to PHP 5.6 code. --php-version defaults to your current version.
  • it has a --safe-types mode that will only update PHP 7 return typehints with information Psalm has gathered from non-docblock sources of type information (e.g. typehinted params, instanceof checks, other return typehints etc.)
  • using --allow-backwards-incompatible-changes=false you can make sure to not create backwards incompatible changes

Plugins

You can pass in your own manipulation plugins e.g.

vendor/bin/psalter --plugin=vendor/vimeo/psalm/examples/plugins/ClassUnqualifier.php --dry-run

The above example plugin converts all unnecessarily qualified classnames in your code to shorter aliased versions.

Supported fixes

This initial release provides support for the following alterations, corresponding to the names of issues Psalm finds. To fix all of these at once, run vendor/bin/psalter --issues=all

MissingReturnType

Running vendor/bin/psalter --issues=MissingReturnType --php-version=7.0 on

<?php
function foo() {
  return "hello";
}

gives

<?php
function foo() : string {
  return "hello";
}

and running vendor/bin/psalter --issues=MissingReturnType --php-version=5.6 on

<?php
function foo() {
  return "hello";
}

gives

<?php
/**
 * [@return](https://github.com/return) string
 */
function foo() {
  return "hello";
}

MissingClosureReturnType

As above, except for closures

InvalidReturnType

Running vendor/bin/psalter --issues=InvalidReturnType on

<?php
/**
 * [@return](https://github.com/return) int
 */
function foo() {
  return "hello";
}

gives

<?php
/**
 * [@return](https://github.com/return) string
 */
function foo() {
  return "hello";
}

There's also support for return typehints, so running vendor/bin/psalter --issues=InvalidReturnType on

<?php
function foo() : int {
  return "hello";
}

gives

<?php
function foo() : string {
  return "hello";
}

InvalidNullableReturnType

Running vendor/bin/psalter --issues=InvalidNullableReturnType --php-version=7.1 on

<?php
function foo() : string {
  return rand(0, 1) ? "hello" : null;
}

gives

<?php
function foo() : ?string {
  return rand(0, 1) ? "hello" : null;
}

and running vendor/bin/psalter --issues=InvalidNullableReturnType --php-version=7.0 on

<?php
function foo() : string {
  return rand(0, 1) ? "hello" : null;
}

gives

<?php
/**
 * [@return](https://github.com/return) string|null
 */
function foo() {
  return rand(0, 1) ? "hello" : null;
}

InvalidFalsableReturnType

Running vendor/bin/psalter --issues=InvalidFalsableReturnType on

<?php
function foo() : string {
  return rand(0, 1) ? "hello" : false;
}

gives

<?php
/**
 * [@return](https://github.com/return) string|false
 */
function foo() {
  return rand(0, 1) ? "hello" : false;
}

MissingParamType

Running vendor/bin/psalter --issues=MissingParamType on

<?php
class C {
  public static function foo($s) : void {
    echo $s;
  }
}
C::foo("hello");

gives

<?php
class C {
  /**
   * [@param](https://github.com/param) string $s
   */
  public static function foo($s) : void {
    echo $s;
  }
}
C::foo("hello");

MissingPropertyType

Running vendor/bin/psalter --issues=MissingPropertyType on

<?php
class A {
    public $foo;
    public $bar;
    public $baz;

    public function __construct()
    {
        if (rand(0, 1)) {
            $this->foo = 5;
        } else {
            $this->foo = "hello";
        }

        $this->bar = "baz";
    }

    public function setBaz() {
        $this->baz = [1, 2, 3];
    }
}

gives

<?php
class A {
    /**
     * [@var](https://github.com/var) string|int
     */
    public $foo;

    public string $bar;

    /**
     * [@var](https://github.com/var) array<int, int>|null
     * [@psalm-var](https://github.com/psalm-var) non-empty-list<int>|null
     */
    public $baz;

    public function __construct()
    {
        if (rand(0, 1)) {
            $this->foo = 5;
        } else {
            $this->foo = "hello";
        }

        $this->bar = "baz";
    }

    public function setBaz() {
        $this->baz = [1, 2, 3];
    }
}

MismatchingDocblockParamType

Given

<?php
class A {}
class B extends A {}
class C extends A {}
class D {}

running vendor/bin/psalter --issues=MismatchingDocblockParamType on

<?php
/**
 * [@param](https://github.com/param) B|C $first
 * [@param](https://github.com/param) D $second
 */
function foo(A $first, A $second) : void {}

gives

<?php
/**
 * [@param](https://github.com/param) B|C $first
 * [@param](https://github.com/param) A $second
 */
function foo(A $first, A $second) : void {}

MismatchingDocblockReturnType

Running vendor/bin/psalter --issues=MismatchingDocblockReturnType on

<?php
/**
 * [@return](https://github.com/return) int
 */
function foo() : string {
  return "hello";
}

gives

<?php
/**
 * [@return](https://github.com/return) string
 */
function foo() : string {
  return "hello";
}

LessSpecificReturnType

Running vendor/bin/psalter --issues=LessSpecificReturnType on

<?php
function foo() : ?string {
  return "hello";
}

gives

<?php
function foo() : string {
  return "hello";
}

PossiblyUndefinedVariable

Running vendor/bin/psalter --issues=PossiblyUndefinedVariable on

<?php
function foo()
{
    if (rand(0, 1)) {
      $a = 5;
    }
    echo $a;
}

gives

<?php
function foo()
{
    $a = null;
    if (rand(0, 1)) {
      $a = 5;
    }
    echo $a;
}

PossiblyUndefinedGlobalVariable

Running vendor/bin/psalter --issues=PossiblyUndefinedGlobalVariable on

<?php
if (rand(0, 1)) {
  $a = 5;
}
echo $a;

gives

<?php
$a = null;
if (rand(0, 1)) {
  $a = 5;
}
echo $a;

UnusedMethod

This removes private unused methods.

Running vendor/bin/psalter --issues=UnusedMethod on

<?php
class A {
    private function foo() : void {}
}

new A();

gives

<?php
class A {

}

new A();

PossiblyUnusedMethod

This removes protected/public unused methods.

Running vendor/bin/psalter --issues=PossiblyUnusedMethod on

<?php
class A {
    protected function foo() : void {}
    public function bar() : void {}
}

new A();

gives

<?php
class A {

}

new A();

UnusedProperty

This removes private unused properties.

Running vendor/bin/psalter --issues=UnusedProperty on

<?php
class A {
    /** [@var](https://github.com/var) string */
    private $foo;
}

new A();

gives

<?php
class A {

}

new A();

PossiblyUnusedProperty

This removes protected/public unused properties.

Running vendor/bin/psalter --issues=PossiblyUnusedProperty on

<?php
class A {
    /** [@var](https://github.com/var) string */
    public $foo;

    /** [@var](https://github.com/var) string */
    protected $bar;
}

new A();

gives

<?php
class A {

}

new A();

UnusedVariable

This removes unused variables.

Running vendor/bin/psalter --issues=UnusedVariable on

<?php
function foo(string $s) : void {
    $a = 5;
    $b = 6;
    $c = $b += $a -= intval($s);
    echo "foo";
}

gives

<?php
function foo(string $s) : void {
    echo "foo";
}

UnnecessaryVarAnnotation

This removes unused [@var](https://github.com/var) annotations

Running vendor/bin/psalter --issues=UnnecessaryVarAnnotation on

<?php
function foo() : string {
    return "hello";
}

/** [@var](https://github.com/var) string */
$a = foo();

gives

<?php
function foo() : string {
    return "hello";
}

$a = foo();

ParamNameMismatch

This aligns child class param names with their parent.

Running vendor/bin/psalter --issues=ParamNameMismatch on

<?php

class A {
    public function foo(string $str, bool $b = false) : void {}
}

class AChild extends A {
    public function foo(string $string, bool $b = false) : void {
        echo $string;
    }
}

gives

<?php

class A {
    public function foo(string $str, bool $b = false) : void {}
}

class AChild extends A {
    public function foo(string $str, bool $b = false) : void {
        echo $str;
    }
}
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport