Сбер AIJ 11.12.24
Сбер AIJ 11.12.24
Сбер AIJ 11.12.24

4 причины, по которым Symfony лучше Laravel

И у Symfony, и у Laravel есть свои достоинства и недостатки. В этой статье разбираем, почему Symfony больше подходит для больших проектов.

4К открытий12К показов

Сразу спойлер: в Laravel есть фишки, которых нет у Symfony. Обилие интеграций, нестандартные библиотеки, та же «магия» может обернуться достоинством. Мы же разберём, почему Symfony больше подходит для программистов, которые работают с обширной кодовой базой.

Скорость

Основа современного фреймворка — это DI-контейнер, отвечающий за внедрение зависимостей.

В Symfony есть этап компиляции DI-контейнера, который происходит один раз, как правило, во время деплоя или первого запроса. В Laravel определение зависимостей происходит динамически через рефлексию при каждом запросе. Так, кода становится больше, особенно если в команде много разработчиков.

Кроме того, в Symfony по умолчанию используется Doctrine ORM, которая оптимизирует запросы изменения баз данных. Обновление происходит один раз, и все изменения (удаление, добавление, корректировка записей) проводятся пачками. То есть при изменении одной, 100, 500 или 1 тыс. записей механика не изменится.

В Laravel можно добиться того же эффекта, но об этом нужно будет явно позаботиться.

Фреймворк использует Eloquent ORM с моделью ActiveRecord и по умолчанию работает с одной записью. При изменениях придётся создавать массив на каждую запись и использовать отдельные наборы методов, будь то массовое обновление или вставка новых записей.

			// Добавление/обновление одной записи
$user->saveOrFail();
// Удаление одной записи
$user->deleteOrFail();

// Массовое добавление
User::query()->insert([
    ['email' => 'test1@example.com', ...(другие поля)],
    ['email' => 'test2@example.com', ...(другие поля)],
]);

// Массовый upsert
User::query()->upsert([
    ['email' => 'test1@example.com'],
    ['email' => 'test2@example.com'],
], 'email');

// Массовое удаление
User::query()->where(['id' => 1])->delete();
		

С таким кодом время выполнения скрипта растёт, когда нагрузка становится большой и возникает необходимость оперировать тысячами записей.

Стабильность

Symfony обещает не ломать обратную совместимость и соблюдать Semver, Laravel — нет. А в долгоживущих приложениях это одна из самых важных фич (если не самая). Благодаря ей, при обновлении кодовой базы мы будем уверены, что новая мажорная версия ничего не сломает, и сможем без страха обновить фреймворк и все пакеты экосистемы.

Кроме того, версии Symfony имеют Long-Term Support Release (выходят раз в два года). Багфиксы приходят в течение трёх лет после релиза, а обновления безопасности — в течение четырёх. Так, если мы фокусируемся на развитии продукта, редко обновляем фреймворк и чиним сопутствующие баги, то LTS Symfony — это наш путь. Достаточно обновиться до последней минорной версии.

Мы переезжали с LTS 4.4 сначала на 5.3, потом на 5.4, и всё прошло гладко.

У Laravel последняя версия с LTS — шестая (притом что уже вышла десятая). Шестая, седьмая и восьмая мажорные версии вышли с разницей полгода. И каждый раз обновлять их посреди большого проекта с кучей кода — было очень нетривиальной и дорогой задачей. Возникали проблемы с обновлением пакетов, связанные с конкретной версией фреймворка. Но без него стоимость выросла бы в разы.

Меньше «магии»

В Symfony используется концепция маппинга данных на «сущности» — данные в чистом виде, без дополнительной логики. То есть мы можем явно указать тип — и быть уверенными, что получим только его.

			#[ORM\Column(type: 'string')]
public string $email;
		

Связи между сущностями явно и декларативно указываются в атрибутах. И это тоже добавляет прозрачности.

			#[ORM\ManyToOne(targetEntity: User::class)]
private User $referral;
		

В Laravel много «магии». Основной её поставщик — Eloquent. Покажу на примерах.

  • Так создаётся атрибут $this->user:
			public function getUserAttribute(): User
{
    return new User();
}

public function user(): Attribute
{
    return Attribute::make(
        get: fn() => new User(),
    );
}
		
  • Так задаются связи. Удобно, если не нужно указывать названия ключей:
			public function users(): BelongsToMany
{
    return $this->belongsToMany(User::class);
}
		
  • Так выглядит кастинг типов:
			protected $casts = [
    'created_at' => 'datetime:Y-m-d',
];
		
  • Чтобы была возможность создавать через new, нужно явно задать свойство:
			protected $fillable = [
    'email'
];
		

В IDE все свойства таких моделек не видны, и нужно явно прописывать @property для всех и вся.

			/**
* @property string $name
* @property string $email
* @property string $password
* @property string[] $permissions
* @property CarbonInterface $createdAt
* @property CarbonInterface $updatedAt
*/
class User extends Authenticatable
{}
		
Не забывайте добавлять запись на каждое свойство, иначе IDE не сможет подсказывать.
  • Явной валидации типов свойств также нет. Можно использовать кастинг типов, чтобы преобразовывать строки с цифрами в булевый формат.
			protected $casts = [
    'is_real' => 'boolean',
];
		

Это всё повышает порог входа в разработку на Laravel.

Стандарт индустрии

На Symfony пишут:

  • Skyeng,
  • «Яндекс.Еда»,
  • «СберЛогистика»

и ещё куча компаний. То есть специалист со знанием фреймворка точно будет востребован.

На Laravel пишут e-com проекты, например, в AGIMA. Сам сайт Laravel написан на Laravel, а ещё на нём работает Canva. Но чаще его выбирают для стартапов и если нужно прописывать много интеграций с внешним миром.

В каких случаях выбирают Symfony

  • Когда в проекте важнее внутренняя логика и не предусмотрено множество интеграций — потому что Symfony стабильнее.
  • Когда проект большой, разработчиков много и нужно, чтобы у всех были плюс-минус одинаковые знания — потому что в Symfony используются стандартные решения из коробки.
Но если компания может позволить себе много дорогих, опытных разработчиков, которых не нужно подгонять под условия работы, то и на Laravel получится быстро написать бизнесовую логику.
Следите за новыми постами
Следите за новыми постами по любимым темам
4К открытий12К показов