Не надо так делать! Некромантия в программировании до добра не доводит. Тем более есть актуальный Laravel Echo, который совместим с бесплатным websocket сервером Soketi. Вот доки: https://docs.soketi.app/getting-started/client-configuration/laravel-echo. Работают они друг с другом отлично, нужно только разобраться с самим Echo. И никакой некромантии не нужно.
Как по мне, то если на собеседовании загоняют в такие рамки и не дают использовать привычный или хотябы схожий набор инструментов, то возникает вопрос об адекватности собеседующих. Отнимите в ответ у собеседующего бумажку/планшет/ноут по которым они вопросы задают. Пусть почувствуют себя на Вашем месте =)))
Давайте тогда представим что я тот кто оценивает Ваше решение =) У меня возникают следующие вопросы:
Почему использовался контекст? (Ответ уже знаем: чтобы не прокидывать пропсы)
Чем Вас не устраивает прокидывание пропсов в данной задаче? Ведь это было бы проще и понятнее. Да и компонент же довольно простой, а не конструктор типа Dropdown Menu где контент передается извне и нужно иметь возможность взаимодействия с верхним уровнем.
В проекте где есть рейтинг чаще всего будет и избранное, которое идеально ложится на функционал компонента Star, что будете делать?
Почему не используется TypeScript? Он бы почти никак не повлиял на скорость решения задачи, зато была бы типизация хорошо прописана и соблюдена.
Посудите сами - данное тестовое задание дается не только чтобы проверить что Вы можете написать компонент или знаете какие-то особенности технологии/инструмента/языка, но и то как Вы это сделаете, какие возможности и как примените, и как Вы оцениваете ситуацию вне задачи (вопрос 3). Я ничего не имею против контекстов, прекрасная штука, но тащить их только ради того чтобы не прокидывать пропсы - это как-то неэффективно ни по времени ни по результату. Более того контекст обязывает все компоненты его использующие быть зависимыми друг от друга. Уже нельзя будет для вопроса 3 взять готовое решение. Нужно будет переделывать. А это время и деньги. И не нужно говорить что этого небыло в задании. В реальности далеко не всегда заранее известно какой компонент будет переиспользоваться в будущем. Т.е. я как наниматель увидел что Вы смогли решили задачу, но не подумали о том что некоторые компоненты можно будет переиспользовать в будущем. Ведь у компонента Star очень широкое применение. Его и в like можно было бы превратить всего-лишь поменяв иконку. Но увы, придется делать отдельный компонент...
Я, если честно, не понял зачем так сильно усложнять практически всё. Разве что ради того чтобы показать что ты умеешь в контексты. Только если контексты так использовать на каждый чих, то не выльется ли это в проблемы в итоге? Как по мне так в данном случае использование контекста - это misuse. Например компонент Star в каком-то другом месте использовать будет невозможно. Что совсем не круто. Почему не используется TypeScript? И, кстати, самое тормозное никак не оптимизировано - иконка. Представьте страницу на которой очень много звёздочек, а иконка каждой звездочки - отдельный svg элемент с одинаковым path. Это прямо очень тормозное дело, особенно если иконка в каждом блоке со компонентом рейтинга не одна. А ведь далеко не все иконки имеют такой короткий path. Я напоролся на такую проблему и скажу что абсолютно все остальные оптимизации - экономия на спичках. У меня в одном блоке было всего 4 разных иконки (разные, с длинным path), но блоков было много - от сотни до нескольких тысяч. В каждом блоке было от 4 до 12 иконок (чекбоксов могло быть от 1 до 8 в разном виде) Так вот - браузер очень туго переваривал весь этот зоопарк иконок. На довольно мощном компе. Решение: в svg есть возможность клонирования/переиспользования элементов тэгом <use>. Т.е. нужно:
Вынести иконку в отдельный компонент
При первом создании компонента пробрасывать полный svg в <body> или в другое место откуда будет максимально удобный доступ (Пример полного svg: <svg><circle cx="50" cy="50" r="10" fill="red" id="primcirc" /></svg>, обратите внимание на id). Тут особенность в том что нельзя чтобы полный SVG уничтожался при последующих перерисовках, иначе пропадут все иконки-клоны.
При следующих рендерах компонента выводить не полный svg, а <use xlink:href="#primcirc" /> Подробнее гуглите: Cloning SVG Elements: Using use
Вот полный работающий код компонента иконки на основе MDIIcon (Material Design Community Icons):
import * as React from "react";
import {AllHTMLAttributes, CSSProperties, useEffect, useRef} from "react";
let idCounter: number = 0;
let reusableIcons: {
[key: string]: boolean
} = {};
export interface IconProps extends Omit<AllHTMLAttributes<SVGSVGElement>, 'size' | 'label'> {
id?: string,
path: string,
ref?: React.RefObject<SVGSVGElement>,
title?: string,
description?: string | null,
horizontal?: boolean,
vertical?: boolean,
rotate?: number,
spin?: boolean | number,
style?: CSSProperties,
size?: number | null,
reuse?: string, //< icon id to be reused
reusableItemsContainerJquerySelector?: string | 'body'
}
export default function MDIIcon(props: IconProps) {
const {
id,
path,
title,
description,
size,
horizontal,
vertical,
rotate,
spin,
reuse,
reusableItemsContainerJquerySelector,
style: customStyle = {},
...rest
} = props;
const ref = useRef<SVGSVGElement>(null);
useEffect(() => {
if (reuse && ref.current && ref.current.getAttribute('data-use') === '0') {
// copy original svg element to <body> so that it will persist there even after rerender
// on rerender original svg element will be replaced by <svg><use href="#{reuse}"/></svg> and if
// there are no clone inside <body> - all <use> tag will target nothing and icons will not be rerendered
reusableIcons[reuse] = true;
const existing = document.getElementById(reuse);
if (existing) {
window.$(existing).parent().remove();
}
const $container = window.$('<div style="display: none;" class="react-app"></div>')
.append(window.$(ref.current.cloneNode(true) as any).attr('id', reuse));
if (reusableItemsContainerJquerySelector === 'body') {
window.$(document.body).append($container);
} else {
const $supercontainer = window.$(document.body).find(reusableItemsContainerJquerySelector as string);
if ($supercontainer.length !== 0) {
$supercontainer.append($container);
} else {
const message = '[MDIIcon] failed to find element for reusableItemsContainerJquerySelector = ' + reusableItemsContainerJquerySelector;
console.error(message);
window.$(document.body).append($container);
}
}
}
}, [ref.current, reuse])
const index = ++idCounter;
const pathStyle: any = {};
const transform = [];
const style = Object.assign({}, customStyle || {});
if (size !== null) {
style.height = style.width = size + 'px';
}
if (horizontal) {
transform.push("scaleX(-1)");
}
if (vertical) {
transform.push("scaleY(-1)");
}
if (rotate !== 0) {
transform.push(`rotate(${rotate}deg)`);
}
let transformElement = (
<path
d={path}
style={pathStyle}
/>
);
if (transform.length > 0) {
style.transform = transform.join(' ');
style.transformOrigin = 'center';
}
let spinElement = transformElement;
const spinSec = spin || typeof spin !== 'number' ? 2 : spin;
let inverse = horizontal || vertical;
if (spinSec < 0) {
inverse = !inverse
}
if (spin) {
spinElement = (
<g
style={{
animation: `spin${inverse ? '-inverse' : ''} linear ${Math.abs(spinSec)}s infinite`,
transformOrigin: 'center'
}}
>
{transformElement}
{!(horizontal || vertical || rotate !== 0) && (
<rect
width="24"
height="24"
fill="transparent"
/>
)}
</g>
)
}
let ariaLabelledby;
let labelledById = `icon_labelledby_${index}`;
let describedById = `icon_describedby_${index}`;
let role;
if (title) {
ariaLabelledby = description
? `${labelledById} ${describedById}`
: labelledById;
} else {
role = 'presentation';
if (description) {
throw new Error("title attribute required when description is set");
}
}
if (reuse && reusableIcons[reuse]) {
return (
<svg
ref={ref}
viewBox="0 0 24 24"
style={style}
role={role}
aria-labelledby={ariaLabelledby}
data-use="1"
{...rest as any}
>
<use href={'#' + reuse}/>
</svg>
);
} else {
if (reuse) {
reusableIcons[reuse] = true;
}
return (
<svg
ref={ref}
viewBox="0 0 24 24"
style={style}
role={role}
aria-labelledby={ariaLabelledby}
id={id}
data-use="0"
{...rest as any}
>
{title && <title id={labelledById}>{title}</title>}
{description && <desc id={describedById}>{description}</desc>}
{spin && (
inverse
? <style>{"@keyframes spin-inverse { to { transform: rotate(-360deg) } }"}</style>
: <style>{"@keyframes spin { to { transform: rotate(360deg) } }"}</style>
)}
{spinElement}
</svg>
);
}
}
MDIIcon.defaultProps = {
horizontal: false,
vertical: false,
rotate: 0,
spin: false,
size: 24,
style: {},
reusableItemsContainerJquerySelector: 'body'
} as Partial<IconProps>;
Извините за использование jQuery. Проект был на него завязан, а я не настолько ханжа чтобы этим не воспользоваться. Я не претендую на идеальность кода или решения, но это единственный вариант который я нашел и который достаточно хорошо работает имея минимальные недостатки (по сути только лишний код в <body>). Не стоит пользоваться этой функцией везде - оно имеет смысл только если одинаковых иконок очень много (примерно от 50-100 штук на каждую иконку).
Где как раз сложные формы неплохо работают в связки полей и т.п.. в том числе где нет необходимости поддержания реактивого вывода данных с использование асинхронного взаимодействия пользовательских интерфейсов с системой обработки данных.
В моем понимании это как раз и есть сложные формы =) Т.е. форма в которой, например создается родитель и дети, например - опрос с вариантами ответов. Знаю, вариант довольно простой, но бывают даже такие с кучей настроек как у опроса так и у вариантов ответов. Я рассматривал LiveWire как альтернативу, но решил что React меньше будет сервер грузить, да и опыт у меня с ним уже был неплохой. Вообще мне понравилось когда сервер - это просто API, а фронт как бы отдельно от этого всего. Есть в этом что-то правильное.
Использовать фреймворк не имеющий нормальной поддержки и не получившей её за 4 года существования равносильно выстрелу в голову для руководства. Каким бы ни был прогрессивным фреймворк - если его не используют массово, то он никому не нужен. Ну и синтаксис шаблонов - это отдельный трэш. Шаблоны невозможно понять быстро - они почти полностью нечитабельны. Соответственно нужно вникать в каждую строку и расшифровывать бесконечные спецсимволы, даже если их всего несколько. Это контрпродуктивно как для разработки, так и для поддержки. В добавок нет поддержки со стороны IDE что еще больше усугубляет ситуацию. Я оценил фичи, некоторые действительно крутые, но поймите - как бы Вы не пиарили фреймворк, если его разрабатывает пара человек в свободное время без поддержки со стороны бизнеса, то использование такого фреймворка имеет высокие риски остаться с непопулярным фреймворком наедине. И им придется переписывать проект на что-то другое. Высокие риски допустимы для некоторых стартапов, но не для более-менее крупных компаний. И стартапы тоже предпочтут React/Vue/Angular т.к. у всех у них есть много документации, экосистема, сообщество, разработчики, которых можно нанять. Где вы найдете разработчиков знающих или готовых работать со $smal на замену ушедшему? На рынке сейчас итак недостаток качественной рабочей силы, а тут еще и неизвестный малопопулярный фреймворк. Да все качественные кандидаты просто пойдут к конкурентам после того как ознакомятся со $mol и Вашими статьями в стиле "всё вокруг говно, а $mal лучше всех!". Может и лучше, но почему-то никому не нужен...
К сожалению уже нет конкретного примера. Было это год назад и после того как понял что дело так дальше не пойдет, я удалил всё что там было. Если правильно помню, то проблема там была в том что практически все сторонние либы под Vue не дружили с TS, что делало использование TS болью из declare module. Еще какая-то беда была с первоначальной настройкой TS. Глянул сейчас документацию по активации TS - мне кажется это довольно сложным даже сейчас, когда я намного больше знаю про настройку TS и webpack. С реактом всё как-то сильно проще было.
Только вот огромные формы со сложными зависимостями полей друг от друга сильно проще делать как раз на Vue/React, а не на чистом js или js + dotJs, например. И дело не в визуальной части а именно в функциональной.
Я на своем проекте оценил насколько проще, быстрее и функциональнее стали формы после переделывания их на React. Это не повод, конечно, специально переделывать то что есть если оно работает и не требует серьезных изменений. Но новый функционал можно довольно эффективно внедрять в уже существующий проект. Если правильно настроить webpack.
Зайти однозначно проще. Я быстро зашел. Но потом так же быстро вышел т.к. Vue 3 + Typescript почти невозможное сочетание. А без Typescript - зачем вообще так жить? После довольно долгих мучений я таки подружил его с Typescript, а потом напоролся на то что часть сторонних библиотек не обновлена под Vue 3 и полностью с ним несовместима. Мне, например, не улыбается самостоятельно велосипедить Bootstrap компоненты, но пришлось бы если б остался. После прототипирования пары страниц я понял что работая с Vue я превозмогаю его, а не использую с удовольствием. На этом я ушел в React и настроил всё что мне нужно было намного быстрее, с меньшей болью и усилиями. Даже удовольствие получил от того что оно "просто работает". Typescript из коробки доступен, всё прекрасно работает в IDE со всеми возможными подсказками включая стили. Добавить react router, i18n, transition и набор бутстраповских компонентов на выбор - и можно работать. Для react есть практически все возможные либы и многие из них поддерживаются на свежих версиях реакта, т.е. есть вполне живая экосистема. Для vue 3 экосистемы за пределами стандартных либ можно считать что нет. Такое чувство было что многие решили не обновлять либы с Vue 2 на Vue 3 из-за довольно объемных изменений в ядре Vue 3. Единственное что мне прямо очень понравилось во Vue - как красиво и удобно реализовано глобальное состояние. Redux, часто используемый в паре с React - это мозговыносящая переусложненная боль прямо. Может для супер больших online+offline проектов оно и оправдано, но у меня проект довольно средненький и я предпочел Modx - как-то он логичнее и понятнее. Тем не менее лучшее решение из тех что я пробовал именно у Vue. Хотя в общем я согласен с автором что React слишком либерален и для совсем кривых рук не подходит - там нужно понимать что ты делаешь. Те же хуки - это прямо кладезь потенциального технического долга. Но при этом и очень мощный инструмент при правильном использовании.
9ка на мой взгляд ставила основной целью переход на PHP 8.0, добавление типизаций и аннотаций, а так же обновление компонентов symfony которые начали требовать PHP 8.0.
Всё остальное - так, для вида что что-то таки добавили. Хотя вот допиливание страницы ошибки уже как-то надоело, особенно в условиях когда она адски тупит и не работает при ajax запросах. Я давно отказался от нее как раз потому что ждать пока оно отрендерится слишком долго, иногда исправление ошибки занимало меньше времени чем ожидание вывода информации об ошибке. В итоге использую намного более простое решение в виде своего "костыля" (если интересно - swayok/laravel-extended-errors) + отправку в этом же формате себе в Telegram канал =)
Не знаю, Twig не использовал. Но он не нативен для Laravel как минимум. Я уж лучше тогда Vue на фронте прикручу — пользы больше будет. Вариант перехода на Symphony не рассматривается — слишком муторно.
Оно вполне удобное. Смысла его использовать для простых страниц мало, это да. Но чуть что посложнее — либо он, либо уходить полностью во frontend (vue, react, angular и т.п). Кому что удобнее. Делать свои костыли — не вижу смысла, это бесполезная трата времени (у меня есть несколько таких костылей и этого более чем достаточно чтобы трезво оценивать необходимость новых). Прикручивать к Laravel чужие костыли — а зачем? Есть Blade, он работает достаточно хорошо, но хромает поддержка в IDE.
Понимаю что сложно, но надо как-то решать, ато вот вообще больно стало этим всем пользоваться.
Может на основе настроек Blade директив из настроек IDE конвертировать код в чистый html c php вставками и уже анализировать его?
Это так же позволит настройками Blade директив внедрять специальные переменные типа $loop в итераторы @for, @foreach и т.п. Пример настройки Suffix для each директивы: ); /** @var \stdClass $loop */ ?>
А теперь ложку дегтя:
Когда завезут нормальную поддержку Blade шаблонов? Этот вопрос висит уже много лет и нет никакого развития в эту сторону. Скорее наоборот — с каждой версией IDE становится всё хуже. Самая боль — подсказка имен переменных работает только в редких случаях. Например, если в шаблоне через phpdoc указать входящие переменные, то в Blade директивах нет подсказки имен к ним, но после того как полностью введено имя переменной, IDE его кое-как сопоставляет с тем что определено в PHPdoc (через Ctrl видно тип и даже начинает работать подсказка свойств объекта если переменная — объект), но как бы это уже не особо полезно. Аналогичная проблема с блоками @php и <?php ?> — они вообще живут в разных областях видимости даже относительно остальных Blade директив. Хотелось бы чтобы поддержка Blade шаблонов была более адекватной, чтобы не приходилось варить кашу из костылей типа такого:
Определенную в PHPdoc переменную $array не видно в Blade директивах, соответственно никаких подсказок имени в @foreach или в других блоках
В блоке @php() не видно переменную $value настолько что IDE выдает там ошибку 'Undefined variable $value' если не прописать /** var array $value */
В блоке @php() при прописанном /** var array $value */ ошибки нет, но есть предупреждение 'Expresion result is not used anywhere' хотя на следующей строке переменная используется
в строке {{ $varname }} IDE не знает о переменной $varname, т.е. и тут нет подсказки имени
в строке <?php echo ?> IDE видит $array, но $value и $varname подсвечивает с ошибками 'Undefined variable $value' и 'Undefined variable $varname'
Как видите — пользоваться такой реализацией совершенно не удобно. Это сплошная борьба с IDE вместо того чтобы заниматься чем-то полезным. В целом эффективность написания Blade шаблона в блокноте не сильно ниже чем в PHPStorm. Надеюсь Вас это заденет.
На все эти косяки есть Issue в багтрекере, которые игнорируются годами. Ну тут ничего нового — в JetBrains это уже стало традицией =( Как и то что я к каждому релизу на что-то жалуюсь на Хабре =)
Далекие времена PostgreSQL 9.1. Я тогда настройки делал по инструкциям. Магии как с настройками MySQL не припомню. Тем не менее около 2х лет проект работал без нареканий на БД. Что было после — не знаю.
Сейчас настройкой занимается специально обученный человек, так что не совсем в курсе насколько всё изменилось.
Мне казалось наибольшей сложностью перехода с MySQL на PostgreSQL для большинства было незнание стандартного SQL и привычка использовать нестандартные фишки MySQL. В добавок более строгая типизация не позволяла делать всякую фигню как в MySQL без явного приведения типов. А еще в PG foreign key уже тогда нормально работали в отличие от MySQL. Это как из песочницы вылезти в реальный мир.
А еще в PG нет вечного выбора между MyISAM и InnoDB.
Для меня наоборот после перехода на PG всё встало на свои места т.к. в универе был весьма толковый курс по стандартному SQL.
Как я Вас понимаю =) Я лет 10 назад после очередного марафона по оптимизации настроек и запросов в MySQL обнаружил что это недоразумение отказывается использовать выделенные ему 16 гигов оперативки и использует HDD (скажем спасибо TEXT типу колонок). В итоге психанул и перевел проект на PostgreSQL с минимальными изменениями в структуре и типах полей. В итоге мало того что все проблемы с нагрузкой испарились, так я еще и не настраивал в PG ничего кроме разрешенного объема памяти. Тогда еще были проблемы с производительностью COUNT(*), но проект все-равно работал намного быстрее чем MySQL. А потом я начал вспоминать универ и стандарт SQL со всеми его возможностями, которыми в MySQL и не пахло. В общем с того момента я зарекся использовать MySQL в проектах более чем сайт-каталог с небольшим количеством данных.
На сколько я понял — проблема с непопулярностью PostgreSQL в те времена была в основном потому что мало кто знал о нем и мало кто был способен адекватно использовать его возможности. Я вот, например, кайфовал от количества типов колонок и строгости типизации данных в сравнении с MySQL. А многие считают это проблемой или не понимают как это правильно использовать.
А еще больше меня удивляет скудность поддержки PostgreSQL в фреймворках и ORM даже сейчас.
Не надо так делать! Некромантия в программировании до добра не доводит. Тем более есть актуальный Laravel Echo, который совместим с бесплатным websocket сервером Soketi. Вот доки: https://docs.soketi.app/getting-started/client-configuration/laravel-echo. Работают они друг с другом отлично, нужно только разобраться с самим Echo. И никакой некромантии не нужно.
Мне лень статьи писать =) Я даже комментирую редко.
Как по мне, то если на собеседовании загоняют в такие рамки и не дают использовать привычный или хотябы схожий набор инструментов, то возникает вопрос об адекватности собеседующих. Отнимите в ответ у собеседующего бумажку/планшет/ноут по которым они вопросы задают. Пусть почувствуют себя на Вашем месте =)))
Давайте тогда представим что я тот кто оценивает Ваше решение =)
У меня возникают следующие вопросы:
Почему использовался контекст? (Ответ уже знаем: чтобы не прокидывать пропсы)
Чем Вас не устраивает прокидывание пропсов в данной задаче? Ведь это было бы проще и понятнее. Да и компонент же довольно простой, а не конструктор типа Dropdown Menu где контент передается извне и нужно иметь возможность взаимодействия с верхним уровнем.
В проекте где есть рейтинг чаще всего будет и избранное, которое идеально ложится на функционал компонента Star, что будете делать?
Почему не используется TypeScript? Он бы почти никак не повлиял на скорость решения задачи, зато была бы типизация хорошо прописана и соблюдена.
Посудите сами - данное тестовое задание дается не только чтобы проверить что Вы можете написать компонент или знаете какие-то особенности технологии/инструмента/языка, но и то как Вы это сделаете, какие возможности и как примените, и как Вы оцениваете ситуацию вне задачи (вопрос 3).
Я ничего не имею против контекстов, прекрасная штука, но тащить их только ради того чтобы не прокидывать пропсы - это как-то неэффективно ни по времени ни по результату. Более того контекст обязывает все компоненты его использующие быть зависимыми друг от друга. Уже нельзя будет для вопроса 3 взять готовое решение. Нужно будет переделывать. А это время и деньги. И не нужно говорить что этого небыло в задании. В реальности далеко не всегда заранее известно какой компонент будет переиспользоваться в будущем. Т.е. я как наниматель увидел что Вы смогли решили задачу, но не подумали о том что некоторые компоненты можно будет переиспользовать в будущем. Ведь у компонента Star очень широкое применение. Его и в like можно было бы превратить всего-лишь поменяв иконку. Но увы, придется делать отдельный компонент...
Я, если честно, не понял зачем так сильно усложнять практически всё. Разве что ради того чтобы показать что ты умеешь в контексты. Только если контексты так использовать на каждый чих, то не выльется ли это в проблемы в итоге? Как по мне так в данном случае использование контекста - это misuse. Например компонент Star в каком-то другом месте использовать будет невозможно. Что совсем не круто.
Почему не используется TypeScript?
И, кстати, самое тормозное никак не оптимизировано - иконка. Представьте страницу на которой очень много звёздочек, а иконка каждой звездочки - отдельный svg элемент с одинаковым path. Это прямо очень тормозное дело, особенно если иконка в каждом блоке со компонентом рейтинга не одна. А ведь далеко не все иконки имеют такой короткий path. Я напоролся на такую проблему и скажу что абсолютно все остальные оптимизации - экономия на спичках. У меня в одном блоке было всего 4 разных иконки (разные, с длинным path), но блоков было много - от сотни до нескольких тысяч. В каждом блоке было от 4 до 12 иконок (чекбоксов могло быть от 1 до 8 в разном виде) Так вот - браузер очень туго переваривал весь этот зоопарк иконок. На довольно мощном компе.
Решение: в svg есть возможность клонирования/переиспользования элементов тэгом
<use>
.Т.е. нужно:
Вынести иконку в отдельный компонент
При первом создании компонента пробрасывать полный svg в
<body>
или в другое место откуда будет максимально удобный доступ (Пример полного svg:<svg><circle cx="50" cy="50" r="10" fill="red" id="primcirc" /></svg>
, обратите внимание наid
). Тут особенность в том что нельзя чтобы полный SVG уничтожался при последующих перерисовках, иначе пропадут все иконки-клоны.При следующих рендерах компонента выводить не полный svg, а
<use xlink:href="#primcirc" />
Подробнее гуглите: Cloning SVG Elements: Using useВот полный работающий код компонента иконки на основе
MDIIcon
(Material Design Community Icons):Извините за использование jQuery. Проект был на него завязан, а я не настолько ханжа чтобы этим не воспользоваться.
Я не претендую на идеальность кода или решения, но это единственный вариант который я нашел и который достаточно хорошо работает имея минимальные недостатки (по сути только лишний код в
<body>
). Не стоит пользоваться этой функцией везде - оно имеет смысл только если одинаковых иконок очень много (примерно от 50-100 штук на каждую иконку).В моем понимании это как раз и есть сложные формы =) Т.е. форма в которой, например создается родитель и дети, например - опрос с вариантами ответов. Знаю, вариант довольно простой, но бывают даже такие с кучей настроек как у опроса так и у вариантов ответов. Я рассматривал LiveWire как альтернативу, но решил что React меньше будет сервер грузить, да и опыт у меня с ним уже был неплохой. Вообще мне понравилось когда сервер - это просто API, а фронт как бы отдельно от этого всего. Есть в этом что-то правильное.
Использовать фреймворк не имеющий нормальной поддержки и не получившей её за 4 года существования равносильно выстрелу в голову для руководства. Каким бы ни был прогрессивным фреймворк - если его не используют массово, то он никому не нужен. Ну и синтаксис шаблонов - это отдельный трэш. Шаблоны невозможно понять быстро - они почти полностью нечитабельны. Соответственно нужно вникать в каждую строку и расшифровывать бесконечные спецсимволы, даже если их всего несколько. Это контрпродуктивно как для разработки, так и для поддержки. В добавок нет поддержки со стороны IDE что еще больше усугубляет ситуацию. Я оценил фичи, некоторые действительно крутые, но поймите - как бы Вы не пиарили фреймворк, если его разрабатывает пара человек в свободное время без поддержки со стороны бизнеса, то использование такого фреймворка имеет высокие риски остаться с непопулярным фреймворком наедине. И им придется переписывать проект на что-то другое. Высокие риски допустимы для некоторых стартапов, но не для более-менее крупных компаний. И стартапы тоже предпочтут React/Vue/Angular т.к. у всех у них есть много документации, экосистема, сообщество, разработчики, которых можно нанять. Где вы найдете разработчиков знающих или готовых работать со $smal на замену ушедшему? На рынке сейчас итак недостаток качественной рабочей силы, а тут еще и неизвестный малопопулярный фреймворк. Да все качественные кандидаты просто пойдут к конкурентам после того как ознакомятся со $mol и Вашими статьями в стиле "всё вокруг говно, а $mal лучше всех!". Может и лучше, но почему-то никому не нужен...
Вот скорее всего допилили поддержку. Я не помню конструкций вида `lang="ts" ` и `script setup`.
К сожалению уже нет конкретного примера. Было это год назад и после того как понял что дело так дальше не пойдет, я удалил всё что там было. Если правильно помню, то проблема там была в том что практически все сторонние либы под Vue не дружили с TS, что делало использование TS болью из declare module. Еще какая-то беда была с первоначальной настройкой TS. Глянул сейчас документацию по активации TS - мне кажется это довольно сложным даже сейчас, когда я намного больше знаю про настройку TS и webpack. С реактом всё как-то сильно проще было.
Только вот огромные формы со сложными зависимостями полей друг от друга сильно проще делать как раз на Vue/React, а не на чистом js или js + dotJs, например. И дело не в визуальной части а именно в функциональной.
Я на своем проекте оценил насколько проще, быстрее и функциональнее стали формы после переделывания их на React. Это не повод, конечно, специально переделывать то что есть если оно работает и не требует серьезных изменений. Но новый функционал можно довольно эффективно внедрять в уже существующий проект. Если правильно настроить webpack.
Зайти однозначно проще. Я быстро зашел. Но потом так же быстро вышел т.к. Vue 3 + Typescript почти невозможное сочетание. А без Typescript - зачем вообще так жить? После довольно долгих мучений я таки подружил его с Typescript, а потом напоролся на то что часть сторонних библиотек не обновлена под Vue 3 и полностью с ним несовместима. Мне, например, не улыбается самостоятельно велосипедить Bootstrap компоненты, но пришлось бы если б остался. После прототипирования пары страниц я понял что работая с Vue я превозмогаю его, а не использую с удовольствием. На этом я ушел в React и настроил всё что мне нужно было намного быстрее, с меньшей болью и усилиями. Даже удовольствие получил от того что оно "просто работает". Typescript из коробки доступен, всё прекрасно работает в IDE со всеми возможными подсказками включая стили. Добавить react router, i18n, transition и набор бутстраповских компонентов на выбор - и можно работать. Для react есть практически все возможные либы и многие из них поддерживаются на свежих версиях реакта, т.е. есть вполне живая экосистема. Для vue 3 экосистемы за пределами стандартных либ можно считать что нет. Такое чувство было что многие решили не обновлять либы с Vue 2 на Vue 3 из-за довольно объемных изменений в ядре Vue 3. Единственное что мне прямо очень понравилось во Vue - как красиво и удобно реализовано глобальное состояние. Redux, часто используемый в паре с React - это мозговыносящая переусложненная боль прямо. Может для супер больших online+offline проектов оно и оправдано, но у меня проект довольно средненький и я предпочел Modx - как-то он логичнее и понятнее. Тем не менее лучшее решение из тех что я пробовал именно у Vue. Хотя в общем я согласен с автором что React слишком либерален и для совсем кривых рук не подходит - там нужно понимать что ты делаешь. Те же хуки - это прямо кладезь потенциального технического долга. Но при этом и очень мощный инструмент при правильном использовании.
9ка на мой взгляд ставила основной целью переход на PHP 8.0, добавление типизаций и аннотаций, а так же обновление компонентов symfony которые начали требовать PHP 8.0.
Всё остальное - так, для вида что что-то таки добавили. Хотя вот допиливание страницы ошибки уже как-то надоело, особенно в условиях когда она адски тупит и не работает при ajax запросах. Я давно отказался от нее как раз потому что ждать пока оно отрендерится слишком долго, иногда исправление ошибки занимало меньше времени чем ожидание вывода информации об ошибке. В итоге использую намного более простое решение в виде своего "костыля" (если интересно - swayok/laravel-extended-errors) + отправку в этом же формате себе в Telegram канал =)
Эта магия настолько черна что даже "неназываемый" ею брезгует =)))
Не знаю, Twig не использовал. Но он не нативен для Laravel как минимум. Я уж лучше тогда Vue на фронте прикручу — пользы больше будет. Вариант перехода на Symphony не рассматривается — слишком муторно.
Да вот, похоже, пора. Когда-то давно я хотел дождаться большей функциональности и в итоге забыл о нем =)
Оно вполне удобное. Смысла его использовать для простых страниц мало, это да. Но чуть что посложнее — либо он, либо уходить полностью во frontend (vue, react, angular и т.п). Кому что удобнее. Делать свои костыли — не вижу смысла, это бесполезная трата времени (у меня есть несколько таких костылей и этого более чем достаточно чтобы трезво оценивать необходимость новых). Прикручивать к Laravel чужие костыли — а зачем? Есть Blade, он работает достаточно хорошо, но хромает поддержка в IDE.
Понимаю что сложно, но надо как-то решать, ато вот вообще больно стало этим всем пользоваться.
Может на основе настроек Blade директив из настроек IDE конвертировать код в чистый html c php вставками и уже анализировать его?
Это так же позволит настройками Blade директив внедрять специальные переменные типа
$loop
в итераторы@for
,@foreach
и т.п. Пример настройки Suffix для each директивы:); /** @var \stdClass $loop */ ?>
Довольно толковый релиз получился. Молодцы.
А теперь ложку дегтя:
Когда завезут нормальную поддержку Blade шаблонов? Этот вопрос висит уже много лет и нет никакого развития в эту сторону. Скорее наоборот — с каждой версией IDE становится всё хуже. Самая боль — подсказка имен переменных работает только в редких случаях. Например, если в шаблоне через phpdoc указать входящие переменные, то в Blade директивах нет подсказки имен к ним, но после того как полностью введено имя переменной, IDE его кое-как сопоставляет с тем что определено в PHPdoc (через Ctrl видно тип и даже начинает работать подсказка свойств объекта если переменная — объект), но как бы это уже не особо полезно. Аналогичная проблема с блоками
@php
и<?php ?>
— они вообще живут в разных областях видимости даже относительно остальных Blade директив. Хотелось бы чтобы поддержка Blade шаблонов была более адекватной, чтобы не приходилось варить кашу из костылей типа такого:Тут проблема чуть ли не в каждой строке:
$array
не видно в Blade директивах, соответственно никаких подсказок имени в@foreach
или в других блоках@php()
не видно переменную$value
настолько что IDE выдает там ошибку 'Undefined variable $value' если не прописать/** var array $value */
@php()
при прописанном/** var array $value */
ошибки нет, но есть предупреждение 'Expresion result is not used anywhere' хотя на следующей строке переменная используется{{ $varname }}
IDE не знает о переменной$varname
, т.е. и тут нет подсказки имени<?php echo ?>
IDE видит$array
, но$value
и$varname
подсвечивает с ошибками 'Undefined variable $value' и 'Undefined variable $varname'Как видите — пользоваться такой реализацией совершенно не удобно. Это сплошная борьба с IDE вместо того чтобы заниматься чем-то полезным. В целом эффективность написания Blade шаблона в блокноте не сильно ниже чем в PHPStorm. Надеюсь Вас это заденет.
На все эти косяки есть Issue в багтрекере, которые игнорируются годами. Ну тут ничего нового — в JetBrains это уже стало традицией =( Как и то что я к каждому релизу на что-то жалуюсь на Хабре =)
Далекие времена PostgreSQL 9.1. Я тогда настройки делал по инструкциям. Магии как с настройками MySQL не припомню. Тем не менее около 2х лет проект работал без нареканий на БД. Что было после — не знаю.
Сейчас настройкой занимается специально обученный человек, так что не совсем в курсе насколько всё изменилось.
Мне казалось наибольшей сложностью перехода с MySQL на PostgreSQL для большинства было незнание стандартного SQL и привычка использовать нестандартные фишки MySQL. В добавок более строгая типизация не позволяла делать всякую фигню как в MySQL без явного приведения типов. А еще в PG foreign key уже тогда нормально работали в отличие от MySQL. Это как из песочницы вылезти в реальный мир.
А еще в PG нет вечного выбора между MyISAM и InnoDB.
Для меня наоборот после перехода на PG всё встало на свои места т.к. в универе был весьма толковый курс по стандартному SQL.
Как я Вас понимаю =) Я лет 10 назад после очередного марафона по оптимизации настроек и запросов в MySQL обнаружил что это недоразумение отказывается использовать выделенные ему 16 гигов оперативки и использует HDD (скажем спасибо TEXT типу колонок). В итоге психанул и перевел проект на PostgreSQL с минимальными изменениями в структуре и типах полей. В итоге мало того что все проблемы с нагрузкой испарились, так я еще и не настраивал в PG ничего кроме разрешенного объема памяти. Тогда еще были проблемы с производительностью COUNT(*), но проект все-равно работал намного быстрее чем MySQL. А потом я начал вспоминать универ и стандарт SQL со всеми его возможностями, которыми в MySQL и не пахло. В общем с того момента я зарекся использовать MySQL в проектах более чем сайт-каталог с небольшим количеством данных.
На сколько я понял — проблема с непопулярностью PostgreSQL в те времена была в основном потому что мало кто знал о нем и мало кто был способен адекватно использовать его возможности. Я вот, например, кайфовал от количества типов колонок и строгости типизации данных в сравнении с MySQL. А многие считают это проблемой или не понимают как это правильно использовать.
А еще больше меня удивляет скудность поддержки PostgreSQL в фреймворках и ORM даже сейчас.