Обновить
64K+

PHP *

Скриптовый язык общего назначения

76,15
Рейтинг
Сначала показывать
Порог рейтинга
Уровень сложности

Когда разработчики ленятся писать документацию: описываем клиентский API силами нейросетей

Уровень сложностиСредний
Время на прочтение19 мин
Охват и читатели2.1K

Документация устаревает быстрее, чем код успевает писаться? Рассказываем, как мы построили конвейер из Python-скриптов и нейросетей, который сам находит изменения в PHP-контроллерах и обновляет документацию API Invapi.

Читать далее

Новости

Четыре CMS, один интерфейс публикации: WordPress, 1С-Битрикс, InSales и Joomla

Уровень сложностиСредний
Время на прочтение10 мин
Охват и читатели4.6K

Полгода назад я делал сервис, который генерирует статьи и сам кладёт их на сайт. Написать текст казалось сложной частью, а публикация — формальностью: ну дёрнем REST API, что там может быть.

Оказалось наоборот. Четыре CMS — четыре разных мира, и в каждом свой способ соврать вам об успехе.

Joomla возвращает 400, когда статья уже создана: плагин «Умный поиск» падает после записи в базу. Повторили запрос — получили дубль. InSales требует published_at даже у черновика, потому что черновиков там просто нет. А у 1С-Битрикс метода для создания статьи через API не существует вовсе — официальная документация прямо говорит про read-only режим.

Внутри: как выглядит общий интерфейс на четыре системы, почему CIBlockElement::Add() возвращает ошибку при успешно созданном элементе, зачем понадобилась двойная буферизация вывода и прямой SQL в обход автотранслитерации.

Читать далее!

Матрешка из Base64 и ROT13: разбираем вредоносный .sh, который пришел за FreePBX

Уровень сложностиПростой
Время на прочтение8 мин
Охват и читатели4.9K

Мне в руки попался файл с расширением .sh и, конечно же, его пришлось изучить. Открываю файл — первая половина более-менее читаемая, а дальше начинается классика: Base64, ROT13 и еще немного Base64. Вроде ничего страшного. Декодируем, смотрим результат, радуемся жизни. Но не тут-то было. Автор скрипта решил сделать небольшой квест в стиле: А что если положить один скрипт внутрь другого скрипта, а потом еще один внутрь него?

Читать далее

Когда Laravel Validator становится узким местом при импорте 50 000 строк

Уровень сложностиПростой
Время на прочтение8 мин
Охват и читатели6K

PHP 7.4 / Laravel 8 / PostgreSQL 13

Проблема: импорт 50 тысяч строк занимал около 45 секунд.
Первое подозрение: база данных, INSERT, UPSERT, индексы, размер batch и количество запросов.
Реальность: бОльшая часть времени уходит на валидацию.

Мы начали разбираться, почему проверка нескольких десятков обычных полей на большом массиве данных оказалась значительно дороже самой записи в PostgreSQL. В итоге удалось сократить время валидации с 42,5 секунды до 0,65 секунды, а длительность всего job — примерно с 45 до 4 секунд.

В статье покажу, что именно оказалось узким местом, почему стандартный Laravel Validator оказался не самым подходящим инструментом для этого конкретного сценария и почему мы не стали от него отказываться.

Читать далее

Как на ровном месте сэкономить 1000+ ядер, или Куда на самом деле уходили 80% CPU

Уровень сложностиСредний
Время на прочтение18 мин
Охват и читатели12K

Всем привет, меня зовут Миша, и я бэкенд‑разработчик в платформе Яндекс Еды. Я уже рассказывал, как мы анализировали наш PHP‑монолит и вынесли из него процессинг заказов, и с тех пор роль этого легаси заметно уменьшилась. Заодно туда стали писать гораздо меньше нового кода, релизы стали реже, и он спокойненько себе работал, не привлекая лишнего внимания. 

Так оно бы и продолжалось, но тут случилась повышенная нагрузка и необходимость зарезервировать побольше мощностей для беспроблемной обработки повышенного спроса. Монолит справился на отлично, но самое интересное случилось потом: возвращая выделение ресурсов к прежним значениям, я случайно обратил внимание, что RPS в пиковые вечерние часы как‑то подозрительно совпадает с количеством ядер CPU, выделенных на весь монолит.

