Ответы пользователя по тегу PHP
  • Что быстрее — глобальная переменная или инициализация класса в другом классе?

    @egorinsk
    > Работаю сейчас над проектом который будет работать при высокой нагрузке.
    > Что быстрее — глобальная переменная или инициализация класса в другом классе?

    Боюсь, что вы даже не представляете себе, что такое «высокие нагрузки». Кстати, не думали двойные кавычки заменить на одинарные и сократить имена переменных до 4 букв (чтобы они помещались в 1 регистр процессора)?
    Ответ написан
    Комментировать
  • Интересная задача на PHP

    @egorinsk
    Ох май май, какой косяк в PHP, сразу же вспоминается еще путаница в возвращаемых значениях в strpos(), когда она может вернуть 0 или false
    Ответ написан
    4 комментария
  • Неожиданно правильное поведение программ

    @egorinsk
    Не верю в чудеса и неожиданности.

    Зато верю в то, что чем строже и больше различных проверок ввести, тем больше ошибок выскочит. Для этого:

    1) ставлю error_reporting в -1 (показывать абсолютно все ошибки, включая всякие deprecated и strict standarts)
    2) Иногда делаю код, преобразующий любую малейшую ошибку в исключение, валящее всю программу (в не-PHP языках это часто по умолчанию так и есть, и это правильно)
    3) указываю type hints — если в функцию должен придти массив или объект определенного класса, то так и пишу
    4) Ставлю assert() массово. Если переданный в функцию массив не должен быть пуст, а другая переменная не может быть отрицательной, проверяю это
    5) Не использую @ и не исправляю ошибки, пока не пойму причину (так как реальная ошибка может быть в вызывающем коде)
    6) В штуках, которые принимают плейсхолдеры, всегда проверяю соответствие числа плейсхолдеров и переданных данных
    7) Жалею, что в PHP нет (или уже есть?) type hints для скалярных типов

    > При правильном проектировании на самом деле часто бывает, что оно работает, и ты не понимаешь почему, и это нормально…

    Нет, не бывает. Вы просто плохо разбираетесь в коде или особенностях языка.
    Ответ написан
    2 комментария
  • Каковы накладные расходы в PHP на мелких объектах?

    @egorinsk
    Во-первых, точный ответ дадут только тесты. Набросайте по-быстрому подобие того, что вы хотите сделать, и проверьте, сколько времени уйдет, например, на создание 100 000 объектов.

    Во-вторых, по моим наблюдениям, проблема не столько в времени создания объектов, сколько в вызовах фукнций, они в PHP не очень быстрые. При создании объекта вызывается как минимум конструктор, и создание 20 свойств выльется в вызов 20 функций.

    Я бы предпочел обойтись без этого. Мне кажется, вы усложняете себе жизнь.

    Вообще, сложные объектные конструкции лучше реализовывать на языках выроде .NET/Java, а не на скриптовых — там все это будет работать гораздо быстрее.
    Ответ написан
    Комментировать
  • Создавать сессии только для залогиненых пользователей?

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

    Вам уже советовали хранить сессии в редисе, можно так же в БД их попробовать хранить.
    Ответ написан
    Комментировать
  • Какой путь выбрать для оптимизации ооочень большой страницы с кучей инпутов?

    @egorinsk
    Надо все же что-то поменять, чтобы HTML не весил 80 мегабайт и там не было 18 000 строк. Человек все равно не станет читать все эти тысячи строк.
    Ответ написан
    Комментировать
  • Как организована система оповещений а-ля Вконтакте?

    @egorinsk
    У вас же браузер есть. Заходим на vk.com и видим, что, например, в Опере, шлются long-polling запросы на qNN.queue.vk.com/im305, куда посылается id пользователя, хитрый ключ, временные метки, в ответ приходит код вида ([{«ts»:«1567120607»,«events»:[]}

    Очевидно, у них развернута сеть серверов, на которых висят демоны, не знаю, на какой технологии, может Си, может Node.JS, может еще что-то, которые, с одной стороны, принимают запросы от клиентов, с другой стороны, получают уведомления.

    Думаю, в коде проще всего при каком-то событии (например, отправка сообщения/добавление в друзья) параллельно этому демону посылается уведомление, и он ретранслирует это обновление заинтересованным пользователям.

    Если бы мне нужен был такой демон, я бы взял для разработки язык D и библиотеку libev.

    Но вы можете попробовать такой демон на PHP написать, я думаю, 10-20 одновременных пользователей он точно выдержит. Или можете взять уже готовый демон — PHP Multiplexor или как-то так, от DKLab.
    Ответ написан
    2 комментария
  • Хочу понять алгоритм перемещания узла в дереве nested set

    @egorinsk
    Нарисуйте небольшое дерево и вручную переместите узел, и посчитайте, что поменялось.
    Ответ написан
    Комментировать
  • Как синхронизировать только структуру БД?

    @egorinsk
    Извечная проблема деплоймента. Если сайт небольшой и не-частообновляемый, то проще всего скачать ночью live базу, внести изменения, залить обратно.

    Если сайт большой, то пишут миграции — код, который апгрейдит/даунгрейдит базу с версии N на версию N + 1, также пишется скрипт, который смотрит версию БД и применяет нужные миграции.

    Но этот вариант, на мой взгляд, плох, так как код миграций надо писать руками, и это сомнительное удовольствие. Я же и так базу ковыряю запросами, почему миграции не генерировать как-то автоматически? Зачем делать все по 2 раза? А вот спросите у любителей Руби, почему им нравится делать все одну и ту же работу 2 раза.
    Ответ написан
  • Как отгружать купленные электронные товары?

    @egorinsk
    > 1) Где лучше хранить сами материалы? FTP-сервер, файловый хостинг?

    На любом сервере с nginx с широким каналом. Ограничений типа качать только в 1 поток или ограничений на скорость скачивания ставить не надо — у вас же магазин, а не бесплатный рапидшеар. Думайте не как сделать проще вам, а как удобнее клиенту.

    > 2) Каким образом формировать уникальную для каждого покупателя, но постоянную относительно ресурса ссылку?

    Добавлять что-нибудь вроде key/session_id в ссылку, а в нгинксе использовать вызов внешнего скрипта для проверки ключа и учета. Например, storage.example.org/key-123456789/История римского права в 3 томах, т.1, Иванов А.А.pdf

    Key может быть привязан к логину, первым 3 цифрам IP и времени.

    Если key неправильный — не выводить непонятных ошибок HTTP 403, а возвращать в личный кабинет на страницу ошибки и выводить телефон, на который можно позвонить в случае проблем со скачиванием.

    У файла должно быть нормальное человекочитаемое имя, а не хеш md5.

    > 3) Какие использовать защитные механизмы для предотвращения расшаривания этой ссылки? Срок жизни, привязка к IP, SMS-подтверждения?

    См. ответ 2

    > 4) Как обезопасить продаваемые материалы в хранилище? Использовать права доступа?

    См. ответ 2
    Ответ написан
    Комментировать
  • Копирайт в каждом файле проекта, или нет?

    @egorinsk
    Не нужно. Если в коде не указан копирайт, это еще не значит, что с ним можно делать что угодно.
    Ответ написан
  • Обработка большого числа $_POST

    @egorinsk
    Я бы убрал strtoupper. Он не нужен. Если программист на клиентсайде перепутал большие буквы с маленькими — пусть исправляет ошибку сам, а не скрипт за него это делает.

    Собирать запрос к БД руками — неуклюже. Я бы свалил все в массив, и передал через плейсхолдеры вроде execute(«INSERT INTO ?table (?#) VALUES (?a)», $table, array_keys($data), array_values($data))

    В остальном нормальный код, выполняющий свои функции. Хотя, конечно, кто-то предложит для этих целей сделать модели, репозитории, unit-of-work и что там еще придумал Мартин Фаулер для этих целей.

    Если вам интересно, как это можно сделать сложнее, почитайте мануалы к любому фреймворку типа Yii или Zend или Symfony или Ruby on Rails или Джанго. Там вам расскажут про модели, валидаторы, хранилища, бекенды, слои абстракции и прочие умности.

    И да, все эти ORM и фреймворки для PHP тяжелые, уродливые, и сам язык, из-за того что при каждом запросе надо инициализировать приложение заново, не позволяет их сделать нормальными, так что с точки зрения производительности лучше писать все руками.

    Но я бы такой код писать не стал, так как мне надо, чтобы свойства модели и полей формы для ее модификации хранились в одном месте, а не были раскиданы по HTML-коду, яваскриптам и PHP-обработчикам. Забудешь же потом, где что менять, когда захочется например изменить лейбл у поля ввода. Также, ваш код не умеет ни делать валидацию переданных данных (передавай что хочешь — все запишет в БД), ни маппинг/сериализацию/джейсонизацию, а мне надо, чтобы все это было.
    Ответ написан
    4 комментария
  • Сайт, способный выдержать высокую нагрузку (?)

    @egorinsk
    Начнем с того, что вам это вряд ли нужно для практических целей. В сутках 86400 секунд. Средний нормально написанный сайт (не друпал, не phpBB и прочий кривокод. Не Zend и не симфони) на PHP с использованием MySQL на среднем сферическом VPS в вакууме (с объемом памяти в 256 Мб) выдерживает 40-50 rps. Иногда даже он упирается не в процессор, а в ширину канала.

    40-50 rps * 86 400 = примерно 1-2 млн хитов в сутки (так как нагрузка неравномерна по времени суток). Это примерно 100-200 тыс. среднеактивных посетителей (или 20-50 тыс., если речь не о блоге а о соцсети). Вряд ли у вас столько будет.

    От идеи генерировать статический HTML давайте откажемся сразу: любой функционал чуть сложнее набора неизменных страниц так не сгенерируешь. Сложность кода и число зависимостей кешей будет расти в геометрических прогрессиях. Идея вставлять динамические фрагменты страниц через SSI/AJAX бесперспективна — они все равно будут вызывать запуск PHP, возможно даже увеличивая нагрузку. Лучше написать масштабируемое приложение с хорошим кешированием данных.

    Хорошей идеей мог бы быть отказ от PHP в пользу Java/C++/.NET/D. Но это усложнит разработку: на этих языках все сложнее и дольше пишется.

    Даже если на ваш блог ринутся все читатели Хабра, tema и еще нескольких блогов. Имея грубо написанный самопис на кривоPHP, у нас есть возможность масштабироваться раз в 10 с ростом нагрузки: ставим более мощное железо, расширяем память с 256 Мб до 64 Гб, ставим нормальный 8-ядерный процессор, нормальные диски. Тюним объем кешей MySQL, добавляем APC, начинаем понемного кешировать страницы в мемкеш. Далее, если нагрузка все равно растет, разносим код на несколько фронтендов, и, возможно, делаем мастер-слейв на MySQL. Можно скомпилировать PHP через hiphop.

    Многим проектам этого хватает.

    Но это тупой подход. Сделать репликацию, поставить балансировщик и нарастить память — ума много не надо. Даже обезьяна с этим справится. Гораздо лучше (и интереснее) изначально делать приложение с учетом возможности масштабироваться (что уж там стесняться) неограниченно. И куда как приятнее осознавать, что твое приложение может расти не хуже вконтакта с его отличниками и победителями математических олимпиад.

    Представим, что у нас растет нагрузка и нам надо увеличиться до 1000 нод. Что касается фронтендов (в вашем случае на PHP), если не хватает мощности одного сервера, их (серверов) мы легко можем поставить хоть 1000, хоть 10000 (единственное, надо отказаться от сохранения сессий в локальных файлах, иначе никто не сможет залогиниться. Возможно, стоит перейти на REST и вообще отказаться от сессий). Перед ними ставим N балансировщиков на nginx, настраеваем round-robin в DNS (чтобы запросы валились на них поочередно).

    Как работает round-robin в DNS вы можете увидеть, набрав nslookup vk.com несколько раз.

    Мемкеш также (вы должны использовать мемкеш в приложении) легко масштабируется на N серверов. Лишь бы памяти было много и минимум гигабитная локальная сеть.

    Раздача статики (картинки, CSS, скрипты) тоже банальна — ставим nginx на N серверов и забываем об этой проблеме. Единственная сложность — это раздача видео. Погуглите, на Хабре есть статьи про организацию CDN для видео и сопутствующие проблемы.

    А вот с БД мы получаем затык. Даже если мы настроим мастер-слейв с несколькими слейвами, объем данных на запись на мастер от 1000 PHP-ных фронтендов положит любой сервер. Несмотря на то, что MySQL в сферической конигрурации на среднем сервере в вакууме легко делает 1-5 тысяч выборок по PKEY в секунду, на запись она работает гораздо хуже. Потому, раз уж мы делаем хайлоад сервис, то база тоже должна масштабироваться. Во-первых, можно разнести разные таблицы на разные сервера. Это мало. во-вторых, можно порезать таблицы на куски и разнести на разные сервера. Это то, что надо. То есть, допустим, в соцсети юзеры с ид 1-10000 хранятся на первом сервере в таблице users_1, юзеры 10000-20000 на втором сервере в таблице user_2, и так далее. Распределение записей и таблиц по серверам должно быть не намертво вбитое, а конфигурируемое, чтобы можно было переносить пачки записей с одного сервера на другой, уравновешивая нагрузку. Для этого придется написать небольшое приложение, показывающее распределение нагрузки и позволяющее переконфигурировать шарды.

    Из такой схемы построения БД вытекают очевидные правила: запросы к БД не должны использовать JOIN (так как это невозможно при разнесенных таблицах, и дждойны плохо работают), должны использовать выборку только по индексам, лучше всего по PKEY (так как без индексов слишком медленно) и должны быть как можно проще. Они должны иметь небольшой LIMIT. Также, стоит пользоваться денормализацией данных: например, чтобы получить список фотографий пользователя, мы берем сериализованный список id этих фото, затем выбираем фото по id, а НЕ используем выборку по полю user_id в таблице photos (так как такая выборка не шардится и не масштабируется).

    В общем, запросы должны быть тупыми как пробка и сводиться к SELECT… WHERE id IN (1, 2, 3). Кстати, как дополнительный плюс, такие запросы легко кешировать и очищать такой кеш.

    Для сервисов типа поиска пользователей (как вконтакте) при такой схеме придется писать отдельные приложения на C++, которые будут индексировать БД и хранить данные в памяти. Увы, PHP тут не справится.

    Вы можете почитать про архитектуру высоконагруженных проектов тут: www.insight-it.ru/highload/

    А да, все. что написано выше, лишь теоретические рассуждения. Подумайте 10 раз, прежде чем применять это на практике.
    Ответ написан
    1 комментарий
  • Какой вариант логики запросов правилен?

    @egorinsk
    Только второй вариант. Не слушайте теоретиков. MySQL все эти джойны и аггрегацию никак не соптимизирует.
    Ответ написан
    Комментировать
  • Какой вариант логики запросов правилен?

    @egorinsk
    Только второй вариант. Не слушайте теоретиков. MySQL все эти джойны и аггрегацию никак не соптимизирует.
    Ответ написан
  • Стоит ли открыть исходный код ORM для PHP?

    @egorinsk
    Сам по себе ORM — банальная ничем не примечательная хрень. Это уже много раз делали в других фреймворках (например, RoR, Java) и описано в книгах про паттерны. Берешь, делаешь как в Руби и пользуешься хоть до посинения.

    Пример с User::create() неудачный: у реальных объектов бывает по 20 свойств и фукнция с 20 аргументами будет выглядеть дико. Функции с подчеркиванием в начале — уродливые. Передавать __CLASS__ и подобные магические методы тоже не очень как-то.

    Один из сложных моментов в проектировании ORM — оптимальная организация взаимодействия с хранилищем. Например, этот ваш пример:

    > foreach(UsersGroup::getPremiumMembers()->orderBy('registration_date')->limit(10) as $user){
    > echo $user->getCountry()->getCurrency()->getCode()."
    ";

    Сколько запросов сгенерирует при использовании SQL-хранилища? По идее, должно быть в районе 3-4, причем данные справочников еще бы и стоило кешировать (ибо валюты у стран меняются очень редко) и обойтись 1-2 запросами. Если у вас в цикле для каждого юзера делается запрос — хлам это, а не ORM.

    Второй момент — оверхед. Вы когда-нибудь считали, какая разница по времени выполнения запроса через ваш ORM и через mysqli_query() (включая время на загрузку и инициализацию классов ORM)? Посчитайте, наверняка у вас после этого вообще пропадет желание использовать ORMы.

    Третий момент — масштабирование. Можно ли, к примеру, сделав огромный сайт на вашем ORM, не переписывая кода, реализовать расшардивание базы на 100 серверов (чтобы справиться с нагрузкой). Можно ли на нем делать проекты уровня хотя бы игр для соцсетей или вконтакта?

    Если у вас есть решение хотя бы некоторых из описанных 3 проблем проектирования ORM, ваша статья на тему архитектурных решений и программистских хитростей была бы крайне интересна. Если нет решения — то такой орм любой школьник может сделать, как я уже сказал, прочтя мануал к рубионрейлс.
    Ответ написан
    3 комментария
  • Как перевести комментарии в *.php файлах ?

    @egorinsk
    Хороший повод выучить китайский, не?
    Ответ написан
    Комментировать
  • С чего начать?

    @egorinsk
    C официального мануала:

    ru.php.net/manual/ru/getting-started.php
    Ответ написан
    Комментировать
  • Как программисту найти работу с нестандартным графиком?

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

    Иначе надо свою компанию.
    Ответ написан
    Комментировать
  • PhpMyAdmin + PHP-FPM = SEGFAULT?

    @egorinsk
    Вы можете собрать/установить debug-версию и после падения отладчиком gdb посмотреть, где (в какой функции) произошла ошибка.
    Ответ написан