laravel-ide-helper
laravel-ide-helper copied to clipboard
Invalid phpdoc generated for custom cast without defined return type
Versions:
- ide-helper Version: 2.9.2, but exists on 2.10 as well
- Laravel Version: 8.51.0
- PHP Version: 8.0.8
Description:
When using a cast that implements CastsAttributes interface, if get
method doesn't return a type, ie:
public function get($model, $key, $value, $attributes)
and given column is of json type then an invalid phpdoc is generated, like this:
* @property |null $premium
The reason for this is that in ModelsCommand
class, in castPropertiesType
method $realType = $this->checkForCustomLaravelCasts($realType);
returns null, $realType = $this->getTypeOverride($realType);
returns null, $this->properties[$name]['type'] = $this->getTypeInModel($model, $realType);
returns null (which defacto overrides the type of property that has been set, in this case mixed|null
). Then
if (isset($this->nullableColumns[$name])) {
$this->properties[$name]['type'] .= '|null';
}
which evaluates to null.'|null'
produces |null
Steps To Reproduce:
- Add field
foo
to users migration like this
class CreateUsersTable extends Migration
{
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->jsonb('foo')->nullable();
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
}
- Make User use a custom cast:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use App\Casts\FooCast;
class User extends Authenticatable
{
use HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
'email',
'password',
'foo'
];
protected $casts = [
'foo' => FooCast::class,
'email_verified_at' => 'datetime',
];
}
- Create a cast without a defined type:
<?php
namespace App\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
class FooCast implements CastsAttributes
{
public function get($model, $key, $value, $attributes)
{
return json_encode($value, true);
}
/**
* Prepare the given value for storage.
*/
public function set($model, $key, $value, $attributes)
{
return json_decode($value, true);
}
}