Количество выделенных ядер, конечно, ещё ничего не означает, поэтому я полез смотреть реальное потребление процессорного времени, сложив CPU usage по всем подам. С помощью нехитрой арифметики я обнаружил, что 100% загрузки одного ядра приходятся на 2,5 RPS. Какое‑то время я находился в состоянии глубокого изумления, после чего решил, что это никуда не годится, и отправился в увлекательное приключение на 20 минут. 

Немного спойлеров: дело оказалось далеко не только в PHP. 

Читать далее

Пользователь придумал пароль из 100 символов. От 28 из них ваша проверка не зависит

Уровень сложностиСредний
Время на прочтение6 мин
Охват и читатели13K

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

Ломалось не у него. Так работает bcrypt, и работает уже двадцать семь лет.

Читать далее

Как записать ЛИД в Битрикс24 (заявка с сайта и подобное) через входящий вебхук на PHP

Уровень сложностиСредний
Время на прочтение7 мин
Охват и читатели6.6K

Для простой серверной интеграции с Битрикс24 далеко не всегда требуется полноценная OAuth 2.0-авторизация.

Если задача — из внешнего сервиса создать контакт, проверить существующего клиента и записать лид в CRM, это можно сделать через входящий вебхук Битрикс24 и обычный PHP.

Я использую такую схему в интеграциях, когда внешняя система отправляет данные на наш сервер, а сервер уже решает, что именно нужно создать в CRM.

Читать далее

Пакуем PHP в PHP, чтобы запаковать в JS, чтобы обернуть в HTML

Время на прочтение3 мин
Охват и читатели7K

Прочтя недавний перевод про запаковку БД в exe, решил рассказать об идеи, которую реализовал лет 6 назад в своем домашнем проекте. Сам проект недоделал, но речь в статье об архитектуре файлов и их запаковке.

Читать далее

Как я год загружал фото в Битрикс24 и собрал все грабли файлового API

Уровень сложностиСложный
Время на прочтение12 мин
Охват и читатели8.6K

Работа с файлами в REST API Битрикс24 — та задача, где документация заканчивается ровно там, где начинаются проблемы. Официальные примеры показывают, как загрузить один файл в одно поле. А дальше выясняется, что у crm.item.update и crm.deal.update разные несовместимые форматы, что вложенный base64 через http_build_query уходит в никуда, а сервер при этом честно отвечает «result».

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

Собрал всё в один разбор — шесть подходов с кодом и восемь граблей:

два формата файлового значения, которые нельзя смешивать, и почему при смешении затираются уже прикреплённые файлы;

тихий провал: HTTP 200, в ответе result, поле не обновилось;

useOriginalUfNames=Y, без которого UF_CRM_* молча игнорируются;

downloadUrl приходит с пустым auth= и без подстановки токена не скачивается, а при протухшем токене вместо файла отдаётся HTML-страница с кодом 200;

у одного изображения бывает несколько URL, и часть из них не работает — пришлось делать скоринг вариантов по эвристике.

В конце — таблица «что брать под какую задачу» и чеклист граблей. Двадцать блоков кода, всё из боевых проектов.

Читать далее

Автогенерация типов показала, что проблема была не в типах

Уровень сложностиСредний
Время на прочтение10 мин
Охват и читатели6.8K

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

Статья не про саму автогенерацию — с ней всё понятно, про неё и без меня написано достаточно. Мы внедрили генерацию типов из OpenAPI, и она вытащила наружу то, что с генерацией напрямую не связано: кто не хочет писать комментарии, почему у одной сущности два имени и почему у нас падал dev. По сути — про команду, эго и умение договариваться.

Сразу оговорюсь: это не единственно верный путь. Команды и компании разные, у всех свои нюансы, я рассказываю, как было у нас. Но если автогенерации у вас ещё нет и вы соберётесь её внедрять — будете хотя бы знать, что вас ждёт.

Читать далее

Публичный API у генератора QR-кодов: без ключей, лимитер на файлах и грабля Apache

Уровень сложностиСредний
Время на прочтение4 мин
Охват и читатели5.6K

