new static — это способ создать объект класса с учётом позднего статического связывания (Late Static Binding). Механизм появился в PHP 5.3 и решает одну конкретную проблему: в каком именно классе мы находимся при вызове через наследование.
new self vs new static
new self() | new static() | |
|---|---|---|
| Привязка | К классу, где написан код | К классу, на котором вызван метод |
| Учитывает наследование | Нет | Да |
| Когда определяется класс | На этапе компиляции | На этапе выполнения |
Простой пример
class Animal
{
protected string $type = 'animal';
public static function create(): static
{
return new static();
}
public function getType(): string
{
return $this->type;
}
}
class Dog extends Animal
{
protected string $type = 'dog';
}
class Cat extends Animal
{
protected string $type = 'cat';
}
Результат вызовов:
Animal::create(); // объект Animal
Dog::create(); // объект Dog (не Animal!)
Cat::create(); // объект Cat (не Animal!)
Dog::create()->getType(); // "dog"
Если заменить new static() на new self(), то Dog::create() и Cat::create() вернут Animal — потому что self жёстко указывает на класс, в котором написан метод.
Где это используется в Laravel
1. Eloquent-модели
Внутри базового класса Model множество методов используют new static:
// Illuminate\Database\Eloquent\Model
public static function query()
{
return (new static)->newQuery();
}
public static function create(array $attributes = [])
{
$model = new static($attributes);
$model->save();
return $model;
}
Благодаря этому User::create([...]) создаёт именно User, а Post::query() работает именно с моделью Post.
2. Фабричные методы
// Пример из Collection
public static function make($items = [])
{
return new static($items);
}
3. Builder-паттерн
class FormRequest
{
public static function fromRequest(Request $request): static
{
$instance = new static();
$instance->merge($request->all());
return $instance;
}
}
Практический пример: свой код
class BaseRepository
{
protected static string $model;
public static function findOrFail(int $id): Model
{
return (new static)->getModel()::findOrFail($id);
}
protected function getModel(): string
{
return static::$model;
}
}
class UserRepository extends BaseRepository
{
protected static string $model = User::class;
}
class PostRepository extends BaseRepository
{
protected static string $model = Post::class;
}
// Вызов
UserRepository::findOrFail(1); // ищет User
PostRepository::findOrFail(1); // ищет Post
Бонус: static как тип возврата
Начиная с PHP 8.0 можно указывать static как return type:
class Builder
{
public function where(string $column, mixed $value): static
{
// ...
return $this;
}
}
Это говорит: метод возвращает экземпляр того же класса (или дочернего), на котором был вызван. Полезно для fluent-интерфейсов и цепочек вызовов.
Итого
new self()— всегда создаёт объект класса, где написан код.new static()— создаёт объект класса, на котором вызван метод (учитывает наследование).- В Laravel
new static— основа работы Eloquent, коллекций и фабричных методов. - Используйте
new static, когда пишете базовый класс, от которого будут наследоваться другие.