Art-revolver или как не стоит делать сайты
Я хотел рассказать об этом проекте, когда он будет уже совсем в production, но его у меня забрали, поэтому, чтобы не забыть, пишу сейчас.
Я не ставлю целью якобы обличить “дураков-заказчиков” и “дураков-менеджеров”, а себя выгородить как жертву обстоятельств, а просто пытаюсь поделиться опытом и рассказать, как не стоит делать сайты. Тем более сложные.
Сначала расскажу немного о себе, чтобы вы понимали обстановку на момент начала работы над проектом. Мне 23, программирую с переменным успехом с 15 лет, были долгие (несколько лет) перерывы в связи с отсутствием компьютера и/или должной мотивации. Поэтому в то время, когда некоторые мои ровесники на этом ресурсе вовсю пишут дополнения с применением Node.js, я едва научился делать действительно неплохие сайты. Работать с MODX Revo я начал осенью 2015 года, до этого год делал сайты на OpenCart, до этого год – на MODX Evo.
Собственно, именно с осени 2015 началась разработка этого проекта. Полгода он обсуждался заказчиком и директором веб-студии, в которой я работал. Заказчик – профессиональный фотограф с большим опытом и собственной большой студией, лауреат международных выставок. Он обнаружил, что на российском рынке отсутствует ресурс, похожий на всемирно известный YelloKorner и решил сделать его аналог.
YelloKorner – это огромный интернет-магазин с фотографиями, которые печатаются ограниченным тиражом на отличной бумаге и имеют уникальные идентификаторы. Почти тоже самое, что купить хорошую картину, в общем-то. Так вот. Несмотря на то, что проект обсуждался с сентября 2015 по январь 2016, я к моменту начала работы не получил вообще никакого технического задания. Только общие фразы: “интернет-магазин с двумя языками, опциями товара, от которых зависит цена, личный кабинет и платежная система”. Если убрать всю воду из того “ТЗ”, то получается, что это все. Бюджет на разработку, прошу не ржать в голос – десять в пятой степени рублей, из них только (два в шестой степени минус четыре) тысяч рублей – на оплату труда программиста. Техническое задание я придумал у себя в голове уже тогда, когда получил дизайн-макеты будущего сайта.
И оно получалось примерно таким:
Мультиязычный интернет-магазин по продаже фотографий с различными опциями – размер фото, наличие/отсутствие рамки, выбор бумаги. Каждая опция имеет свою цену, и при ее выборе общая цена товара меняется. При изменении размера фотографии и ее опций – рамка, тубус, бумага – фотография товара должна меняться на соответствующую заданным параметрам. На сайте должна быть функция фотобанка – продажа цифровых копий фотографий по заданной стоимостьи, с защитой от копирования и защитой от несанкционированного скачивания. На сайте должен быть реализован личный кабинет автора – человека, который выставляет свои фотографии на продажу. Он должен иметь возможность менять аватарку, фон в личном кабинете, заполнять информацию о себе, указывать ссылки в соц.сетях, а так же, добавлять товары. Цены на сайте должны быть реализованы в двух валютах – рубли и евро. При переключении языка цена товара меняется на соответствующую: русский – рубли, английский – евро, с конвертацией по актуальному курсу. На сайте должен быть реализован блог – раздел, где авторы делятся своим опытом и дискуссируют на различные темы. Блог, опять же, двуязычный. На сайте должна присутствовать поисковая система и фильтр товаров по характеристикам – цветовой тон фотографии, раздел, тип товара (живопись, фото, фотобанк). Оплата на сайте должна производиться с помощью систем PayPal для иностранных клиентов и Яндекс.Касса для российских. Все.
Ошибка номер 1. При создании более-менее нестандартного сайта требуйте полное техническое задание. Со всеми, со всеми подробностями! Если ни у кого нет на ТЗ времени – не беритесь за проект, пока ТЗ не будет. Или составьте сами посредством интервью с заказчиком. За отдельную плату, офкорс.
Окей. Так как я был работником веб-студии, оспаривать бюджет права не имел, ибо все равно, оплата сдельная, а не попроектная. Получаю свои пять умножить на шесть тысяч рублей в месяц и ок. Начал работу. Мне с самого начало казалось, что моих способностей на это не хватит, но договор есть, крутись-вертись, но делай. Да и по-хорошему, такое бы на каком-нибудь Laravel делать, ведь чуяло мое сердце, что все будет не так просто, особенно с фотобанком. Это же ведь, защиту нужно придумать, способ передачи фотокопии клиенту, и вообще и вообще. Но, наша веб-студия делала сайты только на MODX Revo, и никак иначе.
Итак, ход мыслей:
Размер 30*45 Базовая цена
Размер 40*60 Кастомная цена
Размер 120*180 Кастомная цена
Бумага Fuji 0 рублей
Бумага Epson 1000 рублей
Без рамки 0 рублей
Пенокартон 1000 рублей
Пенокартон + рамка 2000 рублей
Техническое задание получается теперь таким:
Интернет-магазин по продаже фотографий с различными опциями – размер фото, наличие/отсутствие рамки, выбор бумаги. Каждая опция имеет свою цену, и при ее выборе общая цена товара меняется. Но! Все опции взаимосвязаны между собой определенным ценовым коэффициентом. То есть, если размер фотографии 30*45, то цена бумаги одна, цена рамки одна, то при размере фотографии 40*60 цена бумаги становится другой, цена рамки – другой, и все в том же духе. Мало того. Размеры фотографий тоже должны задаваться вручную, так как не всегда фотографии делаются именно в этих стандартных размерах, есть исключения. При этом, для определенного типа бумаги действительны одни размеры фотографии, для другого типа бумаги – другие, так как большой формат не печатают на Fuji, а маленький не печатают на Epson. А с холстом вообще все сложно – его нельзя натянуть на паспарту и пенокартон, только в рулоне или подрамнике. А для фотобумаги нельзя выбрать подрамник.
Получается крайне изощренная система опций. Если попытаться осмыслить всю эту систему с первого раза, то скорее всего, голова задымится. А ведь это еще закодить надо…
Логика работы фотобанка тоже пересмотрена заказчиком – товар не продается по одной цене, можно купить разные копии фото – в маленьком разрешении, в стандартном, и в HD.
Система с Babel тоже не выдерживает критики от заказчика, так как заполнять два ресурса для одного товара слишком утомительно, да и в блоге должны быть и русские комментарии, и зарубежные. Необходимо сделать так, чтобы язык менялся как-то иначе, Babel ну вообще не вариант.
Итак. После встречи оказывается, что нужно за десять в пятой степени рублей сделать убер-магазин с нереальным функционалом, когда разработчик (т.е. я) ничего сложнее магазина свадебных платьев никогда не делал. Я понимаю, что все, что я могу сделать – это суперкостыльный сайт, но ничего с этим поделать не могу, так как я единственный разработчик с кучей проектов на очереди. И что же мы делаем дальше?
Правильно! Еще на месяц забиваем на этот проект, ибо он на рассрочке, а деньги-то нужны. Тем временем в моей жизни происходят кое-какие изменения, и я вынужден покинуть место работы и уехать из города на пару месяцев. Я нахожу себе замену – на MODX.pro я оставлял даже соответствующее объявление, и уезжаю. Art-revolver остается на мне, так как новый разработчик, хоть вроде, даже поумнее меня, но ему сходу дают парсинг и перенос крупного сайта с самописной CMS на MODX + все старые проекты. Ему точно некогда, и так, задержки по всем фронтам. Договариваемся с боссом, что я за оставшиеся из бюджета пять умножить на шесть тысяч рублей доделаю этот сайт и мы больше ничего друг другу не должны. Сайт практически не работает, все нужно переделывать. То есть, по цене обычного небольшого магазина я должен за два месяца сделать суперпроект. Но деваться некуда, иных источников дохода я найти не могу, так как обстоятельства, беру и делаю.
Ошибка номер 2. Если дело пахнет керосином, а денюжка небольшая – бегите. Больше потеряете, чем заработаете. И это не только о деньгах. Еще есть нервы там, личное время…
Ошибка номер 3. Если вы понимаете, что не осилите проект, не сможете сделать его хорошо – лучше слиться. Репутация и отношения дороже. У меня забрали проект, почти ничего не объяснив и никто со мной теперь не общается из тех людей. Такие дела.
Итак, я, находясь в непростой ситуации, начинаю уже более-менее осмысленно делать проект, теперь хотя бы есть общая картинка того, как это видит заказчик.
Далее по тексту наконец-то будут технические подробности реализации, УРА!
Так как я ранее много работал с OpenCart, то решил использовать их систему мультиязычности, в контексте работы с MODX. И такую систему я накостылил следующим образом.
В менюшке есть переключалка языка – rus/eng. Язык по-умолчанию – русский. Ссылка на переключалке имеет GET-параметр “lang”, который передает серверу команду на переключение словарей в плагине на событие OnHandleRequest и сохраняет текущую настройку в куках:
На фронте замена всего происходит так.
Пункты меню, наименования опций, кнопки и прочая фиготень берут тексты из нужных записей словаря текущего языка:
Названия ресурсов и их страниц обрабатывают сниппеты getPagetitle и getContent:
Система опций.
Бэкенд.
Толком кодить на JS я не умею, кастомизировать miniShop2 и админку MODX для меня задача непосильная. До сих пор боюсь. Решил продолжить делать все на MIGX, знатно расширив таблицу опций и сделав значения по-умолчанию, а если надо, то в карточке товара можно что-нибудь подправить. Расширил таблицу следующим образом – есть пять размеров фотографии – от обычной рамочной, до полотна на всю стену. Каждый размер имеет свои ценовые значения для каждой опции – бумага, рамка, тубус, стоимость печати. По идее, при выборе нужного чекбокса на фронтенде, JS-скрипт лезет через AJAX на сервер и тянет нужные цены для выбранного параметра, типа, вот так:
Сама таблица опций MIGX выглядит так:
Фронтенд.
Боль моей души. Мой ночной кошмар. Мое незнание JavaScript…
Когда я начинал учиться веб-разработке, то у меня было две книги по HTML 4 (дело было в 2009 году), написанные русскими авторами, и оба они советовали забить на JS, ибо Flash это революция и он всех порвет. С тех пор и до 2016 года я упорно забивал на изучение JS (а препод по JS в универе только усилил ненависть к JS) и юзал только jQuery. Удобно же.
Ошибка номер 4. Выучи JS. Научись делать все классами/методами/объектами, и перестань быдлокодить на уровне if/else.
Собственно, за систему опций мне стыдно больше всего на этом сайте. Те, кто осиливает сейчас этот текст, и до сих пор не забил, может зайти на сайт и поковырять там код в карточке товара. Обещаю – скучно не будет. Когда я это писал, я уже понимал, что это полное д***мо. Но иначе не умел. Да и сейчас, я едва-едва начал что-то понимать в классах и методах, благо немного освоил Node.js, он дал мне неплохое представление о хорошем JS коде. Да и изучение исходников JS кода miniShop2 тоже помогает.
Когда я закончил эту систему опций, если не ошибаюсь, в июле, Володя выкатил новый, обновленный релиз msOptionsPrice2.
Интересно узнать, умеет ли этот компонент все то, что заложено в ТЗ в этом топике?
upd. Изменение фото в зависимости от опций
При выборе параметров необходимо изменять превью и фото товаров на соответствующие опциями. Совать 32 возможных варианта в админку — нереально, плюс неизвестно, как это выводить. Поэтому решение получилось примерно таким:
Есть две подложки — для маленьких форматов и больших — на столе и за диваном.
Есть само изображение товара. Есть опции в виде рамок и их цветов.
Путем переключения radio кнопок с помощью HTML+CSS я накладываю одну картинку на другую и CSS рисую рамку. Чтобы CSS был более-менее адекватным, была сделана система префиксов параметров:
размер фона — ориентация фото — размер фото, то есть, в боевом режиме:
класс .sofa-vertical-real означает показать фотографию за диваном в вертикальной ориентации в большом размере
Далее. Личный кабинет.
Так как к этому времени Володя уже убрал из магазина UserProfile, то ничего не оставалось, как купить Office. Запросил бюджет на компонент от заказчика, настроил по мануалу. А дальше самое интересное. По-идее, на сайте должно быть две группы пользователей – авторы и покупатели. Авторы – выставляют товары, делают посты, имеют аватарки и личные странички. Покупатели – только покупают и смотрят в личном кабинете статус заказа. Оказалось, что НИКТО вообще не знает, как должен выглядеть кабинет покупателя и что там должно быть. Мало того, оказалось, что НИКТО до конца не знает, как должен выглядеть кабинет автора, и что там должно быть. Нет, на макете был нарисован кабинет автора – личная страничка, аватарка, текст о себе, ссылки в соц.сетях, выставленные работы. Но нет кнопок – добавить товар, редактировать товар, выйти из личного кабинета, еще-что нибудь. На мои плечи, помимо реализации двух разных кабинетов, еще ложится разработка логики работы авторов и покупателей, так как никто кроме меня вообще не в курсе того, что это нужно. Иначе вообще же смысла в кабинете нет.
Повторяю ошибку номер 1. Техническое задание. Полностью. Без него трудные проекты – не брать. Нельзя сделать хороший проект на одних разговорах. Нельзя. Нереально.
Итак, права пользователей и роутинг кабинетов. В админке создаем два контейнера ресурсов – пользователи и авторы. На всякий затер id страниц, мало ли что.
Далее создаем две группы пользователей – users и authors.
Роутинг осуществляется по заметке Василия, в плагине на событие OnPageNotFound, примерно так:
Сам же шаблон страницы автора не так интересен. Картинка-фон к кабинету это адрес картинки, который хранится в extended поле юзера, его биография и ссылки на соц.сети – тоже extended. Как я реализовал загрузку кастомной картинки в кабинет пользователя – не помню. Не могу найти в исходниках (о бардаке в чанках и сниппетах — позже).
Внезапно оказывается, что заказчик хочет менять цвет текста-описания биографии. Естественно, учить HEX-кодам не вариант, HTML 5 поле color не все браузеры еще умеют, прилепил jQuery плагин, который показывает форму выбора цвета и сохраняет в extended поле HEX код. А при загрузке кабинета это прописывается прям в “style” атрибут тега с текстом. Костыль, но опять же. Задача внезапная, а увеличения бюджета тоже не планируется.
На следующий день заказчик хочет, чтобы во время редактирования текста биографии в textarea поле отображалась фоновая картинка, чтобы можно было менять цвет текста и сразу смотреть как это выглядит.
Ошибка номер 4. Никаких новых хотелок по ходу работы. Только после завершения оговоренных работ. Иначе разработка превратится в бесконечный цирк, где денег за доп.работу можно и не увидеть. Или увидеть не в полном объеме.
Загрузка товаров авторами
Это тоже задачка была не из простых, но к счастью, есть ms2Form. С горем-пополам настроил модуль, товары создаются. Правда, из-за того, что товары разные, и каждый тип имеет свои уникальные характеристики, пришлось сделать сначала выбор типа товара, потом AJAX’ом загружать сниппет и отдавать шаблон.
—
Во время настройки ms2Form произошел знатный прикол, который отнял у меня пару дней времени. Оказалось, что если один пользователь загружает фото товара к своему товару, но внезапно бросил это дело, и закрыл браузер, то если другой автор будет грузить свой товар и свои фото, то он будет видеть, что грузил другой автор. Но так как права на редактирования чужих товаров он не имеет, то и свой товар загрузить не может. Конфликт! Решилось ковырянием исходников ms2Form и раскомментированием последних строчек в сниппете ms2Form (да, нужные строчки были почему-то закомментированы).
В общем, с горем пополам, за две-три недели личные кабинеты пользователей двух групп и доступ к анонимам был реализован.
Переходим к самому прикольному – фотобанку
Идея реализовать полноценный фотобанк в стиле Fotolia на базе MODX, имея не самые хорошие знания платформы, как я уже говорил, с самого начала казалось мне плохой. Но, вызов принят. Арсенал костылей еще полон, полный вперед!
Итак, идея примерно такова.
Нужен раздел на сайте, продающий цифровые товары, то есть, ссылки на фотографии в различном разрешении. При этом, файлы нельзя скачать посторонним пользователям, доступ к ссылке имеют только купившие товар. В идеале, ссылка всегда должна хэшироваться и для каждого юзера быть уникальной. Фотографии хранятся в HD, и весят по 15-20 мегабайт. Хранить все это добро на shared-хостинге идиотизм. Но об этом, как всегда, никто не подумал. Поэтому я, вооружившись Swift, настроил облако Selectel и фотобанк хранится там. Хранение фотографий сначала реализовал с помощью FileAttach. Он даже ссылочки хэшировать умеет. Но, как оказалось, он работает только с локальным хранилищем, а с облаком не умеет. Ума допилить компонент у меня не хватило. Поэтому я обратил внимание на компонент от Володи – UserFiles. Подостовав Володю в тех.поддержке, я таки-настроил компонент и фотки загружаются в Selectel и хранятся там. Проблема только в том, что ссылки не хэшируются, и купивший фотографию человек, может спокойно расшарить ссылку всем. Но, думаю, до этого не дойдет.
Как же сделана выдача ссылок покупателю?
Подразумевается, что купить фотку в фотобанке можно только картой. Значит, у такого товара будет статус “ОПЛАЧЕН”. Выходит, задача такая – найти пользователя, который купил этот товар, проверить статус товара и вывести сниппет UserFiles со ссылкой на фотку. Создал сниппет getBuyingPhotos и поместил вызов сниппета на странице покупателя, сразу под стандартным кабинетом Office на ExtJs.
Код сниппета getBuyingPhotos:
Бардак в коде
Проект делался (а точнее, делается) уже год.
За это время мои знания улучшались, но из-за спешки в реализации я не соблюдал никакой логики в хранении и именовании элементов, поэтому сейчас на сайте, чтобы понять, как что-то работает, нужно убить достаточно времени, ибо сразу отыскать все сниппеты и чанки задача не из легких.
Уже в сентябре я освоил Fenom и файловые элементы, когда большая часть была сделана, а переделывать такую махину было уже лень. Тем более, не забываем о оплате в пять умножить на шесть тысяч рублей. Тратить еще две недели на переписывание этого кошмара мне уже не моглось.
Ошибка номер 5. Следуй какой-то методике хранения элементов. Правильно называй чанки/сниппеты/плагины. Разложи все по папкам. По-хорошему – сделай все на файловых элементах Fenom, чтобы четко видеть местоложение всех элементов. Это реально удобно. Точнее, это нереально удобно.
Я уверен, что текущий разработчик, который занимается этим проектом, наверняка увидит этот пост, и может даже обратит на него внимание босса и заказчика. Возможно, я даже получу по шапке за эту публикацию. Но, я уверен, никаких договоренностей на этот счет нет ни у кого, а я вообще, как бы, не при делах. Да и код, по сути, мой. Почти что интеллектуальная собственность.
P.S. Я все же получил еще доплату за проект в размере два в четвертой степени минус одна тысяча рублей. Итого, за 8 месяцев работы гонорар по проекту вышел в два в шестой степени плюс одиннадцать тысяч рублей. Стоит ли проект этот суммы, несмотря на костыли? Как считаете?
P.S.2. За последние полгода я сделал достаточно проектов, за которые мне ни разу не стыдно. Все сделано реально круто. Везде Fenom, грамотное наследование шаблонов, неплохо (а местами очень хорошо) написанные сниппеты, хорошая верстка, TV в работе с miniShop2 почти не использую, только плагины товаров, вовсю использую словари и системные параметры, ну и вообще, за исключением внезапных приступов тупости (можно видеть в моих предыдущих топиках), считаю, что могу сказать, что делаю хорошие сайты. Но с Art-revolver судьба не сложилась.
Я не ставлю целью якобы обличить “дураков-заказчиков” и “дураков-менеджеров”, а себя выгородить как жертву обстоятельств, а просто пытаюсь поделиться опытом и рассказать, как не стоит делать сайты. Тем более сложные.
Сначала расскажу немного о себе, чтобы вы понимали обстановку на момент начала работы над проектом. Мне 23, программирую с переменным успехом с 15 лет, были долгие (несколько лет) перерывы в связи с отсутствием компьютера и/или должной мотивации. Поэтому в то время, когда некоторые мои ровесники на этом ресурсе вовсю пишут дополнения с применением Node.js, я едва научился делать действительно неплохие сайты. Работать с MODX Revo я начал осенью 2015 года, до этого год делал сайты на OpenCart, до этого год – на MODX Evo.
Собственно, именно с осени 2015 началась разработка этого проекта. Полгода он обсуждался заказчиком и директором веб-студии, в которой я работал. Заказчик – профессиональный фотограф с большим опытом и собственной большой студией, лауреат международных выставок. Он обнаружил, что на российском рынке отсутствует ресурс, похожий на всемирно известный YelloKorner и решил сделать его аналог.
YelloKorner – это огромный интернет-магазин с фотографиями, которые печатаются ограниченным тиражом на отличной бумаге и имеют уникальные идентификаторы. Почти тоже самое, что купить хорошую картину, в общем-то. Так вот. Несмотря на то, что проект обсуждался с сентября 2015 по январь 2016, я к моменту начала работы не получил вообще никакого технического задания. Только общие фразы: “интернет-магазин с двумя языками, опциями товара, от которых зависит цена, личный кабинет и платежная система”. Если убрать всю воду из того “ТЗ”, то получается, что это все. Бюджет на разработку, прошу не ржать в голос – десять в пятой степени рублей, из них только (два в шестой степени минус четыре) тысяч рублей – на оплату труда программиста. Техническое задание я придумал у себя в голове уже тогда, когда получил дизайн-макеты будущего сайта.
И оно получалось примерно таким:
Мультиязычный интернет-магазин по продаже фотографий с различными опциями – размер фото, наличие/отсутствие рамки, выбор бумаги. Каждая опция имеет свою цену, и при ее выборе общая цена товара меняется. При изменении размера фотографии и ее опций – рамка, тубус, бумага – фотография товара должна меняться на соответствующую заданным параметрам. На сайте должна быть функция фотобанка – продажа цифровых копий фотографий по заданной стоимостьи, с защитой от копирования и защитой от несанкционированного скачивания. На сайте должен быть реализован личный кабинет автора – человека, который выставляет свои фотографии на продажу. Он должен иметь возможность менять аватарку, фон в личном кабинете, заполнять информацию о себе, указывать ссылки в соц.сетях, а так же, добавлять товары. Цены на сайте должны быть реализованы в двух валютах – рубли и евро. При переключении языка цена товара меняется на соответствующую: русский – рубли, английский – евро, с конвертацией по актуальному курсу. На сайте должен быть реализован блог – раздел, где авторы делятся своим опытом и дискуссируют на различные темы. Блог, опять же, двуязычный. На сайте должна присутствовать поисковая система и фильтр товаров по характеристикам – цветовой тон фотографии, раздел, тип товара (живопись, фото, фотобанк). Оплата на сайте должна производиться с помощью систем PayPal для иностранных клиентов и Яндекс.Касса для российских. Все.
Ошибка номер 1. При создании более-менее нестандартного сайта требуйте полное техническое задание. Со всеми, со всеми подробностями! Если ни у кого нет на ТЗ времени – не беритесь за проект, пока ТЗ не будет. Или составьте сами посредством интервью с заказчиком. За отдельную плату, офкорс.
Окей. Так как я был работником веб-студии, оспаривать бюджет права не имел, ибо все равно, оплата сдельная, а не попроектная. Получаю свои пять умножить на шесть тысяч рублей в месяц и ок. Начал работу. Мне с самого начало казалось, что моих способностей на это не хватит, но договор есть, крутись-вертись, но делай. Да и по-хорошему, такое бы на каком-нибудь Laravel делать, ведь чуяло мое сердце, что все будет не так просто, особенно с фотобанком. Это же ведь, защиту нужно придумать, способ передачи фотокопии клиенту, и вообще и вообще. Но, наша веб-студия делала сайты только на MODX Revo, и никак иначе.
Итак, ход мыслей:
- Мультиязычность – значит Babel.
- Личный кабинет – Office. Но, он платный, а бюджет и так никакой. Однако, тогда еще лежал в репозитории UserProfile и Virtual Page от Володи. Берем.
- Магазин – значит miniShop2.
- Блог – Tickets.
- Цены в валюте – CurrencyRate.
- Поиск – mSearch2.
- Платежные системы – и так все ясно.
- Верстка – Bootstrap, ибо полюбил.
- Virtual Page и User Profile толком не хотят работать. То ли я криворукий, то ли что, но кабинет автора ну вообще не получался. Еле-еле сделал какое-то демо, где можно было менять аватарку и менять пароль с личной информацией.
- Опции товара с помощью MIGX и кривонаписанного JS скрипта реализовал созданием скрытого поля options[], которое добавляло стоимость.
Размер 30*45 Базовая цена
Размер 40*60 Кастомная цена
Размер 120*180 Кастомная цена
Бумага Fuji 0 рублей
Бумага Epson 1000 рублей
Без рамки 0 рублей
Пенокартон 1000 рублей
Пенокартон + рамка 2000 рублей
- Мультиязычность через разные контексты сделал. Все работает. Но вот проблема – некоторые вещи, такие как опции товара и какие-то другие тексты не переводились через Babel. О словарях я тогда знал немного.
- Поиска еще не было, как не было и фильтра.
- Фотографии к товарам не меняются при изменении опций, ибо я хз как это сделать вообще. Идей не было никаких.
- Блог, понятно дело, получился одноязычным, ибо писать две статьи и иметь на одной версии русские комментарии, а на другой – английские это идиотизм.
Техническое задание получается теперь таким:
Интернет-магазин по продаже фотографий с различными опциями – размер фото, наличие/отсутствие рамки, выбор бумаги. Каждая опция имеет свою цену, и при ее выборе общая цена товара меняется. Но! Все опции взаимосвязаны между собой определенным ценовым коэффициентом. То есть, если размер фотографии 30*45, то цена бумаги одна, цена рамки одна, то при размере фотографии 40*60 цена бумаги становится другой, цена рамки – другой, и все в том же духе. Мало того. Размеры фотографий тоже должны задаваться вручную, так как не всегда фотографии делаются именно в этих стандартных размерах, есть исключения. При этом, для определенного типа бумаги действительны одни размеры фотографии, для другого типа бумаги – другие, так как большой формат не печатают на Fuji, а маленький не печатают на Epson. А с холстом вообще все сложно – его нельзя натянуть на паспарту и пенокартон, только в рулоне или подрамнике. А для фотобумаги нельзя выбрать подрамник.
Получается крайне изощренная система опций. Если попытаться осмыслить всю эту систему с первого раза, то скорее всего, голова задымится. А ведь это еще закодить надо…
Логика работы фотобанка тоже пересмотрена заказчиком – товар не продается по одной цене, можно купить разные копии фото – в маленьком разрешении, в стандартном, и в HD.
Система с Babel тоже не выдерживает критики от заказчика, так как заполнять два ресурса для одного товара слишком утомительно, да и в блоге должны быть и русские комментарии, и зарубежные. Необходимо сделать так, чтобы язык менялся как-то иначе, Babel ну вообще не вариант.
Итак. После встречи оказывается, что нужно за десять в пятой степени рублей сделать убер-магазин с нереальным функционалом, когда разработчик (т.е. я) ничего сложнее магазина свадебных платьев никогда не делал. Я понимаю, что все, что я могу сделать – это суперкостыльный сайт, но ничего с этим поделать не могу, так как я единственный разработчик с кучей проектов на очереди. И что же мы делаем дальше?
Правильно! Еще на месяц забиваем на этот проект, ибо он на рассрочке, а деньги-то нужны. Тем временем в моей жизни происходят кое-какие изменения, и я вынужден покинуть место работы и уехать из города на пару месяцев. Я нахожу себе замену – на MODX.pro я оставлял даже соответствующее объявление, и уезжаю. Art-revolver остается на мне, так как новый разработчик, хоть вроде, даже поумнее меня, но ему сходу дают парсинг и перенос крупного сайта с самописной CMS на MODX + все старые проекты. Ему точно некогда, и так, задержки по всем фронтам. Договариваемся с боссом, что я за оставшиеся из бюджета пять умножить на шесть тысяч рублей доделаю этот сайт и мы больше ничего друг другу не должны. Сайт практически не работает, все нужно переделывать. То есть, по цене обычного небольшого магазина я должен за два месяца сделать суперпроект. Но деваться некуда, иных источников дохода я найти не могу, так как обстоятельства, беру и делаю.
Ошибка номер 2. Если дело пахнет керосином, а денюжка небольшая – бегите. Больше потеряете, чем заработаете. И это не только о деньгах. Еще есть нервы там, личное время…
Ошибка номер 3. Если вы понимаете, что не осилите проект, не сможете сделать его хорошо – лучше слиться. Репутация и отношения дороже. У меня забрали проект, почти ничего не объяснив и никто со мной теперь не общается из тех людей. Такие дела.
Итак, я, находясь в непростой ситуации, начинаю уже более-менее осмысленно делать проект, теперь хотя бы есть общая картинка того, как это видит заказчик.
Далее по тексту наконец-то будут технические подробности реализации, УРА!
Так как я ранее много работал с OpenCart, то решил использовать их систему мультиязычности, в контексте работы с MODX. И такую систему я накостылил следующим образом.
В менюшке есть переключалка языка – rus/eng. Язык по-умолчанию – русский. Ссылка на переключалке имеет GET-параметр “lang”, который передает серверу команду на переключение словарей в плагине на событие OnHandleRequest и сохраняет текущую настройку в куках:
<?php
if($modx->context->key == "mgr"){return;}
else
{
$defaultLang = 'ru';
if (empty($_COOKIE['lang'])){
$siteLang = $defaultLang;
setcookie('lang',$siteLang);
} else {
$siteLang = $_COOKIE['lang'];
if (isset($_GET['lang'])){
if ($siteLang != $_GET['lang']){
$siteLang = $_GET['lang'];
setcookie('lang',$siteLang);
}
}
}
$modx->setOption('cultureKey', $siteLang);
$modx->getService('lexicon','modLexicon');
$modx->lexicon->load($siteLang.':art-revolver:default');
}
В админке сайта у каждого ресурса появляются TV-поля: content-en, pagetitle-en, longtitle-en. Теперь все данные заполняются в одном ресурсе, довольно удобно. Для менеджеров-то точно. Минус – все-таки это TV, занимает время на выборку + английский сайт не индексируется поисковыми системами (но это не точно).На фронте замена всего происходит так.
Пункты меню, наименования опций, кнопки и прочая фиготень берут тексты из нужных записей словаря текущего языка:
<div class="col-md-10">
<span class="option-name">Fuji</span>
<p class="photo-description">[[!%art-revolver.fuji]]</p>
</div>
Важно! Записи словаря должны вызываться некэшированными, иначе нифига не будет работать.Названия ресурсов и их страниц обрабатывают сниппеты getPagetitle и getContent:
<a href="[[+link]]" [[+attributes]]>[[!getPagetitle?&lang=`[[!%art-revolver.sitelang?&namespace=`art-revolver`]]`&id=`[[+id]]`]] </a>
Код сниппета getPagetitle (для getContent тоже самое. Можно даже универсально сделать, но тогда как-то это в голову не пришло):<?php
if ((isset($lang)) && (isset($id)) ){
$page = $modx->getObject('modResource', $id);
if ($lang == 'ru'){
$pagetitle = $page->get('pagetitle');
} else if ($lang == 'en') {
$pagetitle = $page->getTVValue('longtitle-en');
if ($pagetitle == ''){
$pagetitle = $page->get('pagetitle');
}
} else {
$pagetitle = $page->get('pagetitle').' / '.$page->getTVValue('longtitle-en');
}
return $pagetitle;
} else {
return 'эта строка не может быть отображена';
}
Вот таким, не очень хитрым способом я запилил мультиязычность на сайте. До сих пор считаю, что данная система имеет право на существование, но я бы очень хотел узнать методы улучшения, и очень интересно, как мультиязычность работает на MODX.pro. Система опций.
Бэкенд.
Толком кодить на JS я не умею, кастомизировать miniShop2 и админку MODX для меня задача непосильная. До сих пор боюсь. Решил продолжить делать все на MIGX, знатно расширив таблицу опций и сделав значения по-умолчанию, а если надо, то в карточке товара можно что-нибудь подправить. Расширил таблицу следующим образом – есть пять размеров фотографии – от обычной рамочной, до полотна на всю стену. Каждый размер имеет свои ценовые значения для каждой опции – бумага, рамка, тубус, стоимость печати. По идее, при выборе нужного чекбокса на фронтенде, JS-скрипт лезет через AJAX на сервер и тянет нужные цены для выбранного параметра, типа, вот так:
<?php
if ($_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest') {return;}
if (empty($_POST['action'])) {return;}
//На выходе всегда отдавались крокозябры, добавил header(), вроде помогло.
header('Content-Type: text/html; charset=utf-8');
$action = $_POST['action'];
$id = '';
$id = $_POST['id'];
//По полученным параметрам запускаем MIGX сниппет с параметром WHERE и тянем данные.
if ($product = $modx->getObject('msProduct', $id)) {
$output = $modx->runSnippet('getImageList',array(
'tvname' => 'photo_format',
'tpl' => 'photo_options-tpl',
'where' => '{"MIGX_id:=":"'.$action.'"}'
));
} else {
$output = '<h2>Невозможно загрузить страницу</h2>';
}
if (!empty($output)) {
die($output);
}
Весь скрипт вырван из заметки Василия за 2013 год о работе AJAX, ибо тогда я реально мало что в этом понимал. Сейчас мои AJAX запросы выглядят прикольнее. Правда.Сама таблица опций MIGX выглядит так:
[{"MIGX_id":"1","name":"[[!%art-revolver.photo-standart]]","description":"[[!%art-revolver.photo-standart-decription]]","size":"30*45","price":"4800","epson":"0","fuji":"0","canvas":"1600","nodecor":"0","mont1":"1120","mont2":"1760","printCanvas":"0","mont3":"800"},
{"MIGX_id":"2","name":"[[!%art-revolver.photo-optimal]]","description":"[[!%art-revolver.limited-edition]] 500 [[!%art-revolver.copies]]","size":"40*60","price":"8000","epson":"0","fuji":"0","canvas":"2640","nodecor":"0","mont1":"1280","mont2":"2800","printCanvas":"0","mont3":"960"},
{"MIGX_id":"3","name":"[[!%art-revolver.photo-real]]","description":"[[!%art-revolver.limited-edition]] 300 [[!%art-revolver.copies]]","size":"60*90","price":"12800","epson":"0","fuji":"0","canvas":"4000","nodecor":"0","mont1":"2400","mont2":"0","printCanvas":"0","mont3":"2000"},
{"MIGX_id":"4","name":"[[!%art-revolver.photo-exclusive]]","description":"[[!%art-revolver.limited-edition]] 200 [[!%art-revolver.copies]]","size":"100*150","price":"28000","epson":"0","fuji":"0","canvas":"10800","nodecor":"0","mont1":"6320","mont2":"0","printCanvas":"0","mont3":"2400"},
{"MIGX_id":"5","name":"[[!%art-revolver.photo-super]]","description":"[[!%art-revolver.limited-edition]] 100 [[!%art-revolver.copies]]","size":"120*180","price":"80000","epson":"0","fuji":"0","canvas":"16000","nodecor":"0","mont1":"9200","mont2":"0","printCanvas":"0","mont3":"4000"}]
Теги MODX используются для мультиязычности. Хитро. Хе-хе.Фронтенд.
Боль моей души. Мой ночной кошмар. Мое незнание JavaScript…
Когда я начинал учиться веб-разработке, то у меня было две книги по HTML 4 (дело было в 2009 году), написанные русскими авторами, и оба они советовали забить на JS, ибо Flash это революция и он всех порвет. С тех пор и до 2016 года я упорно забивал на изучение JS (а препод по JS в универе только усилил ненависть к JS) и юзал только jQuery. Удобно же.
Ошибка номер 4. Выучи JS. Научись делать все классами/методами/объектами, и перестань быдлокодить на уровне if/else.
Собственно, за систему опций мне стыдно больше всего на этом сайте. Те, кто осиливает сейчас этот текст, и до сих пор не забил, может зайти на сайт и поковырять там код в карточке товара. Обещаю – скучно не будет. Когда я это писал, я уже понимал, что это полное д***мо. Но иначе не умел. Да и сейчас, я едва-едва начал что-то понимать в классах и методах, благо немного освоил Node.js, он дал мне неплохое представление о хорошем JS коде. Да и изучение исходников JS кода miniShop2 тоже помогает.
Когда я закончил эту систему опций, если не ошибаюсь, в июле, Володя выкатил новый, обновленный релиз msOptionsPrice2.
Интересно узнать, умеет ли этот компонент все то, что заложено в ТЗ в этом топике?
upd. Изменение фото в зависимости от опций
При выборе параметров необходимо изменять превью и фото товаров на соответствующие опциями. Совать 32 возможных варианта в админку — нереально, плюс неизвестно, как это выводить. Поэтому решение получилось примерно таким:
Есть две подложки — для маленьких форматов и больших — на столе и за диваном.
Есть само изображение товара. Есть опции в виде рамок и их цветов.
Путем переключения radio кнопок с помощью HTML+CSS я накладываю одну картинку на другую и CSS рисую рамку. Чтобы CSS был более-менее адекватным, была сделана система префиксов параметров:
размер фона — ориентация фото — размер фото, то есть, в боевом режиме:
класс .sofa-vertical-real означает показать фотографию за диваном в вертикальной ориентации в большом размере
Далее. Личный кабинет.
Так как к этому времени Володя уже убрал из магазина UserProfile, то ничего не оставалось, как купить Office. Запросил бюджет на компонент от заказчика, настроил по мануалу. А дальше самое интересное. По-идее, на сайте должно быть две группы пользователей – авторы и покупатели. Авторы – выставляют товары, делают посты, имеют аватарки и личные странички. Покупатели – только покупают и смотрят в личном кабинете статус заказа. Оказалось, что НИКТО вообще не знает, как должен выглядеть кабинет покупателя и что там должно быть. Мало того, оказалось, что НИКТО до конца не знает, как должен выглядеть кабинет автора, и что там должно быть. Нет, на макете был нарисован кабинет автора – личная страничка, аватарка, текст о себе, ссылки в соц.сетях, выставленные работы. Но нет кнопок – добавить товар, редактировать товар, выйти из личного кабинета, еще-что нибудь. На мои плечи, помимо реализации двух разных кабинетов, еще ложится разработка логики работы авторов и покупателей, так как никто кроме меня вообще не в курсе того, что это нужно. Иначе вообще же смысла в кабинете нет.
Повторяю ошибку номер 1. Техническое задание. Полностью. Без него трудные проекты – не брать. Нельзя сделать хороший проект на одних разговорах. Нельзя. Нереально.
Итак, права пользователей и роутинг кабинетов. В админке создаем два контейнера ресурсов – пользователи и авторы. На всякий затер id страниц, мало ли что.
Далее создаем две группы пользователей – users и authors.
Роутинг осуществляется по заметке Василия, в плагине на событие OnPageNotFound, примерно так:
<?php
if ($modx->event->name != 'OnPageNotFound') {return false;}
$alias = $modx->context->getOption('request_param_alias', 'q');
if (!isset($_REQUEST[$alias])) {return false;}
$request = $_REQUEST[$alias];
$tmp = explode('/', $request);
// Ссылка подходит под заданный формат: user/username
if (($tmp[0] == 'user') || ($tmp[0]=='author')) {
// Теперь очищаем имя пользователя от возможного расширения
$name = str_replace('.html', '', $tmp[1]);
// Здесь будем определять, какую страницу надо показывать
// Дальше проверяем наличие запрошенного пользователя
if ($user = $modx->getObject('modUser', array('username' => $name))) {
if ($user->isMember('Authors')){
$tmp[0] = 'author';
if ($tmp[2] == 'comments'){
$section = __; // id ресурса для подстраницы «Комментарии»
}
} else {
if ($tmp[2] == 'comments'){
$section = __; // id ресурса для подстраницы «Комментарии»
}
}
if (!$section = $modx->findResource($tmp[0] . '/')) {
return false;
}
if ($tmp[1] != $name) {
$modx->sendRedirect($tmp[0] . '/' . $name . '/');
}
$modx->sendForward($section);
}
}
Но тут появляется такая проблема. Дело в том, что переходить в личный кабинет автора могут как сами авторы, так и пользователи из группы Users, так и анонимы. А у автором же в кабинете загрузчик товаров (о нем позже), статистика продаж, манипуляции с товарами, редактирование информации, замена аватарок, фона кабинета. И авторы могут переходить в режим кабинета покупателя, так как по сути, имеют на это все право. Поэтому формируется задача – редиректить users и authors только на их шаблоны кабинетов + запрещать показывать непринадлежащие формы и чанки, но дать анонимам и юзерам смотреть страницы авторов. Решил я это таким вот сниппетом: <?php
$alias = $modx->context->getOption('request_param_alias', 'q');
if (!isset($_REQUEST[$alias])) {return 'пустой запрос';}
$request = $_REQUEST[$alias];
$tmp = explode('/', $request);
$tmp[0] = strtolower($tmp[0]);
// Ссылка подходит под заданный формат: user/username
if (($tmp[0] == 'user') || ($tmp[0] == 'author') || ($tmp[0] == 'authors')) {
$name = strtolower(str_replace('.html', '', $tmp[1]));
// Здесь будем определять, какую страницу надо показывать
// Дальше проверяем наличие запрошенного пользователя
if ($user = $modx->getObject('modUser', array('username' => $name))) {
//получаем пользователя в сессии
$current_user = $modx->getUser();
$current_user = strtolower($current_user->get('username'));
//если запрошенный пользователь состоит в группе пользователей дать обычный шаблон, иначе - шаблон автора
if ($user->isMember('Users')){
$tpl = 'cabinet-tpl';
} else {
$tpl = 'author-cabinet-tpl';
}
//если имена пользователей сходятся, то запустить Офис, то есть пустить в личный кабинет
if ($name == $current_user){
$output = $modx->runSnippet('officeProfile',array(
'tplProfile' => $tpl,
'avatarParams' => '{"w":150,"h":150,"zc":1,"bg":"ffffff","f":"jpg"}'
));
return $output;
} else {
//Иначе - отобразить страничку пользователя
$u_name = $user->get('username');
$u_profile = $user->Profile->toArray();
$user_prop = array('username' => $u_name, 'cabinet-menu' => 'off');
$u_profile = array_merge($u_profile,$user_prop);
$modx->setPlaceholders($u_profile);
$output = $modx->getChunk($tpl, $u_profile);
return $output;
}
} else if ( ($name == 'add') || ($name == 'comments') || ($name == 'add-socials') || ($name == 'history') || ($name == 'edit') || ($name == 'my-selling') ){
if ($user = $modx->getUser()){
if ($user->isMember('Users')){
$tpl = 'cabinet-tpl';
} else {
$tpl = 'author-cabinet-tpl';
}
$output = $modx->runSnippet('officeProfile',array(
'tplProfile' => $tpl,
'avatarParams' => '{"w":150,"h":150,"zc":1,"bg":"ffffff","f":"jpg"}'
));
return $output;
}
}
}
Было бы интересно более элегантное решение, хотя бы в теории.Сам же шаблон страницы автора не так интересен. Картинка-фон к кабинету это адрес картинки, который хранится в extended поле юзера, его биография и ссылки на соц.сети – тоже extended. Как я реализовал загрузку кастомной картинки в кабинет пользователя – не помню. Не могу найти в исходниках (о бардаке в чанках и сниппетах — позже).
Внезапно оказывается, что заказчик хочет менять цвет текста-описания биографии. Естественно, учить HEX-кодам не вариант, HTML 5 поле color не все браузеры еще умеют, прилепил jQuery плагин, который показывает форму выбора цвета и сохраняет в extended поле HEX код. А при загрузке кабинета это прописывается прям в “style” атрибут тега с текстом. Костыль, но опять же. Задача внезапная, а увеличения бюджета тоже не планируется.
На следующий день заказчик хочет, чтобы во время редактирования текста биографии в textarea поле отображалась фоновая картинка, чтобы можно было менять цвет текста и сразу смотреть как это выглядит.
Ошибка номер 4. Никаких новых хотелок по ходу работы. Только после завершения оговоренных работ. Иначе разработка превратится в бесконечный цирк, где денег за доп.работу можно и не увидеть. Или увидеть не в полном объеме.
Загрузка товаров авторами
Это тоже задачка была не из простых, но к счастью, есть ms2Form. С горем-пополам настроил модуль, товары создаются. Правда, из-за того, что товары разные, и каждый тип имеет свои уникальные характеристики, пришлось сделать сначала выбор типа товара, потом AJAX’ом загружать сниппет и отдавать шаблон.
—
Во время настройки ms2Form произошел знатный прикол, который отнял у меня пару дней времени. Оказалось, что если один пользователь загружает фото товара к своему товару, но внезапно бросил это дело, и закрыл браузер, то если другой автор будет грузить свой товар и свои фото, то он будет видеть, что грузил другой автор. Но так как права на редактирования чужих товаров он не имеет, то и свой товар загрузить не может. Конфликт! Решилось ковырянием исходников ms2Form и раскомментированием последних строчек в сниппете ms2Form (да, нужные строчки были почему-то закомментированы).
В общем, с горем пополам, за две-три недели личные кабинеты пользователей двух групп и доступ к анонимам был реализован.
Переходим к самому прикольному – фотобанку
Идея реализовать полноценный фотобанк в стиле Fotolia на базе MODX, имея не самые хорошие знания платформы, как я уже говорил, с самого начала казалось мне плохой. Но, вызов принят. Арсенал костылей еще полон, полный вперед!
Итак, идея примерно такова.
Нужен раздел на сайте, продающий цифровые товары, то есть, ссылки на фотографии в различном разрешении. При этом, файлы нельзя скачать посторонним пользователям, доступ к ссылке имеют только купившие товар. В идеале, ссылка всегда должна хэшироваться и для каждого юзера быть уникальной. Фотографии хранятся в HD, и весят по 15-20 мегабайт. Хранить все это добро на shared-хостинге идиотизм. Но об этом, как всегда, никто не подумал. Поэтому я, вооружившись Swift, настроил облако Selectel и фотобанк хранится там. Хранение фотографий сначала реализовал с помощью FileAttach. Он даже ссылочки хэшировать умеет. Но, как оказалось, он работает только с локальным хранилищем, а с облаком не умеет. Ума допилить компонент у меня не хватило. Поэтому я обратил внимание на компонент от Володи – UserFiles. Подостовав Володю в тех.поддержке, я таки-настроил компонент и фотки загружаются в Selectel и хранятся там. Проблема только в том, что ссылки не хэшируются, и купивший фотографию человек, может спокойно расшарить ссылку всем. Но, думаю, до этого не дойдет.
Как же сделана выдача ссылок покупателю?
Подразумевается, что купить фотку в фотобанке можно только картой. Значит, у такого товара будет статус “ОПЛАЧЕН”. Выходит, задача такая – найти пользователя, который купил этот товар, проверить статус товара и вывести сниппет UserFiles со ссылкой на фотку. Создал сниппет getBuyingPhotos и поместил вызов сниппета на странице покупателя, сразу под стандартным кабинетом Office на ExtJs.
Код сниппета getBuyingPhotos:
<?php
$pdo = $modx->getService('pdoTools');
if (empty($tpl)){
$tpl = 'UFfileattach.tpl';
}
if (empty($tplOuter)){
$tplOuter = 'UFfileattachOuter.tpl';
}
//Если пользователь авторизован
if ($modx->user->isAuthenticated('web')) {
$current_user = $modx->getUser();
if (!isset($user_id)){
$user_id = $current_user->get('id');
}
//Создаем запрос
$query = $modx->newQuery('modResource');
//Проверяем необходимые параметры
$parent == '' ? $parent = __ : $parent;
$parent == '' ? $parent = __ : $template;
//условие
$query->where(array(
'parent' => $parent,
'template' => $template,
'ms2o.status' => $status,
'ms2o.user_id' => $user_id,
));
//Запрос с JOIN нужных таблиц
$query->select('modResource.id');
$query->leftJoin('msOrderProduct', 'ms2op', 'modResource.id=ms2op.product_id');
$query->leftJoin('msOrder', 'ms2o', 'ms2op.order_id=ms2o.id');
$query->prepare();
$query->stmt->execute();
$result = $query->stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($result as $res) {
$links .= $pdo->runSnippet('!pdoResources',array(
'parents' => __,
'limit' => 10,
'class' => 'UserFile',
'loadModels' => 'UserFiles',
'tpl' => $tpl,
'leftJoin' => '{
"Thumb": {
"class": "UserFile",
"on": "Thumb.parent = UserFile.id"
}
}',
'where' => '{"UserFile.parent":"'.$res['id'].'","UserFile.name:!=":"modelrelease"}',
'sortby' => 'rank',
'sortdir' => 'ASC',
'select'=>'{
"UserFile": "*",
"Thumb": "Thumb.url as thumb"
}'
));
}
// return $links;
if (!empty($links)){
$output = $pdo->getChunk($tplOuter,array('links'=>$links));
} else {
$output = '';
}
return $output;
} else {
$modx->sendUnauthorizedPage();
}
Таким вот образом я запилил что-то типа фотобанка. От вариаций покупки в разных разрешениях пришлось отказаться, так как слишком запарно, даже сам заказчик, кажется, забил на эту идею.Бардак в коде
Проект делался (а точнее, делается) уже год.
За это время мои знания улучшались, но из-за спешки в реализации я не соблюдал никакой логики в хранении и именовании элементов, поэтому сейчас на сайте, чтобы понять, как что-то работает, нужно убить достаточно времени, ибо сразу отыскать все сниппеты и чанки задача не из легких.
Уже в сентябре я освоил Fenom и файловые элементы, когда большая часть была сделана, а переделывать такую махину было уже лень. Тем более, не забываем о оплате в пять умножить на шесть тысяч рублей. Тратить еще две недели на переписывание этого кошмара мне уже не моглось.
Ошибка номер 5. Следуй какой-то методике хранения элементов. Правильно называй чанки/сниппеты/плагины. Разложи все по папкам. По-хорошему – сделай все на файловых элементах Fenom, чтобы четко видеть местоложение всех элементов. Это реально удобно. Точнее, это нереально удобно.
Я уверен, что текущий разработчик, который занимается этим проектом, наверняка увидит этот пост, и может даже обратит на него внимание босса и заказчика. Возможно, я даже получу по шапке за эту публикацию. Но, я уверен, никаких договоренностей на этот счет нет ни у кого, а я вообще, как бы, не при делах. Да и код, по сути, мой. Почти что интеллектуальная собственность.
P.S. Я все же получил еще доплату за проект в размере два в четвертой степени минус одна тысяча рублей. Итого, за 8 месяцев работы гонорар по проекту вышел в два в шестой степени плюс одиннадцать тысяч рублей. Стоит ли проект этот суммы, несмотря на костыли? Как считаете?
P.S.2. За последние полгода я сделал достаточно проектов, за которые мне ни разу не стыдно. Все сделано реально круто. Везде Fenom, грамотное наследование шаблонов, неплохо (а местами очень хорошо) написанные сниппеты, хорошая верстка, TV в работе с miniShop2 почти не использую, только плагины товаров, вовсю использую словари и системные параметры, ну и вообще, за исключением внезапных приступов тупости (можно видеть в моих предыдущих топиках), считаю, что могу сказать, что делаю хорошие сайты. Но с Art-revolver судьба не сложилась.
Поблагодарить автора
Отправить деньги
Комментарии: 38
и очень интересно, как мультиязычность работает на MODX.pro.Примерно так же, я это давно описывал.
Ну а вообще да, изрядная картина создания сайта на MODX из говна и палок за еду. Очень интересно, чем думает веб-студия, когда берёт такие проекты без ТЗ, сроков и выставляет смешные ценники. Жадность ли это, или банальная глупость?
Есть мнение, что для сдачи такого проекта заказчику, студия потратит больше, чем заработает.
Все в таком случае теряют больше, чем получают. Заказчик — год ждет результата. Разработчик — работает за еду, как вы верно подметили, а студия за этот год получает ужасно смешные деньги от этого проекта. Профита вообще никакого.
Такие проекты берут продажники или руководители, которые умеют только продавать. Плевать они хотели, как это будет делаться. Мыслят по-другому.
я бы десять раз плюсанул, но можно только один)
Без этих ребят все равно никуда не деться. Есть торговцы, есть технари.
Есть нормальные торговцы, которые вникают в вопрос и советуются с исполнителем прежде чем его на что-то подписывать. Есть торговцы, которые просто «продать то не знаю что, главное побольше». Ему обороты, а тебе — сам разбирайся
Согласен. Но зачастую, это простые барыги. Рынок, знаете ли… диктует сои правила.
Так и живем)
Захватывающая история, но я бы на месте автора убрал хотя бы наименование сайта.
Всё же заказчик не виноват что менеджер проектов не опирается на опыт работников.
А так что я могу сказать, описаны советы от капитана:
Без ТЗ получаем ХЗ
Всё же заказчик не виноват что менеджер проектов не опирается на опыт работников.
А так что я могу сказать, описаны советы от капитана:
Без ТЗ получаем ХЗ
Немножко убрал название сайта. Теперь нужно погуглить, чтобы найти. В статье все-таки есть некоторый объем кода, и хотелось показать его в деле. А без кода и демонстрации это получаются и вправду, советы от капитана.
Это какой-то страшный сон вёб разработчика…
Интересно прочиталось, спасибо.
Чувствуется вся боль.
Долгострой сам по себе морально сложен, а тут еще поддерживают стресс за счет «быстро-быстро, горим».
Со временем, наверное, все приходят к тому, что лучше отказаться от чего-то подобного и потратить время на семью, себя или что-то поинтереснее в профессиональном плане.
Чувствуется вся боль.
Долгострой сам по себе морально сложен, а тут еще поддерживают стресс за счет «быстро-быстро, горим».
Со временем, наверное, все приходят к тому, что лучше отказаться от чего-то подобного и потратить время на семью, себя или что-то поинтереснее в профессиональном плане.
Спасибо за статью. Всегда интересно почитать чужой опыт взаимодействия с заказчиками и проект менеджерами, почитать о том, какой еще бред встречается, сравнить со своим опытом.
Тоже штук 5 подобных проектов (по сложности брал), все слил в свое время, зато получил опыта и знаний немерено.
Тоже штук 5 подобных проектов (по сложности брал), все слил в свое время, зато получил опыта и знаний немерено.
По-хорошему – сделай все на файловых элементах FenomА можете про этот пункт подробнее, пожалуйста?
1. Вводная статья о том, что такое Fenom и зачем оно надо
2. Статья о том, как работать с файловыми элементами
Серьезно, после освоения этого инструмента делать сайты на MODX стало еще проще. И код стал куда красивее. Идиотские однообразные простыни шаблонов с одним отличием сменились на шаблоны с наследованием, все чанки и собственноручно написанные сниппеты/модификаторы хранятся в файлах, их можно использовать с Git, а это вообще просто потрясающе! Теперь никаких утерянных чанков, все всегда можно откатить и радоваться жизни. Прелесть. Если до сих пор никогда не использовали Fenom — потратьте пару дней и познайте дзен реально крутой разработки.
2. Статья о том, как работать с файловыми элементами
Серьезно, после освоения этого инструмента делать сайты на MODX стало еще проще. И код стал куда красивее. Идиотские однообразные простыни шаблонов с одним отличием сменились на шаблоны с наследованием, все чанки и собственноручно написанные сниппеты/модификаторы хранятся в файлах, их можно использовать с Git, а это вообще просто потрясающе! Теперь никаких утерянных чанков, все всегда можно откатить и радоваться жизни. Прелесть. Если до сих пор никогда не использовали Fenom — потратьте пару дней и познайте дзен реально крутой разработки.
А по скорости есть какие-то преимущества, или вопрос только в удобстве?
Ссылки почитайте. Там все написано.
Сравнения со скоростью загрузки из файла и из базы кажется не было. Если не ошибаюсь авторы MODx именно на это упирали, когда заносили все в базу.
Хотя, как я понял, проблема со скоростью и памятью если и может проявиться, то только при первой загрузке, дальше все попадает в кеш и работает также, как и в базовом подходе MODx.
Подход действительно великолепный, жаль, что MODx изначально не по этому пути шел.
Хотя, как я понял, проблема со скоростью и памятью если и может проявиться, то только при первой загрузке, дальше все попадает в кеш и работает также, как и в базовом подходе MODx.
Подход действительно великолепный, жаль, что MODx изначально не по этому пути шел.
Насколько сложно перевести все на Fenom?
Могут ли параллельно уживаться Fenom и обычный подход?
Не знаете, не планируется ли Modx на Fenom перевести?
Могут ли параллельно уживаться Fenom и обычный подход?
Не знаете, не планируется ли Modx на Fenom перевести?
В ссылках написано всё. Всё. Кроме последнего вопроса. Но мне кажется, что нет, не планируется. Если весь мир до сих пор упорно использует getPage, Wayfinder, getResources, о чем может вообще речь идти?
Не знаете, не планируется ли Modx на Fenom перевести?А зачем? Кому нравится феном, ставит pdoTools, кому twig ставит twiggy, кому smarty — modxSmarty.
Из этого абзаца прямо следует, что вам бы не «за жизнь» (заказчики, потраченное время, нервы, эмоции) писать топик, а по теме «Fenom — потратьте пару дней и познайте дзен», «использовать с Git» ))) Напишите, как использовать с Git, как познать дзен. Будет интереснее чем терки за заказчиком (ИМХО).
Думаю, вся статья состояла бы из нескольких слов «Феном позволяет вызывать элементы MODX из файлов, что позволяет контролировать версии элементов при использовании системы версионирования.»
Это прям определение для справочника))) А статья может содержать примеры, сравнения, рассуждения, о «граблях» \фишках\кейсах, мало ли.
Вот достаточно полная статья про файловые элементы. Что можно ещё добавить, да ещё на целую статью?
Тем более тебя интересовал Git
Тем более тебя интересовал Git
Напишите, как использовать с Git, как познать дзен. Будет интереснее чем терки за заказчиком (ИМХО).А это уже к феному никакого отношения не имеет. ))
Да я не о том. Я не просил лично для меня написать.
Перевел на феном и файловые элементы уже не один свой сайт — полет нормальный. Просто по самой статье «Art-revolver или как не стоит делать сайты» предложит автору писать как эти сайты делать надо, применяя феном и т.п. со всеми тонкостями.
Мне казалось именно это могло быть понятно из мой реплики автору топика.
Перевел на феном и файловые элементы уже не один свой сайт — полет нормальный. Просто по самой статье «Art-revolver или как не стоит делать сайты» предложит автору писать как эти сайты делать надо, применяя феном и т.п. со всеми тонкостями.
Мне казалось именно это могло быть понятно из мой реплики автору топика.
И, кстати, да, спасибо тебе и Василию за эти самые файловые элементы! Очень удобно.
Да, помню. Начиналось всё вот так
П.С. В спорах рождается истина.
Функционал загрузки чанков из файлов там был давным-давно, распространение его на остальные элементы — дело времени и спроса. Которого, кстати говоря, не так-то и много.А закончилось так
pdoTools за год серьёзно вырос, научился полноценно работать с файлами, что изменило лично мой подход к созданию сайтов.))
П.С. В спорах рождается истина.
В некоторых случаях, Fenom проигрывает в скорости. Это не панацея.
Согласен, когда руки из жопы, тогда феном проигрывает в скорости. Ни кто и не говорит что это панацея, просто удобная и главное шустрая замена родному парсеру.
Ты мне его уже показывал.
Возможно.
Делюсь. Авось кому-то пригодится. Формит не хватает.
а я думал время когда заказчики говорили микро веб студиям: «сделайте мне новый фэсбук, мы скоро сказочно разбогатеем» прошли эдак годах в 2010 :)
Я тоже когда то думал что смогу сделать один любой сайт. Как же я ошибался. Все приходит с опытом.
да. Гнать в шею такого работодателя. Который ставит сотрудников в столь ужасные условия…
Про цены ничего не понял. Для чего было писать эти ребусы со степенями… Лучшеб сразу написал суммы цифрами. И так текст длинный.
Про цены ничего не понял. Для чего было писать эти ребусы со степенями… Лучшеб сразу написал суммы цифрами. И так текст длинный.
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.