У моего генератора QR-кодов листами появился публичный API: POST с JSON, в ответ сразу готовый PDF, до 1500 кодов за запрос, без регистрации и ключей. Внутри рассказ, почему я не завел ни ключи, ни Redis, как работает лимитер на файлах с flock и fail-open, и на какой грабле Apache POST молча превращался в GET.

Читать далее

Пишем свой PHP-экстеншен на Rust

Уровень сложностиСредний
Время на прочтение12 мин
Охват и читатели6.1K

Когда речь заходит о разработке PHP-расширений, многие сразу представляют C, Zend API и сложную систему сборки. Но сегодня есть более удобный путь. С помощью ext-php-rs можно создавать расширения на Rust, используя привычные инструменты Cargo и практически не сталкиваясь с низкоуровневыми деталями.

В этой статье мы с нуля напишем собственный PHP-экстеншен, подключим его к PHP, разберём, как ext-php-rs связывает Rust с Zend API, а затем посмотрим, в каких задачах такой подход действительно даёт прирост производительности, а где этого ждать не стоит.

Читать далее

Автоматическая установка Wordpress на чистый сервер Ubuntu или Debian

Уровень сложностиПростой
Время на прочтение8 мин
Охват и читатели5.2K

Ставить WordPress руками — занятие на полтора часа: веб‑сервер, PHP с десятком расширений, база данных, конфиг Nginx, права на файлы, лимиты загрузки, сертификат. Я устал повторять этот ритуал и собрал скрипт, который делает всё сам и спрашивает только то, что действительно зависит от меня.

Итог, к которому мы придём: работающий сайт с настроенной админкой, ЧПУ‑ссылками, русской локализацией, при желании — с сертификатом Let’s Encrypt, phpMyAdmin и защитой от подбора паролей. Все доступы будут лежать в одном файле на сервере.

Читать далее

Ближайшие события

OAuth 2.0 в amoCRM REST API на PHP простым языком: получение, хранение и обновление токенов

Уровень сложностиСредний
Время на прочтение6 мин
Охват и читатели5.5K

Когда впервые пишешь собственную интеграцию с amoCRM через REST API, сами запросы к сделкам, контактам или компаниям обычно оказываются не самой сложной частью.

Основной вопрос возникает раньше:

как один раз авторизовать интеграцию, а затем поддерживать доступ к amoCRM без постоянного ручного получения ключей?

1-2 года назад я реализовывал такую интеграцию на PHP. Токены хранили в MySQL, а работу с OAuth разбили на несколько отдельных файлов.

Сейчас решил восстановить общую архитектуру этой реализации.

Если убрать детали, OAuth-интеграция выглядит довольно просто:

Authorization Code → Access Token + Refresh Token → сохранение в БД → запросы к REST API → обновление токенов → повторное сохранение в БД.

Код авторизации берется в AmoCRM:

Читать далее

100% покрытия не поймали единственный баг, который был важен

Уровень сложностиСредний
Время на прочтение6 мин
Охват и читатели7.2K

У виджета было 92 теста и 100% построчного покрытия. Потом я открыл его в маленьком окне терминала, и шапка таблицы уехала за верхнюю границу экрана.

Разбор трёх багов, которые нашлись при разработке пакета поверх экспериментального компонента symfony/tui: одного своего, который не поймало полное покрытие, и двух чужих — их исправления смержены в ядро Symfony. Плюс третий, найденный уже после того, как его починили без меня, — таб в ячейке ломал выравнивание всей таблицы.

Про то, почему покрытие считает выполненные строки и ничего не говорит о предположениях, которые вы ни разу не поставили под сомнение.

Читать далее

Как сайт клиента захватил японский магазин дронов и как мы это исправили

Уровень сложностиСредний
Время на прочтение10 мин
Охват и читатели7K

Суббота, клиент вернулся из отпуска, открыл свой сайт и написал мне: «сайт лежит, вижу только белый экран, что случилось?». Код ответа при этом 200, мониторинг зелёный, хостинг жив, база данных на месте.

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

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

А ещё честно расскажу, где мы сами ошиблись. Одна ошибка стоила ещё десяти часов спама в Google уже после того, как мы решили, что всё закончилось.

