Задать вопрос
  • Не приходят сообщения с контактной формы, Извините, данные не были переданы?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    1. Перед отправкой формы нажимаете F12
    2. В открывшихся инструментах разработчика выбираете вкладку Сеть
    3. Отправляете форму
    4. Во вкладке Сеть появляется новая строчка. Нажимаете на неё и там появляется своя панелька на которой надо выбрать вкладку Ответ
    5. Нажимаем на эту вкладку и смотрим, что приехало с сервера. Если самому непонятно, то постим сюда

    Если там не будет ничего полезного, то надо смотреть логи сервера. Где-то в ISPManager-е должен быть раздел с логами, там нужен лог ошибок.
    Ответ написан
    2 комментария
  • Видит ли провайдер то, что я скачал оффлайн страницу сайта в Google chrome на телефоне?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    "Скачивание не требует интернета" - это какая-то бессмыслица. Скачивание разумеется требует интернета. А тут наверное имеется в виду "открыл скачанную ранее"? В этом случае по идее никаких запросов быть не должно, но тут зависит от яваскрипта, и он может в принципе выдать.
    Ответ написан
    2 комментария
  • Как общаются микро-сервисы в реальных проектах?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Как правильно написал Сергей Горностаев, всё зависит от задачи.
    Например, у вас маркетплейс, и в нем микросервис отзывов о товаре. Это совершенно некритичный функционал, и поэтому никакие очереди тут разумеется не нужны.
    Фактически, фронт может даже напрямую к нему обращаться, и выводить заглушку, если отзывы недоступны.
    Ну или внутри, при формировании страницы товара, код может дёрнуть микросервис и поставить заглушку, если тот недоступен. Дергать опять же можно по-разному, но для универсальности можно делать тот же REST, причём во внутреннем контуре даже без SSL (и его накладных расходов).

    Брокеры же нужны там, где важна целостность. Например оповещения, по почте или СМС. Закинул оповещение в очередь, и дальше оно всё равно уйдет пользователю даже если конкретно в этот момент сервис отправки недоступен.
    Ответ написан
    Комментировать
  • Точь в точь ли маппятся поля json-сущности на поля в таблицах базы данных?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Я просто оставлю это здесь: отображение объектов на реляционную БД - это Вьетнамская война компьютерной науки
    Ответ написан
    2 комментария
  • Как подключится к ubuntu на virtualbox через wsl по ssh?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Надо в настройках сети для виртуалки выбрать Bridged adapter, вместо NAT, который там стоит по умолчанию.
    Ответ написан
    Комментировать
  • Можно ли настроить запросы к php через вебсокет и http одновременно?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Разумеется можно. Никаких нюансов в одновременной работе нет, поскольку тут нет никакой "одновременности". php-fpm и websocket - это два разных сервиса, которые могут располагаться на одном и том же сервере или на разных, но в любом случае никак не пересекаются. В добавление к текущему веб-серверу вы просто запускаете вебсокет сервер и посылаете на него вебсокет запросы из браузера.

    Ну то есть вам всего лишь надо осознать, что никакой одновременности нет, а дальше просто поставить вебсокет сервер, например workerman, и написать код, который по запросу будет соединяться с БД, получать нужную инфу и отправлять клиенту.

    1. Да.
    2. Как говорилось выше - можно. Любой сервер в сети по определению обеспечивает работу множества сервисов, количество которых ограничено только количеством свободных портов. Можно поставить два веб-сервера и пять вебсокет серверов.
    3. Нет, разумеется. unix сокет это как раз внутренняя кухня сервера, но мы же говорим о сетевом взаимодействии. А tcp взаимодействие nginx и php-fpm тут вообще не при чём.
    Ответ написан
    8 комментариев
  • PHP. Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated in?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    В РНР разбираться не обязательно, надо минимально разбираться в поддержке софта.
    Варианты, по степени убывания идеальности
    1. Обновить версию Джюмлы
    2. В настройках пхп отключить ошибки E_DEPRECATED
    3. Залезть с грязными ногами в файл /var/www/u2340392/data/www/test.kaikova.ru/modules/mod_bt_contentslider/tmpl/default.php и на 26 строке при вызове функции trim() дописать ?? '' после имени переменной. Т.е
    -trim($var);
    +trim($var ?? '');
    Ответ написан
    Комментировать
  • Как развивать логику в программировании?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Я бы рекомендовал в качестве первого языка РНР. Он куда проще, читается практически как натуральный английский язык.

    <?php
    $numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    foreach ($numbers as $number) {
        if ($number % 2 === 0) {
            echo "$number is even\n";
        } else {
            echo "$number is odd.\n";
        }
    }

    Ничего лишнего, переменные визуально отличимы от ключевых слов, читается легко, "перебираем массив по одному, назначая очередной элемент переменной $number. Проверяем, если остаток от деления на 2 равен нулю, то выводим что чётное, а иначе - что нечётное".
    Пет проект, опять же, вообще ума не надо: скачал РНР на комп, открыл консоль, выполнил
    php -S localhost:8888 -t "путь к папке с РНР файлами"
    открыл в браузере localhost:8888/test.php и уже готов веб-сайт, ваяй - не хочу.

    Сравним с гошечкой
    package main
    import "fmt"
    func main() {
        numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    
        for _, number := range numbers {
            if number%2 == 0 {
                fmt.Printf("%d is even\n", number)
            } else {
                fmt.Printf("%d is odd\n", number)
            }
        }
    }

    Вроде всё то же самое, но на английском уже не прочтёшь, "для подчеркивание запятая number равно расстояние numbers". Даже вывод какой-то с подвыподвертом. И все эти сокращения, как будто за каждую букву вычитают из зарплаты. Действительно выглядит как набор переменных и непонятных аббревиатур.
    Ответ написан
  • Как называется такая вложенность в php?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Ответ написан
    Комментировать
  • Почему возникает ошибка (T_VARIBLE)?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Когда пишет unexpected '$sql' (T_VARIABLE) это значит, что проблема в конце предыдущего выражения.
    Поднимаем глаза, смотрим на конец предыдущего выражения, и видим, что с ним не так.
    Ответ написан
    Комментировать
  • Помощь в PHP проверка данных из файла только выбранные значения?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    У вас файл создан под Уиндоуз, в которой в качестве разделителя строк используется последовательность \r\n
    Разбивая по \n, вы в конце каждой строки оставляете висеть символ \r, и в итоге при сравнении совпадает только последний элемент файла, после которого нет перевода строки

    Для чтения файлов в РНР есть специальная функция. Которая понимает любые переводы строк, и умеет их автоматически удалять.
    $array = file(JPATH_SITE.'/list.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);

    И всё сразу начнёт находиться.
    Ответ написан
    Комментировать
  • Как в PHP найти строку, которая содержит или не содержит символ?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    "содержит или не содержит символ" (а точнее - предыдущее выражение) в регулярных выражениях обозначается знаком вопроса. Шаблон \. ?ru найдет как site.ru, так и site. ru
    Ответ написан
    Комментировать
  • Какую кодировку выбрать для немецкого языка?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Как обычно, три ответа - и ни одного по делу

    Кодировка таблиц в MySql должна быть utf8mb4.
    Ответ написан
    Комментировать
  • Что выбрать для хостинга сайта: 2 ядра до 5 ГГц или 6 ядер до 3.2 ГГц?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Для конкретного сайта уже ответил Everything_is_bad: для текущей нагрузки оба сервера - это оверкилл, даже для DLE с их идиотcкими xfields в БД. Хватит и одного ядра с гигом памяти.

    Но если отвечать на сферический вопрос в вакууме "что выбрать для хостинга", то ответ освершенно очевиден: второй. Эти два сервера вообще несравнимы. И дело даже не в том, что веб сервер - это по определению параллельные запросы, а вся нагрузка приходится на БД (особенно в случае идиотской БД dle) - то есть нам количество ядер куда важнее их частоты, которая всё равно будет молотить впустую. Но там ещё и памяти больше на порядок. То есть даже если бы у второго сервера было всего два ядра, то в общем случае всё равно следовало бы выбрать его. Просто потому что основная нагрузка - это БД, а скорость БД - это память.
    Ответ написан
    3 комментария
  • Как удалить весь текст кроме ссылок?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Ответ легко ищется поисковиком
    Ответ написан
    Комментировать
  • Почему не получается обратиться к наследуемому свойству (php) через асинхронный запрос?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Вопрос "как обратиться через аякс к свойству класса пхпе" является заведомо бессмысленным. JS не работает со свойствами классов в РНР.
    Поэтому в решении таких проблем очень помогает логика.
    Если отставить в сторону "свойства", то мы получим довольно простую формулировку вопроса: "почему синхронный и асинхронный запрос к одному и тому же скрипту возвращают разные данные?". И здесь уже, рассуждая логически, можно прийти к очевидному ответу: эти запросы обращаются к разным бэкендам. То есть, чтобы решить проблему, надо либо обновить код на том сервере, к которому обращается fetch, либо делать запрос на тот сервер, который возвращает правильные данные.

    Это если исходить из предоставленных данных. Вполне вероятно, что автор запутался где-то ещё. Но тут уже ему придётся разбираться самостоятельно. Но опять же, рассуждая логически, а не "Почему не получается обратиться к свойству php через асинхронный запрос?".
    Ответ написан
    9 комментариев
  • Как добавить данные в бд с помощью php sqlsrv?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Самое главное, чему надо научиться - это правильно формулировать свои проблемы.
    Судя по приведённому коду, вы прекрасно знаете, как добавлять данные. Но почему-то всё равно спрашиваете, как это сделать. "Где логика, где разум?"
    Судя по тексту вопроса, проблема ваша формулируется совсем по-другому: не "как добавить", а "почему не добавляется". Это два совершенно разных вопроса.

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

    1. Убедиться, что в РНР включён вывод ошибок. Проверить можно тупо допустив ошибку синтаксиса. Если она выведется - очень хорошо, значит вы видите ошибки. Если нет, то включить, хотя бы через ini_set.
    1.2. Для древних, как гуано мамонта расширений, таких как sqsrv, надо проверять ошибки запросов вручную. Но делать это надо с умом, а не как в соседнем ответе. Ошибку SQL надо не тупо вываливать на экран вручную, а превратить в ошибку РНР, чтобы она выводилась так же и туда же, куда и остальные ошибки. Это можно сделать простым кодом вида
    if( $stmt === false ) {
        throw new Exception(print_r( sqlsrv_errors(), true));
    }

    2. Упростить свой код. Всегда проверять что-то одно. Вы что хотите проверить? Выполнение запроса на вставку? А зачем вам тогда форма вообще? Сделайте скрипт, который при обращении к нему просто записывает данные в БД, без всяких форм и прочего.
    Работает? Очень хорошо, переходите к формам. И если что-то не будет работать, то и вопрос будет совсем другой, "у меня не работает форма", который к "как сделать запрос" уже совсем никакого отношения не имеет.
    Не работает? Разбирайтесь с запросом, без всяких форм. Если вы проверяете что-то одно, то у вас и не работает что-то одно. А не десять разных потенциальных точек отказа.
    3. Контролировать ход выполнения своего кода.
    Например, вот вы разобрались с запросом, и перешли к обработке формы. И вот у вас есть условие, if (isset($_POST['signInButton'])). А вы проверили, оно хоть выполнилось? Если нет, то в базу никогда ничего не добавится, хоть обперегружайся. Поэтому добавляете временный вывод отладочной информации:
    echo "проверяем нажатие кнопки\n";
    if (isset($_POST['signInButton'])) {
        echo "проверка прошла успешно\n";
        createAccount($conn, $email, $password, $keepSignIn);
    }

    Если "проверка прошла успешно" не вывелось - значит никакого $_POST['signInButton']) в вашем скрипте нет, и надо разбираться - почему. Например, в форме не указан метод, или кнопка называется совсем по-другому. Чтобы разобраться с этим, надо
    3.1 Выводить содержимое используемых переменных. Делаете
    var_dump($_POST);
    после отправки формы, и смотрите. Если там совсем пусто, значит никакую форму методом POST вы не отправляли. Если там что-то есть - то смотрите, что именно, и насколько это соответствует вашим ожиданиям.

    Вот и всё. Эта нехитрая инструкция позволяет быстро решить любые проблемы с кодом. Главное потом не забыть удалить все отладочные сообщения. или научиться пользоваться пошаговой отладкой в IDE
    Ответ написан
    1 комментарий
  • Как объединить запросы в транзакцию?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Поскольку быстрым поиском готовый ответ на Тостере не находится, стоит написать канонический.

    Сначала общая информация:

    Транзакция служит для обеспечения принципа "всё или ничего", гарантируя, что либо все запросы выполнились без ошибок, либо, если в каком-то из запросов произошла ошибка, то все предыдущие будут отменены, как будто их и не было вовсе. Из чего можно сделать следующие выводы:
    • транзакция не нужна для любого количества запросов на выборку данных, поскольку там нечего откатывать
    • транзакция не нужна для одного запроса на изменение данных (вставка, обновление, удаление) - такой запрос представляет из себя мини-транзакцию, которая сама автоматом откатывается при ошибке
    • не следует путать транзакции с блокировками. Хотя при определённых параметрах транзакции могут выполнять и блокировку, в общем случае это два разных механизма, которые могут выполняться как вместе, так и по отдельности. По умолчанию транзакция НЕ обеспечивает блокировку таблиц, участвующих в запросе


    Самым простым вариантом будет заключить запросы между вызовами beginTransaction() и commit(), как показано например в документации к последнему.
    $db->beginTransaction();
    $db->prepare("UPDATE `tab1` SET `col` = ?")->execute($data1);
    $db->prepare("UPDATE `tab2` SET  `col` = ?")->execute($data2);
    $db->prepare("UPDATE `tab3` SET  `col` = ?")->execute($data3);
    $db->commit();

    Для современных версий РНР этого должно быть достаточно: начиная с РНР 8.0 ошибочный запрос по умолчанию выбрасывает исключение. Не пойманное исключение прерывает выполнение РНР скрипта. При прерывании выполнения скрипта РНР закрывает соединение с Mysql, а при закрытии соединения Mysql откатывает все открытые в нём транзакции.

    Соответственно, при ошибке в любом из запросов транзакция автоматически откатится. А при успешном выполнении всех запросов транзакция, соответственно, закоммитится.

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

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


    Также желательно помнить, что в любом более-менее сложном коде очень быстро появляются вложенные транзакции, а PDO при попытке стартовать транзакцию при уже открытой, выбросит исключение, что, соответственно, приведёт к откату родительской (и это гораздо лучше поведения MySQL по умолчанию, которая автоматически коммитит старую). И имеет смысл накидать простой кодик, который считает вложенные транзакции, и не стартует, если уже был старт, а при коммите вычитает вложенность, а реально коммитит только если вложенности не осталось. Что-то вроде кода из комментариев к beginTransaction(), подравняв его напильником
    class \MyPDO extends \PDO
    {
        protected $transactionCounter = 0;
    
        public function beginTransaction()
        {
            if($this->transactionCounter++ === 0) {
                return parent::beginTransaction();
            }
        }
        public function commit()
        {
            $this->transactionCounter--;
            if($this->transactionCounter === 0) {
                return parent::commit();
            }
        }
        public function rollback()
        {
            $this->transactionCounter = 0;
            return parent::rollback();
        }
    }

    разместив его либо прямо в PDO, либо в своем враппере.
    Ответ написан
    3 комментария
  • Разбивка на страницы?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Чтобы ограничить количество выводимых страниц требуется знание арифметики в пределах начальной школы.
    Чтобы вместо 1 и $num_pages использовать заранее рассчитанные значения, укладывающиеся в определённый интервал. Например 10 страниц.
    То есть надо всего лишь определить начальную и конечную цифры, которые подставлять в for вместо 1 и $num_pages.
    Например, если мы хотим выводить только 10 страниц, а текущую выводить посередине то для получения первой цифры надо отнять от текущей 4. Затем к ней надо прибавить 9 - так мы получим второе число.
    При этом, разумеется, надо проверить, чтобы первое не было меньше 1, а последнее - больше $num_pages.
    А дальше просто подставить их в for. Вот и всё.
    Ответ написан
    2 комментария
  • Как сделать полное кэширование базы данных?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Вопрос сформулирован по-дурацки, из серии преждевременной оптимизации. "У меня ещё ни базы, ни запросов, ни нагрузки и никогда не будет, но желаю чтобы всё летало!"

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

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

    Во-вторых, добавить нужные индексы. Поскольку даже в оперативке искать по миллиону записей перебором будет гораздо дольше чем в 5-10 хопов по заранее упорядоченному индексу.
    Ответ написан
    5 комментариев