Одностраничный магазин с корзиной на Phalcon + AngularJS + Zurb Foundation

    Введение


    Всем привет! Завтра у меня дедлайн по проекту, который я делаю для местной Камчатской компании по доставки еды. И поэтому у меня есть две причины написать эту статью, первая — прокрастинация перед дедлайном, а вторая — я не нашёл на Хабре какого-либо обучающего мануала по написанию корзины товаров на AngularJS.

    Я нашёл статью на стороннем блоге, которая частично помогла мне решить пару задач, которые стояли передо мной. Но оформление статьи оставляло желать лучшего, да и за 5 лет я уже отвык от кода в блокноте, без подсветки синтаксиса, поэтому нужно было как-то структурировать и сделать более читабельной эту полезную информацию.



    Почему был выбран формат одностраничного магазина?



    Кто-то из вас, наверное уже знает, что на Камчатке существует проблема с интернетом, так как наш полуостров ещё не связан с материком оптоволокном, и весь поток идёт через единственную вышку. К концу 2015 года планируется завершить работы по прокладке оптоволокна по дну Охотского моря, и возможно у нас появится наконец-то стабильный и быстрый интернет.

    И соответственно чтобы исключить потери клиентов, переходящих по разным категориям блюд, из-за нестабильного канала, была выбрана подобная модель. То есть человеку достаточно один раз загрузить сайт и получить всю необходимую информацию, и сделать заказ.

    Так же такой формат позволил избежать хранения товаров корзины в сессиях, localStorage или же в базе данных. Так как мы точно знаем, что человек никуда не уйдёт с этой страницы, мы храним данные корзины в объекте javascript. Ещё одним плюсом стало уменьшение времени заказа, так как нет нужды перемещаться по категориям, и загружать новые страницы. И так как позиций блюд не слишком много, нам даже не пришлось делать Ajax-подгрузку данных при нажатии на категорию, всё подгружалось из кеша базы данных.

    База данных


    После того, как был готов и свёрстан дизайн одностраничного сайта, пришло время создать структуру базы данных категорий и товаров. Это наверно самый быстрый и самый простой этап, учитывая наши потребности и направленность на простоту работы системы и взаимодействия с пользователями. У меня уже был набросок админки на Phalcon PHP Framework, поэтому поправить его для работы с двумя таблицами category и products, не составило особого труда.

    Таблица category


    Таблица products


    Вот так выглядит админка сайта


    Получаем категории и блюда из базы данных


    Для работы с базой данных использовалась стандартная ORM система фреймворка Phalcon, если вы с ней не работаете, можете пропустить этот раздел, он для общего развития, чтоб дальше было понятно откуда ноги растут, точнее откуда и как берутся блюда на сайте.

    В основном контроллере IndexController.php в модуле frontend, я написал функцию, которая сформирует данные нужным нам образом и выведет их на единственную нашу страницу.
    public function indexAction()
        {
             //Получаем все категории в массив
            $category = Category::find()->toArray();
            $help = new \Lib\Url();
            Перебираем массив и для каждой категории подгружаем блюда
            foreach ($category as $key => $val)
            {
                $category[$key]['url'] = $help->translit_url($val['name']);
                //Это не родительская категория? Тогда удаляем из массива
                if ($val['pid'] != 0)
                {
                    unset($category[$key]);
                }
                else
                {
                    //Подгружаем массив подкатегорий, правда в нашем случае только одна категория имеет подкатегории
                    $category[$key]['sub'] = Category::find("pid = '".$val['id']."'")->toArray();
                    //Если есть подкатегории, цепляем к ним блюда, если нет, то цепляем блюда к основном категории
                    if(count($category[$key]['sub']) > 0)
                    {
                        foreach($category[$key]['sub'] as $i => $cat)
                        {
                            $category[$key]['sub'][$i]['products'] = Products::find("category = '" . $cat['id'] . "'")->toArray();
                        }
                    }
                    else
                    {
                        $category[$key]['products'] = Products::find("category = '" . $val['id'] . "'")->toArray();
                    }
                }
            }
            $this->view->setVar('items',$category);
        }
    


    Возможно есть более изящные решения этой задачи, но у нас не будет больше 200 посетителей за день, и мы подключим кеширование запросов к базе данных, и в принципе не будет такой сильной нагрузки, тем более это Phalcon — «Самый быстрый PHP фреймворк». Но вопрос сейчас не о производительно и оптимизации, это пока рано, главное что пора выводить товар на странице.

    Кому доверить рендеринг товаров на странице? AngularJS или Phalcon?


    Сначала я реализовал всё на AngularJS, ну это было как-то изящнее и красивее, но потом задумался о СЕО-оптимизации, и индексации поисковыми системами, и подумал что лучше наверно не рисковать, и рендеринг доверить нашему старому доброму любимому PHP.

    Приводить код выводящий товары на странице я тут не буду, как из соображений величины этого кода, так и из этических соображений, всё таки это продукт нашего заказчика. Да и думаю, кто читает Хабр знает как пользоваться функцией foreach в php.

    Ну ладно, покажу как я выводил категории блюд, а там уже по примеру каждый разберётся и с товарами.

    <div class="row">
            <div class="large-12 columns">
                <ul class="tabs small-block-grid-2 medium-block-grid-4 large-block-grid-6" data-tab>
                    <?php foreach ($items as $item): ?>
                        <li>
                            <a href="#<?= $item['url'] ?>">
                                <img ng-src="/uploads/<?= $item['images'] ?>" alt="<?= $item['name'] ?>">
                            </a>
                            <p><?= $item['name'] ?></p>
                        </li>
                    <?php endforeach; ?>
                </ul>
            </div>
        </div>
    


    Выглядит это всё дело очень и очень аппетитно.


    Добавление товара в корзину


    Нажимая на категорию, внизу открывается таб с блюдами из этой категории. Возможно кто-то из вас уже не может смотреть на эти аппетитные картинки, но для продолжения описания работы одностраничного магазина, мне просто необходимо показать вам, как выглядит карточка товара на сайте. Смотрите.



    Так, а теперь вытирайте слюни с клавиатуры, и поехали дальше, смотреть как же работает основной функционал добавления в корзину и высчитывания конечной суммы заказа.

    В основном для понимания основы вам нужно видеть только этот отрезок кода, который выводит кнопку «Добавить» с полем, куда можно ввести количество штук блюда.

    <div class="add-cart">
          <input type="number" ng-model="num<?=$p['id']?> value="1" min="1" max="50">
         <button type="button" ng-click="addCart(<?=$p['id']?>, num<?=$p['id']?>, '<?=$p['title']?>', <?=$p['price']?>)"></button>
    </div>
    


    Как видно из исходного кода, функция addCart() выполняет добавление данных в объект javascript, давайте посмотрим исходный код на AngularJS.

        $scope.carts = [];
        $scope.addCart = function(id, num, title, price)
        {
            var nums = num || 1;
            $scope.carts.push({
                id : id,
                num : nums,
                title : title,
                price : price
            });
        };
    


    Я думаю тут нечего объяснять, всё предельно просто и понятно, а главное — работает! После того, как мы добавили данные в $scope.carts, нужно их куда-то вывести. В нашем случае, дизайнер решил сделать это в плавающее окошко справа, вот так.


    И соответственно код.

    <div class="cart ng-cloak" ng-cloak ng-show="carts.length > 0">
        <div class="cart-items">
            <h3 class="text-center">Корзина</h3>
            <div class="row items" ng-repeat="item in carts">
                <div class="small-5 columns text-right">
                    {{item.title}}
                </div>
                <div class="small-2 columns">
                    <input type="number" ng-model="item.num" min="1" max="50">
                </div>
                <div class="small-4 columns">
                    {{item.price}} руб.
                </div>
                <div class="small-1 columns">
                    <a href ng-click="removeItem(carts,item)">X</a>
                </div>
            </div>
        </div>
        <div class="cart-results text-center">
            <div class="row">
                <div class="small-12 columns">
                    <select ng-model="delivery" ng-init="delivery = 0">
                        <option value="0">Октябрьский район</option>
                        <option value="1">Ленинский район</option>
                        <option value="2">Долиновка, Завойко</option>
                        <option value="3">Самовывоз (-10%)</option>
                    </select>
                </div>
            </div>
            <h3>{{total() | number : 0}} руб.</h3>
            <button class="new_btn" data-reveal-id="order">Заказать</button>
        </div>
    </div>
    


    Кстати, функция ng-cloak просто выручает в условиях Камчатского интернета, если её не использовать, пока человек будет ждать загрузку страницы, ему будет видна пустая корзина со страшными символами. Для тех кто не знаком с AngularJS, укажу на несколько ключевых моментов.
    Это нужно, чтобы показывать корзину, только в случае если в ней есть товары.
    ng-show="carts.length > 0"
    

    Этот код выводит конечную сумму заказа, форматируя число, и убирая копейки, которые могут получится, при высчитывании 10% скидки, например в случае самовывоза.
    {{total() | number : 0}}
    

    У меня часто возникала задача удалить элемент ассоциативного массива, я каждый раз забывал как это делать, и обращался к Google, но надеюсь после этой публикации я наконец-то запомню, а те кто не знал, узнают.
    $scope.removeItem = function(carts, item) {
            carts.splice(item, 1);
    };
    

    А что, кто-то рассчитывал что будет больше кода? Можно кстати даже в одну строчку написать. Но не будем изгаляться, нам главное читабельность кода. И наверно последнюю функцию которую я хочу привести в этой статье — это подсчёт конечной суммы заказа. Он был выполнен исходя из условий и способов доставки.
    $scope.total = function() {
            var total = 0;
            angular.forEach($scope.carts, function(item) {
                total += item.num * item.price;
            });
            var delivery = 0;
            if($scope.delivery == 0)
            {
                if(total >= 600)
                {
                    delivery = 0;
                }
                else
                {
                    delivery = 130;
                }
            }
            if($scope.delivery == 1)
            {
                if(total >= 1500)
                {
                    delivery = 0;
                }
                else
                {
                    delivery = 130;
                }
            }
            if($scope.delivery == 2)
            {
                delivery = 300;
            }
            if($scope.delivery == 3)
            {
                delivery = 10/total*100*(-1);
            }
            return total + delivery;
        };
    

    Чем объяснять откуда растут цифры, я просто покажу блок с информацией о доставке, а вы уже сами разгадаете откуда появились разные цифры в коде. Тем более у каждого эти данные будут разные, и будет разное количество районов, поэтому не вижу смысла заострят на этом внимание, тем более статья и так уже получилась достаточно объёмная.


    Послесловие


    Главная задача моего поста решена, теперь на Хабре есть материал, о том как сделать добавление товаров в корзину и подсчёт суммы заказа на AngularJS, а в интернете есть хорошо оформленный материал об этом, который дополнит запись из стороннего блога, ссылку на который я привёл в начале статьи. Ну а так же, я уже достаточно прокрастинировал, поэтому пора приступать снова к работе, и заканчивать отправку заказа нашему заказчику. Надеюсь статья поможет таким же как я. Если у вас всё же возникнут вопросы по приведённому исходному коду, или что-то будет не понятно, я с удовольствием отвечу в комментариях. К сожалению опыт работы с AngularJS всего пол года, поэтому чем смогу, тем помогу. Спасибо за ваше внимание.

    Обновление
    Спасибо всем за комментарии, я постарался исправить недочёты и описал проделанную работу в следующей публикации — «Одностраничный магазин на Phalcon PHP + AngularJS. Работа над ошибками».
    Поделиться публикацией
    Комментарии 45
      +19
      image
      Совсем незачем юзеру говорить будет страница перезагружена или нет, ему это фиолетово. Не усложняйте.
        +9
        Действительно, это выглядит как демонстрация: «Ура! Пользователь, ты представляешь? Мы, наконец, осилили Ангуляр!» :)
          +1
          Хотя может быть и правда на Камчатке всё так плачевно. Средний пользователь с вечера ставит на загрузку десятки страниц во вкладках, чтобы потом в течение следующих суток их почитать.
            +2
            Так было 5 лет назад, 1мб GPRS связи 7 рублей. Сейчас лучше, 3500 рублей за скорость 400 кбит/сек.
            0
            Спасибо за фидбэк, но как дать пользователю визуально понять, что не будет загружена новая страница при клике?
              +7
              Я думаю, что это совершенно ненужная для пользователя информация, следовательно мусор. Средний пользователь просто не поймёт, о чём вы ему хотите сказать, из оставшихся только единицы смогут оценить. Тем более 99,9% интернета как-то прекрасно обходились загрузкой страниц даже во времена диалапа, и никто при этом не страдал.
                0
                может быть ховер на картинку какойнибудь. возможно чтото вроде этого.
                ну или подчеркивание на заголовках из точек. последнее правда не столь очевидно будет на фоне картинки.
                  0
                  Точечное подчёркивание, обычно, означает вызов диалога, вместо навигации. В данном случае примерно это и происходит, так что если для автора это настолько сильно важно, то это самый верный способ.
                    0
                    + отъезжание иконок вверхв-низ, под которой видно, что что-то есть более подробное
                    + подчеркнуть названия пунктиром?
                    +2
                    Вы же делаете магазин одностраничным не для того, что бы пользователь порадовался, что он одностраничный, а для того что бы пользователь ощутил скорость работы, отсутствие тех самых признаков перезагрузки типа белого моргнувшего экрана. И вот когда он нажмет, то сам заценит. Он не поймет перезагрузилась страница или нет, но ему понравится)
                +6
                Так же такой формат позволил избежать хранения товаров корзины в сессиях, localStorage или же в базе данных. Так как мы точно знаем, что человек никуда не уйдёт с этой страницы, мы храним данные корзины в объекте javascript.


                Я правильно понял, что если я случайно закрою вкладку, то все мои товары в корзине будут навсегда потеряны? Придётся оформлять заказ заново? Не слишком ли опрометчивый подход?

                Подозреваю, что на самом деле вам было банально лень делать человеческую корзину.
                  +6
                  Кстати да, зачем избегать localStorage мне не совсем понятно. Туда можно кэшировать стили, в которых «мелкая» графика в base64. И опять таки в localStorage можно собирать объект, который пригодится для аналитики.

                    0
                    В нашем случае нет, средний пользователь не открывает больше 5 вкладок. У меня сейчас открыто 10, потому что я их не закрываю, чтобы потом снова не загружать. А вообще цель статьи была описать общий процесс работы с корзиной, если кто-то захочет развить тему, это его решение. Мы зная наш рынок стараемся делать проще, и конечно же если АБ тесты и вебвизор покажет что 20% пользователей случайно закрывают вкладки, то сделаем с localStorage.
                      +1
                      Дело не только в случайно закрытой вкладке. Я могу начать заказывать, затем отвлечься, закрыть браузер, потом захочу вернуться и тут меня ожидает сюрприз. Это просто некрасиво, я считаю, сегодня обманывать ожидания пользователя. А пользователи привыкли к персистентному состоянию корзины, потому что это абсолютная норма. Даже не знаю, почему вы решили иначе. Но дело ваше, конечно, ваши пользователи.
                        0
                        Никакие тесты не покажут случайность закрытия вкладки. Даже не знаю, к счастью это, или к сожалению :)
                          0
                          Если корзина где-то сохраняется между заходами пользователя, — то это небольшой такой плюсик в карму магазина, = повышение лояльности. Вот логинюсь я на чайник, а там в корзине с лета лежат комплектующие.
                            0
                            Представьте, что 3% купивших бы товар случайно закрыли вкладки и посчитайте сколько потеряет магазин. А потом посчитайте сколько строчек кода вам понадобится что бы внедрить хранение корзины :)
                              –1
                              Можно же в куки положить всю корзину
                                0
                                Зачем если в localStorage до первой зачистки может жить «жирный» объект со статистикой, чтобы напомнить о незакрытом заказе или предложить акцию если после нескольких раз человек так и не решился сделать заказ.

                                0
                                Слишком много «но» и «если», чтобы можно было с такой уверенностью отказываться от абсолютного не требующего затрат полезного инструмента. Но конверсия почти точно будет лучше при условии хранения списка/истории заказа.
                                • НЛО прилетело и опубликовало эту надпись здесь
                                0
                                Если бы я писал такую статью, то убрал бы в главной картинке название фирмы и телефон заказа, а то администраци Хабра посчитает это как реклама или убираем все рубрики WEB разработки, ООП и Добро пожаловать в «Я ПИАРЮСЬ!».
                                  –2
                                  Главная задача моего поста решена, теперь на Хабре есть материал, о том как сделать добавление товаров в корзину и подсчёт суммы заказа на AngularJS
                                  Эта задача была бы решена, если бы ты оформил все в ввиде модуля библиотеки и выложил это на гитхаб. А как сделать карзину товаров, знает любой WEB разработчик, проработавший более 6 мес.
                                    +2
                                    <a href="#<?= $item['url'] ?>">
                                    про шаблоны — ничего не знаем?
                                      –1
                                      Вообще php изначально в общем-то язык-шаблонизатор. Зачем в нем использовать еще один шаблонизатор, который будет написан на каком-то еще мета-языке?
                                        0
                                        Чтобы не писать постоянно
                                        <?= isset($item['url'])? htmlspecialchars($item['url']): '';?>
                                        ?

                                        Тем более, что у phalcon есть volt.
                                          –1
                                          php был шаблонизатором (причем убогим) для c/c++ очень давно, во времена php1/2. Вспомните JS лет так 8-10 назад.
                                        +1
                                        Моё небольшое ИМХО:

                                        добавление в корзину через вставку инлайн PHP скриптов — плохо. Т.к. в идеале, Angular — MVC фреймворк, и в его виды, никто лезть не должен.

                                        Когда контроллеры Angular пухнут, становится сложновато разобрать структуру. Лично для себя, выводил такие предопределенные структуры:

                                        $scope.models = {
                                           someModel:0
                                        }
                                        
                                        $scope.actions = {
                                           someAction:function() { }
                                        }
                                        


                                        Для всех Agnular-тэгов, лучше подставлять префикс data-, data-ng-model, data-ng-click. Так валиднее, привет опять таки IE.

                                        А еще есть https://github.com/johnpapa/angularjs-styleguide стайлгайд, к которому в принципе можно привыкнуть.

                                        Большинство выводимых данных, лучше выводить через ng-bind или ng-bind-template или ng-bind-html (при наличии модуля $sce).
                                          –2
                                          Обучающий материал по написанию корзины товаров на AngularJS?! Вы это серьезно сейчас?
                                          • НЛО прилетело и опубликовало эту надпись здесь
                                              0
                                              А вообще любой «самый быстрый фреймворк» можно замедлить построением дерева категорий больше, чем за 1 запрос к бд.
                                              • НЛО прилетело и опубликовало эту надпись здесь
                                                  +1
                                                  или заюзать nested set/matherialized path
                                                    –1
                                                    … и кешировать его, т.к. в случае отображения древовидных структур, в шаблонах набивается некислая такая логика
                                                +6
                                                Так как у нас тут пока ещё свобода слова, то пожалуй оставлю каплю своего негатива.
                                                Никаких обид, говорю только по делу. Статью надо было назвать: «ура, я начал изучать angular js, смотрите что он умеет». Carts в переводе на русский будет тележки. Я не специалист по Phalcon/php, но SQL-запросы в циклах? Не эксперт по деревьям, но думаю тут лучше подошла бы MongoDB для приложения в целом. Больно смотреть на php внутри angular шаблонов, однако если вы настолько обеспокоены своей сео-оптимизацией, то может проще было взглянуть на решения вроде prerender.io? Если бы это был мой магазин, я бы сео-оптимизацией не беспокоил бы себя в принципе. Гораздо проще и выгоднее купить рекламу. А дальше сайт, если хороший — раскрутит себя самостоятельно. Задача сео в данном контексте как раз таки выдать сайт по запросу вроде «заказать пиццу онлайн караганда». Ну и к слову — надеюсь, что вы хотя бы проверяете на сервере что прислал клиент, и перезваниваете ему. Используя мощь AngularJS + localStorage можно чисто на стороне клиента, создать многофункциональный лендинг, который будет делать всё настолько красиво, что серверу останется лишь отдать ему товары (rest/rpc/inline-js) и принять заказ, предварительно его проверив. Какой у вас тут смысл от angular? На Vanilla JS можно то же самое написать и работать будет намного быстрее. Хранить картинки в базе идея плохая на мой взгляд. Да и если я правильно понимаю админов вы «angular'ом» обделили, оставив им «перезагружающиеся страницы». Админка к слову плохая. Внутри не дерево, а просто список аля «проследи кто у кого предок».
                                                  +1
                                                  Не со всем, но со многими вещами согласен. В отличие от автора предыдущего комментария, я настроен спокойнее, хотя и понимаю его довольно резкое высказывание. Впрочем, дополню. Простите, но так вот нельзя:
                                                  > $category = Category::find()->toArray();

                                                  И здесь же, но ниже, уже никакого CamelCase:
                                                  > $category[$key]['url'] = $help->translit_url($val['name']);

                                                  В теории, ничего страшного. Но на практике это маленькая выходка одного программиста (если не считать замечаний предыдущего комментатора), но громадный геморрой всей команде впоследствии, т.к. порядок, если он есть, должен быть во всем. Очень скоро начнут появляться функции-близнецы, одинаково используемые по коду… например, func_name и funcName. Говорю из реального опыта: имел дело с системой, где были такие вот «близнецы». При этом, схожесть названия не мешала им работать совершенно по-разному.
                                                    0
                                                    Видимо товарищ никогда не работал в команде еще. Отсюда и такие грабли. И все эти магические цифры

                                                         if($scope.delivery == 3)
                                                            {
                                                                delivery = 10/total*100*(-1);
                                                            }
                                                    

                                                    которые потом он сам же, спустя полгода, будет мучительно разбирать, когда понадобится добавить еще одно условие доставки или поменять скидку
                                                      0
                                                      Справедливости ради замечу: недостаток опыта — это очень простой недостаток. Он очень легко компенсируется, и все у автора будет еще впереди. А то налетели, коршуны.
                                                    0
                                                    Вопрос по prerender.io

                                                    Получается он прокликивает страницу и сохраняет html-снапшоты всех возможных состояний, которые и отдает в итоге поисковикам?
                                                      0
                                                      Нет, не прокликивает.
                                                      prerender.io отдаёт поисковому боту HTML, «сфотографированный» после того, как закончатся все AJAX запросы или по установке специального флага.
                                                      А вот поисковый бот потом уже «кликает» по ссылкам.

                                                      Мы тоже им пользовались почти полгода. Для проекта с 150 000 страниц он стал работать на редкость гадостно.
                                                      Взяли исходники, которые лежат на github в упрощённом виде, без веб-интерфейса и очередей, изучили и сделали свой github.com/icons8/impresser
                                                      Документация — не пинайте ногами, пожалуйста :( — нет вообще, даже в коде комментариями
                                                      Сейчас отрисовывает полмиллиона страниц, по 3-5 секунд на каждую, но делает это регулярно и поисковым ботам выдаёт результат за миллисекунды.
                                                      Требует выделенный сервер, потому что фантом очень жрёт процессор и на VDS упирается именно в производительность виртуальных процессоров. Мы взяли один в США, чтобы было максимально близко от серверов, на которых работают гуглоботы.

                                                      Зачем prerender/impresser, если гуглобот умеет исполнять Javascript?
                                                      Во-первых, гуглобот не понимает, что страница ждёт данных через AJAX — в результате в поисковый индекс попало много пустых страниц с крутящийся картинкой-загрузчиком. У prerender есть специальный флаг в javascript, чтобы подождать, пока страница не готова.
                                                      Во-вторых, Yandex, Bing, Yahoo и много других поисковых систем не умеют исполнять JS и видят вообще пустые страницы.
                                                      В-третьих, боты социальных сетей не умеют исполнять Javascript. В результате, например, Facebook не видит название страницы и иллюстрацию к ней, если теги Open Graph динамически заполняются через Angular.

                                                      Попробуйте сравнить результаты:
                                                      Инструкция take.ms/BzPOr черех Google Chrome.
                                                      Откройте страницу ic8.link/very_basic в одной обычной вкладке браузера и в другой вкладке в режиме эмуляции устройств с UserAgent = «googlebot».
                                                      HTML страницы загружаются быстрее и вообще не содержат никакого JS. Их можно шарить через соц сети.
                                                    –2
                                                    А почему был выбран AngularJS? JQuery уже ведь грузится с Zurb Foundation
                                                      +1
                                                      Я не понимаю, почему раньше чтобы набрать 9 плюсов надо было классную статью написать, а сейчас можно написать что угодно в любом качестве.
                                                        +2
                                                        Тема не раскрыта.
                                                        Почему Phalcon + AngularJS + Zurb Foundation?
                                                        Корзина по хорошему, в рамках подобного проекта, пишется на javascript в несколько строк (можно вообще без ооп). В чем преимущество использовать связки эти и т.п.? Зачем в таком простом проекте использовать ORM?

                                                        В общем тема поста не соответствует действительности, после прочтения больше вопросов чем ответов. На недели делал одностраничный магазин, на голом php+mysql+javascript по времени ушло часов 10 (с версткой и доп.правками которых не было в макете, сам программинг часа 3-4 ).

                                                        Так в чем приемущество? Не будет ли проще, быстрей, понятней и удобней в мелких работах без фреймворков обойтись? Может и не пришлось бы запихивать запрос в цикл.
                                                          0
                                                          Можно и без фреймворков вообще и без ORM. Вот сравнение «с фреймворком или без».
                                                          Я бы сказал — чем владеет, на том и делает.
                                                          В данном случае ORM не страшен, потому его в меру. А та часть Фалькона, которая реалиует микросервисы — очень хорошо подошла бы для Reach Client Application, которые данные с сервера забирают только через AJAX — код получается компактным, изящным.
                                                          –1
                                                          Опять куча фреймворков и как обычно получается «велик»…
                                                          А не проще ли использовать готовые решения. К примеру opencart.
                                                          Будет гораздо проще, а функционал на много порядков больше.

                                                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                          Самое читаемое