Работали ли вы с базами данных через ORM в PHP?

Ответ

Да, основную часть работы с базами данных в PHP я выполнял через ORM. Чаще всего это был Eloquent ORM в Laravel и Doctrine ORM в Symfony.

Пример работы с Eloquent (Laravel):

// Определение модели с отношениями
class Post extends Model
{
    protected $casts = ['published_at' => 'datetime'];

    public function author() {
        return $this->belongsTo(User::class);
    }

    public function scopePublished($query) {
        return $query->whereNotNull('published_at');
    }
}

// Использование: создание, запросы, отношения
$newPost = Post::create([
    'title' => 'My Article',
    'body' => 'Content here',
    'author_id' => Auth::id(),
]);

$recentPosts = Post::with('author') // Жадная загрузка
    ->published() // Использование scope
    ->orderBy('published_at', 'desc')
    ->take(10)
    ->get();

foreach ($recentPosts as $post) {
    echo $post->author->name; // Доступ к связанным данным
}

Пример работы с Doctrine (Symfony):

// Entity-класс с аннотациями (или атрибутами в PHP 8+)
/**
 * @ORMEntity
 * @ORMTable(name="products")
 */
class Product
{
    /**
     * @ORMId
     * @ORMGeneratedValue
     * @ORMColumn(type="integer")
     */
    private $id;

    /** @ORMColumn(type="string", length=255) */
    private $name;

    // Геттеры и сеттеры
}

// Работа в сервисе
$product = new Product();
$product->setName('Laptop');

$this->entityManager->persist($product); // Отслеживание сущности
$this->entityManager->flush(); // Запись в БД

// DQL (Doctrine Query Language) для сложных запросов
$query = $this->entityManager->createQuery(
    'SELECT p FROM AppEntityProduct p WHERE p.price > :price'
)->setParameter('price', 1000);
$products = $query->getResult();

Выводы из практики:

  • Плюсы ORM: Быстрая разработка, безопасность (защита от SQL-инъекций через подготовленные выражения), удобная работа со связями, миграции.
  • Минусы и обходные пути: Сложные аналитические запросы или операции с большими объемами данных часто пишу на нативном SQL (через DB::raw() в Laravel или NativeQuery в Doctrine) для максимальной производительности. Важно понимать, какие запросы генерирует ORM, используя ее инструменты для отладки (например, ->toSql() в Laravel или профилирование Doctrine).

Ответ 18+ 🔞

А, ну про ORM спросил, отлично! Я с ними, можно сказать, на короткой ноге, всю жизнь в них ковыряюсь. В основном, конечно, Eloquent в Laravel и Doctrine в Symfony — это мои рабочие лошадки, без них нихуя не сдвинешься.

Вот, смотри, как в Laravel'е обычно выглядит этот цирк:

// Описываешь модель, отношения — всё как у людей
class Post extends Model
{
    protected $casts = ['published_at' => 'datetime'];

    public function author() {
        return $this->belongsTo(User::class);
    }

    public function scopePublished($query) {
        return $query->whereNotNull('published_at');
    }
}

// А потом просто пишешь, как будто на чистом английском, а не на SQL
$newPost = Post::create([
    'title' => 'My Article',
    'body' => 'Content here',
    'author_id' => Auth::id(),
]);

$recentPosts = Post::with('author') // Жадная загрузка, чтоб не было N+1 проблемы
    ->published() // Использование scope — красота же!
    ->orderBy('published_at', 'desc')
    ->take(10)
    ->get();

foreach ($recentPosts as $post) {
    echo $post->author->name; // И вот тебе данные автора, без всяких джойнов вручную
}

А в Symfony с Doctrine история немного другая, там больше магии с аннотациями (или атрибутами, если ты не из каменного века):

// Тут ты по сути описываешь схему базы прямо в классе, ёпта
/**
 * @ORMEntity
 * @ORMTable(name="products")
 */
class Product
{
    /**
     * @ORMId
     * @ORMGeneratedValue
     * @ORMColumn(type="integer")
     */
    private $id;

    /** @ORMColumn(type="string", length=255) */
    private $name;

    // Ну и куча геттеров-сеттеров, без них нихуя
}

// Работаешь через EntityManager — он за тебя всё отслеживает
$product = new Product();
$product->setName('Laptop');

$this->entityManager->persist($product); // Говоришь: "Следи за этой сущностью, братан"
$this->entityManager->flush(); // И тут всё разом летит в базу

// А если запрос сложный, пишешь на DQL — это как SQL, но для объектов
$query = $this->entityManager->createQuery(
    'SELECT p FROM AppEntityProduct p WHERE p.price > :price'
)->setParameter('price', 1000);
$products = $query->getResult();

Что я в итоге понял, блядь, за эти годы?

  • Плюсы ORM — овердохуища: Разработка в разы быстрее, про безопасность (те же подготовленные выражения) можно не париться, связи между таблицами описываются за пару строк, миграции — вообще песня. Не жизнь, а малина.
  • Но и минусы есть, куда ж без них: Как только дело доходит до каких-нибудь адских аналитических отчётов или работы с охуенно большими данными, ORM начинает тупить и генерировать такое, что волосы дыбом встают. В таких случаях я без зазрения совести пишу нативный SQL (через DB::raw() в Laravel или NativeQuery в Doctrine) — производительность сразу взлетает. Главное — не забывать смотреть, какие запросы ORM на самом деле генерирует, а то можно и на ровном месте схлопотать проблем с производительностью. В общем, инструмент классный, но голову включать всё равно надо.