Ответы пользователя по тегу PHP
  • Как исправить ошибки возникающие при поднятии/установке сайта с помощью Docker?

    gscraft
    @gscraft
    Программист, философ
    Вы собираете решение на основе некого полу-любительского Docker-образа. По ссылке на github видно, что автор(ы) репозитория страдает некой манией велосипедных дел, и создал свои контейнеры на все про всё, и при этом давно их не обновляет. Если хотите решение на базе Docker, то стоит быть готовым к тому, что такое решение нужно сопровождать, т.к. сторонние нестабильны. Поэтому желательно разобраться в базовых образах nginx / php / базы данных, чтобы завести это все вручную и самостоятельно, с уверенным пониманием процесса. В официальных хабах есть все необходимые инструкции: как устанавливать пакеты, как задать стартовые настройки через окружение или шаблонные значения. Это займет время, конечно, день-два, но окупится как в данном проекте, так и в дальнейшем. Эти контейнеры систематически обновляются и имеют лучшую совместимость, в противоположность случаю, когда что-то отваливается у авторов 10+ контейнеров, неспособных их сопровождать (в чем проблема и сейчас: не хватает расширения, автор не предусмотрел / забросил, подложив проблему своим пользователям). В Вашей ситуации нужно также ознакомиться со списком требований Drupal, и развернуть требуемый Dockerfile для PHP (через Alpine и встроенную систему установки расширений или Debian / ppa)
    Ответ написан
    1 комментарий
  • Как вырезать слово из строки?

    gscraft
    @gscraft
    Программист, философ
    <?php
    $string = 'Нажми кнопку и получи @приз, чтобы принять участие';
    $matches = [];
    if (preg_match('/@[а-я]+/ui', $string, $matches)) {
      $word = $matches[0];
      echo $word, PHP_EOL;
    }
    Ответ написан
    Комментировать
  • Не загружается в бд таблица?

    gscraft
    @gscraft
    Программист, философ
    О, небо. Постарайтесь разделить код и дизайн, пусть логикой занимается отдельный PHP-файл, а выводит — другой. Вы вставляете записи в какую таблицу? `excel` или `user_details`?

    Конкретно по проблеме, посмотрите, что у Вас формируется в $query, выведите его любым удобным образом (отладчик, консоль, die($query) и т.д.), и посмотрите, что там не так. Можно попробовать этот запрос в MySQL-клиенте (PHPMyAdmin, HeidiSQL, MySQL Workbench, Valentina Studio, mysql.exe, etc).
    Ответ написан
  • Как оптимизировать запись в файл .xls?

    gscraft
    @gscraft
    Программист, философ
    И Excel спокойно поглощает такое количество строк? Там вроде около миллиона строк, но Excel не предназначен для этого, если массив данных очень большой, то работать с ним лучше через СУБД.

    Способов оптимизации много, но универсальных путей не так много, не зная бизнес-требований, структуры данных сложно сказать точнее. Из общего. Во-первых, да, брать данные порциями, например, по 10к или 50к строк. Во-вторых, не брать данные повторно, кэшировать (вряд ли у Вас меняются все данные каждый раз), сохраняя срезы Excel или денормализацией. В-третьих, оптимизировать структуру данных и / или запросы. В этом плане Doctrine или другой движок едва ли играют роль, тем более Вы используете конструктор запросов. В-четвертых, если память грузит запись в Excel, можно отказаться от движка (опять же, неизвестно, используете ли такой?), писать вручную в XML-шаблон, упаковывая в Excel опять же руками.
    Ответ написан
    8 комментариев
  • Целесообразно ли логирование выносить в отдельную базу?

    gscraft
    @gscraft
    Программист, философ
    А в чем загвоздка? Проблем с этим нет, если журналы грузят базу, то используйте отдельную. И даже не классическую базу, а MongoDB, например, или иные инструменты.

    PS Ну а снятие копий, почему не исключить таблицы при выборке? Плюс, есть другие решения для разработчика, например, наборы тестовых данных (у Laravel есть соответствующий инструмент).
    Ответ написан
    2 комментария
  • Цикл проходит несколько раз, где ошибка?

    gscraft
    @gscraft
    Программист, философ
    Судя по Вашему JSON, полученному от сервиса, Вам не нужны два цикла foreach, второй — лишний, его можно просто удалить.
    Ответ написан
    2 комментария
  • В чем практический смысл использования интерфейсов в PHP?

    gscraft
    @gscraft
    Программист, философ
    Вам нужно смотреть в сторону принципов SOLID, разобраться, почему эти подходы оправданы. Интерфейсы же выполняют несколько задач, в связи с этими принципами.

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

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

    В-третьих, продуманный интерфейс позволяет в большей степени создавать взаимозаменяемые реализации — конечные классы. Тот, кто использует интерфейс при разработке класса обязан разработать все обязательства интерфейса.

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

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

    Добавлю, к слову, о внедрении зависимостей. Действительно, этот подход может использоваться и без интерфейсов, тот факт, что инверсия управления и внедрение зависимостей используются чаще всего с интерфейсами — своего рода совпадение. Хороший пример: фреймворк Yii 2 или библиотека Pimple, там в качестве маркеров для внедрения зависимостей часто используются произвольные (или основанные на иных соглашениях) строки. Это к тому, что DI — необязательно самый яркий пример использования интерфейсов (хотя и более ценный, чем другие варианты).
    Ответ написан
    Комментировать
  • Почему если цикл в цикле, то идёт дублирование?

    gscraft
    @gscraft
    Программист, философ
    vladislav997, чтобы в print_r($var); не дублировались посты нужно воспользоваться инъекцией зависимостей и обязательно подключить пару серьезных библиотек, например, AR/ORM.

    Если серьезно, путей решения того, что хотите сделать, очень много. Проще всего — группировать, что в каком-то смысле и делают ORM, где сразу доступно $user->posts. Группировать можно и на уровне запроса к базе, и на уровне кода. Например.
    $vars = [];
    foreach($posts as $post)
      $vars[$post->author_id][] = $post->name;
    print_r($vars); // теперь у Вас записи группированы по пользователю, делайте что хочется,
    // например:
    foreach ($users as $user)
      if (isset($vars[$user->id]))
        print_r(implode(', ', $vars[$user->id]));

    — вообще, есть правило, старайтесь избегать двойного обхода массивов. А в данном случае Вы дважды обходили $posts внутри перебора $users.
    Ответ написан
    Комментировать
  • Как сократить условия php?

    gscraft
    @gscraft
    Программист, философ
    В цикле:
    foreach (range(2016, 2025) as $year)
      if (intval($_GET['year']) == $year)
        $jdns['year'] = (string) $year;

    Или без цикла:
    if (in_array(intval($_GET['year']), range(2016, 2025)))
      $jdns['year'] = (string) intval($_GET['year']);

    PS FanatPHP верно отмечает, если даты лежат последовательно в заданном диапазоне, проще сравнить условием больше-меньше:
    if (intval($_GET['year']) >= 2016 && intval($_GET['year']) <= 2025)
      $jdns['year'] = (string) intval($_GET['year']);
    Ответ написан
  • Почему ругается Undefined offset: 18145?

    gscraft
    @gscraft
    Программист, философ
    Вы пытаетесь сделать ++ к несуществующему элементу в массиве $companyStatistics. Сначала проверьте, существует ли элемент.
    UPD немного запутался в Ваших квадратных скобках
    Ответ написан
  • Как сделать редирект после заполнения формы?

    gscraft
    @gscraft
    Программист, философ
    Редирект делает браузер, Вам нужно отправить заголовок Location: header("Location: /{$url}", true, $status); — однако, стоит учитывать, что это может не сработать с некоторыми ajax-библиотеками, там уж смотрите по обстоятельствам.
    Ответ написан
    Комментировать
  • Почему дублируется пустая таблица?

    gscraft
    @gscraft
    Программист, философ
    А каким фреймворком пользуетесь? Очень похоже на то, что возвращается HTML с макетом всей страницы. Кстати, если уж пользуетесь JS / Ajax, почему бы не использовать какой-то движок таблицы? Например, datatables.net (тяжеловат, но можно найти аналоги легче). Другой вариант, использовать что-нибудь вроде vue, хотя все это займет время. Ajax-таблицы позволят разгрузить вывод, ведь можно будет вернуть json.

    С пагинацией, первое, просто переписать в духе того, как формируется таблица:
    $pagination = '';
    if ($page != 1) {
        $pagination .= "<a class=\"page\" href=\"/app/index?page={$prev}\"></a>";
    }
    // ...

    Ну или начать использовать шаблонизатор, например (но подозреваю, что он уже есть, т.к. что-то тащит за собой весь макет (layout) страницы).

    ЗЫ так же событие клика может происходить дважды, попробуйте в инструментах разработчика (ctrl + shift + i), поставить точку остановки на строке 'let column_name = '.
    Ответ написан
  • Как реализовать итератор анонимным классом?

    gscraft
    @gscraft
    Программист, философ
    $o = new class ([1, 2, 3]) implements \Iterator {
        protected array $data;
        protected int $position;
        public function __construct(array $data) { $this->data = $data; $this->position = 0; }
        public function current () { return $this->data[$this->position]; }
        public function key () { return $this->position; }
        public function next () { ++$this->position; }
        public function rewind () { $this->position = 0; }
        public function valid () { return isset($this->data[$this->position]); }
    };
    
    foreach ($o as $i => $v) echo "$i => $v", PHP_EOL;
    Ответ написан
  • Как отсортировать массив в порядке, определенном пользователем?

    gscraft
    @gscraft
    Программист, философ
    $source = [...];
    $pattern = [321, 8734, 210, 2131];
    usort($source, function ($a, $b) use ($pattern) {
      $x = array_search($a['id'], $pattern); // Вам нужно искать свое значение, разумеется
      $y = array_search($b['id'], $pattern);
      if ($x == $y) return 0;
      return ($x < $y) ? -1 : 1; // если индекс первого элемента больше, он "меньше"
    });

    — суть в том, чтобы определять вес элементов при сортировке по их позиции в массиве-паттерне.
    Ответ написан
  • Найти конечный элемент что то типа замыкания php?

    gscraft
    @gscraft
    Программист, философ
    Вы пытаетесь вывести в ссылке материализованный путь? Да, при смене одного из звеньев в цепочке родитель-потомок придется менять весь путь. Да, Вам нужно перебрать всех родителей от потомка, чтобы построить этот путь и если Вы не храните иерархию именно в виде пути. А что за конечный элемент Вы пытаетесь разыскать и с какой целью? Если ссылка вида: /родитель1/родитель2/потомок, то Вам нужен только потомок, а запрос от него всех родителей нужен только для формирования ссылки. Но вообще, не лучшая идея, в этом нет особого смысла, если это не строгое желание заказчика и сокращение ссылки при этом не ведет в соответствующий раздел (но лучше обойтись именно хлебными крошками на странице, ведущими по прямой ссылке в категорию).
    Ответ написан
    Комментировать
  • Как сделать сортировку в html с использованием php?

    gscraft
    @gscraft
    Программист, философ
    Вячеслав Коростин, сделайте список ссылками или среагируйте на нажатие с JS и сделайте программный переход по ссылке:
    <!-- вместо -->
    <input type="radio" name="sortType" value="sort-az" checked="checked" id="sort-az"><label for="sort-az">Название: А — Я</label>
    <!-- например: -->
    <a href="/showAll?order=asc&sort=name">Название: А — Я</a>

    Или (чисто для примера, можно решить эффективнее):
    document.getElementById('sort-az').onchange = function (event) {
        if (event.target.checked)
            document.location.href =  '/showAll?order=asc&sort=name';
    };
    Ответ написан
    Комментировать
  • В чем проблема PDO?

    gscraft
    @gscraft
    Программист, философ
    Вы пытаетесь в сессию сохранить все данные класса User, вот и ругается, что сериализуете объект PDO. Во-первых, довольно странное подключение, у вас и $connect, и $global_connection одно и тоже, и глобальное подключение передаете в класс. Есть смысл переосмыслить все это. Во-вторых, реализуйте, например, метод User::getData, который вернет непосредственно данные пользователя: $_SESSION['logged'] = $user->getData()
    Ответ написан
    Комментировать
  • Как по имени пользователя получить данные из базы и подсчитать их?

    gscraft
    @gscraft
    Программист, философ
    Ну, вывести результат придется самостоятельно. А вариантов запросов множество. Через JOIN, через вложенные запросы, через группировку по значению, но в любом случае с агрегацией. Далее примеры решения, без знания структуры Ваших данных и без оптимизаций. В первом случае Вы получите по 2 (и более) строки на каждого пользователя (например, user_id=1, status='ok', name= 'John galt', status_count=2 и user_id=1, status='trash', name= 'John galt', status_count=67):
    SELECT *, COUNT(status) as status_count FROM table_name WHERE name = :name GROUP BY user_id, status;

    В этом случае получите 1 строку на каждого пользователя, но запрос, возможно, тяжелее (user_id=1, name= 'John galt', status_ok_count=2, status_trash_count=95)
    SELECT COUNT(ok.status) as status_ok_count, COUNT(trash.status) as status_trash_count, table_name.user_id, table_name.name
    FROM table_name WHERE name=?
       INNER JOIN table_name as ok ON ok.user_id = table_name.user_id
       INNER JOIN table_name as trash ON trash.user_id = table_name.user_id
    WHERE table_name.name = :name AND ok.status = 'ok' AND trash.status='trash'
    GROUP BY table_name.user_id;

    PS Есть смысл делать выборку не по имени, а по идентификатору, если надо получить данные на пользователя (а не найти именно по имени), запросы по первичному ключу всегда существенно быстрее.
    Ответ написан
    6 комментариев
  • Как сделать подсчёт совпадающих слов php?

    gscraft
    @gscraft
    Программист, философ
    Вхождения подстроки:
    $names = explode(', ', mb_strtolower('Катя, Марина, Миша')); // обратите внимание на разделитель
    $text = mb_strtolower('Сегодня Катя пошла гулять. Миша и Марина пришли на площадку немного позже, Катя увидев их зразу же подбежала к ним');
    $count = 0;
    foreach ($names as $name) $count += mb_substr_count($text, $name);
    echo $count, PHP_EOL;

    Вхождения слов, с учетом разделителей:
    $names = implode('|', explode(', ', 'Катя, Марина, Миша'));
    $text = 'Сегодня Катя пошла гулять. Миша и Марина пришли на площадку немного позже, Катя увидев их зразу же подбежала к ним';
    $count = preg_match_all("/(^|\W+)($names)(\W+|$)/ui", $text);
    echo $count, PHP_EOL;
    Ответ написан
    6 комментариев
  • Как сделать поиск в строке со стоп словом?

    gscraft
    @gscraft
    Программист, философ
    Я несколько минут не могу прочитать код, что происходит? Что это за конструкции, что пытаетесь сделать с переменной $stop_words после false и погружая в нее текст "&& strpos($description, для бровей)=== false "? Вы текст ошибки пробовали в Yandex Translate закинуть? Банально, ошибки синтаксиса. Навскидку, Вам достаточно:
    foreach ($stops as $stop) { // $stop должно быть строкой, разумеется
      if ( mb_strpos($description, 'тени') !== false && mb_strpos($description, $stop) === false ) {
         echo 'Mission complete: ', $description, PHP_EOL;
      }
    }
    Ответ написан
    3 комментария