Вопрос: Обработка изображений товаров для сайта, как правильно реализовать?

Лучший ответ:
Сочетайте все три способа вместе! 
1. На подстраховку задайте в css размеры изображений и чтобы он их обрезал.
2. Сохраняйте оригинал файла. А уже от этого оригинала генерируйте обрезанные копии для разных частей сайта:
- Для корзины надо 50х50px
- Для админки 100х100px
- Для списка товаров 300х400px
- Для просмотра товара 1000х1000px и ещё с водяным знаком. 
В таком случае вы папки изображений разделяете на две:
- original (оригинальные фалы)
- cache (сгенерированные из оригинала под нужные размеры).
В дальнейшем можно удалить просто папку cache и сгенерировать новые по нужным размерам из оригиналов папки original без опаски удаление оригинала и опаски потерять оригинал совершив ошибку при обрезке.
Сохранение оригинала ещё поможет в будущем... Например, если изменится вёрстка и нужно будет пересоздать файлы под другие размеры. 
На Yii для этого есть замечательная библиотека, которая реализует такой подход
Пример настройки: public function behaviors(): array
    {
        return [
            [
                'class' => ImageUploadBehavior::className(),
                'attribute' => 'photo',
                'createThumbsOnRequest' => true, //Создавать при запросе (если файлы из cache удалить, то они снова сгенерируются под новым размерам указаных ниже)
                'filePath' => '@staticRoot/origin/posts/[[id]].[[extension]]',
                'fileUrl' => '@static/origin/posts/[[id]].[[extension]]',
                'thumbPath' => '@staticRoot/cache/posts/[[profile]]_[[id]].[[extension]]',
                'thumbUrl' => '@static/cache/posts/[[profile]]_[[id]].[[extension]]',
                'thumbs' => [
                    'admin' => ['width' => 100, 'height' => 70],
                    'thumb' => ['width' => 640, 'height' => 480],
                    'blog_list' => ['width' => 1000, 'height' => 150],
                    'widget_list' => ['width' => 228, 'height' => 228],
                    'origin' => ['processor' => [new WaterMarker(1024, 768, '@frontend/web/image/logo.png'), 'process']],
                ],
            ],
        ];
    }
Вы так же можете сделать такой подход со своей написанной библиотекой. Но подход такой достаточно хороший и логичный. На него я бы делал больше упор, чем на остальные пункты.
3. Лучше не предупреждать что будет обрезано, а в момент загрузке на js показать как будет выглядеть изображение на всех видах верстки. Но можно и просто написать.
Вообще это идеальный вариант. Вы можете использовать самый простой вариант и работать с простой и удобной библиотекой. Или любой другой популярной написанной на чистом php. Решать вам)

Худший ответ:
Используй для обрезки и уменьшения библиотеку imagemagic, там всё просто и доступно: https://www.php.net/manual/ru/book.imagick.php
Что-бы подогнать под пропорции (обрезать) нужно сначала уменьшить до допустимых значений, например ширина картинки максимально 800 пикс, тогда что-бы получить высоту нужно получить сначала соотношение сторон, делается делением высоты на ширину, будет например 900/1600 будет 0,56 и дальше при ресайзе ты указываешь - "ширина 800 пикс, а высота равна ширине*0,56" в результате ты получаешь пропорционально уменьшенную картинку. Дальше можно сделать обрезку, если высота вылезла за допустимые пределы.