В конце — 5 способов за 5 минут проверить ваш собственный сайт.

Читать далее

Как мы разработали свой сервис бронирования и победили гонки за слоты

Уровень сложностиПростой
Время на прочтение7 мин
Охват и читатели4.9K

Привет, Хабр!

Меня зовут Михаил Емельянов, я ведущий разработчик в НЛМК ИТ. Команда, в которой я состою, занимается разработкой и поддержкой различных корпоративных информационных систем на базе Битрикс24.

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

- Юридические нюансы: обработка персональных данных по требованиям 152‑ФЗ и внутренних политик безопасности. Стороннему сервису не всегда можно передать всё, что нужно, а иногда это прямо запрещено.

- Стоимость: даже одно недельное мероприятие обходилось достаточно дорого.

- Процессные ограничения: неудобно быстро менять расписание «на лету» во время мероприятия, неидеальная логика резервирования времени приводила к редким, но болезненным коллизиям.

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

Читать далее

Генератор QR‑кодов листами на PHP: детерминированное ядро и пять граблей по дороге

Уровень сложностиСредний
Время на прочтение7 мин
Охват и читатели6.6K

Этой весной мне понадобился лист QR‑кодов с подписями: по коду на каждую позицию, чтобы скачать PDF, распечатать и разрезать. Онлайн‑генераторы делают коды по одному или просят подписку за пакет, так что я написал свой сервис на PHP 8.2. В посте про то, что интереснее разработчику: чистое детерминированное ядро с golden‑тестами байт‑в-байт, кириллические домены и punycode, кириллица, которую TCPDF молча теряет в SVG, артикулы в виде 4.6E+12 из Excel, “прозрачный” PNG с маджентовым фоном и самописный EAN-13 с оракулом в тестах.

Читать далее

Современный API Reference в Symfony через Scalar

Уровень сложностиПростой
Время на прочтение6 мин
Охват и читатели7.9K

Работая с PHP, испытываешь постоянную необходимость поддерживать документацию в актуальном состоянии. В последнее время PHP проекты — это API‑first, когда бек на PHP, а фронт собирается отдельно.

Тут у нас два пути:

— Spec‑first, то есть сначала готовится спецификация всех возможных маршрутов с входными/выходными параметрами, ошибками и пр. Часто это YAML‑файл OpenAPI.

— OpenAPI файл генерируется на основе атрибутов и аннотаций в коде.

В первом случае мы делаем то, что прописано в спецификации и имеем возможность сравнить, верно ли у нас всё сделано. Во втором случае у нас всегда актуальная схема (после автоматического обновления).

Хотелось бы легкий, современный UI для отрисовки готового OpenAPI yaml файла для первого типа работы с документацией API.
И, кажется, Scalar для этого отлично подходит, но вот интеграции из коробки у Symfony со Scalar нет. В одном своём проекте у меня подход OpenAPI‑first, то есть сначала спецификация, потом реализация. Мощный NelmioApiDocBundle тянуть в проект не хотелось.

Выбор пал на Scalar. Но одно плохо, нет интеграции. Можно было просто интегрировать своими силами в проекте, но понял, что можно оформить это в виде bundle и в дальнейшем переиспользовать в других проектах.

Читать далее

Анти Бот для 1C Битрикс: как антиспам для WordPress обзавёлся родственником на Битриксе

Уровень сложностиПростой
Время на прочтение5 мин
Охват и читатели9.8K

Некоторое время назад я писал здесь про антиспам для WordPress — историю о том, как из недоступного клиентам Cloudflare и дырявых бесплатных решений родился свой плагин геоблокировки, а чуть позже — вторую часть с разбором критики и рассказом, что успело поменяться. В конце самой первой статьи была одна проходная фраза: «параллельно ведется разработка аналогичного решения для 1С Битрикс — задача там несколько сложнее архитектурно, но подход тот же». С тех пор модуль доехал до Маркетплейса, обзавелся парой обновлений и первыми покупателями. Расскажу, что получилось — и почему для Битрикса такая защита понадобилась даже раньше, чем для WordPress.

Читать далее
1
23 ...