Ответы пользователя по тегу PHP
  • Почему не срабатывает insert into через php?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    $db_table = "articles"; // Имя Таблицы БД

    Нет, не имя таблицы, а имя базы данных ($dbname).

    if (!$mysqli->query($query)) {
        printf("Errormessage: %s\n", $mysqli->error);
    }

    См. также: SQL Injection
    Ответ написан
    2 комментария
  • Php как проверить строку?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    if (count(explode('.', $value)) == 3) {
      echo "ok";
    }

    Проверка строки в формате NN.NN.NNNN:

    if (preg_match('/\d{2}\.\d{2}\.\d{2,4}/', $value) === 1) {
      echo "ok";
    }

    Проверка на наличие трех точек с любым содержимым:

    if (preg_match('/.+\..+\..+/', $value) === 1) {
      echo "ok";
    }
    Ответ написан
    Комментировать
  • При отправки файла с сайта вместо одного приходит сразу два в чём проблема?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Две части с Content-Disposition и каждая attachment (вложение).

    5b1e48689868e497681523.png
    Ответ написан
    Комментировать
  • Как вывести переменную за массив foreach?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Судя по всему вы циклом проходите по всем товарам?

    Что такое spec? В вашем примере это константа, полагаю проблема именно в этом.

    Вероятно, spec должна быть переменной:

    $good[$spec] = array('mall', 'discount', 'promotion');
    //    ^
    
    foreach($good[$spec] as $mall) {
      //          ^
      // ...
    }

    ---

    UPD: Теория с константой оказалась ошибочной и в данном случае spec интерпретируется, как строковой литерал, однако так делать не рекомендуется:

    php.net/manual/ru/language.types.array.php
    Почему $foo[bar] неверно?

    Всегда заключайте в кавычки строковый литерал в индексе ассоциативного массива. К примеру, пишите $foo['bar'], а не $foo[bar]. Но почему? Часто в старых скриптах можно встретить следующий синтаксис:

    <?php
    $foo[bar] = 'враг';
    echo $foo[bar];
    // и т.д.
    ?>

    Это неверно, хотя и работает. Причина в том, что этот код содержит неопределенную константу (bar), а не строку ('bar' - обратите внимание на кавычки). Это работает, потому что PHP автоматически преобразует "голую строку" (не заключенную в кавычки строку, которая не соответствует ни одному из известных символов языка) в строку со значением этой "голой строки". Например, если константа с именем bar не определена, то PHP заменит bar на строку 'bar' и использует ее.
    Ответ написан
    4 комментария
  • Как составить условие, если переменная равна -1?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    <?php if($music != -1) { ?>
    Или тут в чем-то подвох? :-)
    Ответ написан
    8 комментариев
  • Как быстро отсортировать таблицу?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Узкое место тут в первую очередь jQuery. Нужно уменьшить число запросов к элементам через jQuery. А то получается, что у вас при сортировки для каждой итерации происходит маленький ад :-)

    Возможно, если вы сделаете сортировку, сформируете новый набор данных и затем замените им старые данные, работать будет быстрее.

    Вот небольшой пример: https://jsfiddle.net/alekseynemiro/q3tsw3bt/1/

    var data = [];
    
    // получаем данные из таблицы в массив
    $('tr', 'table>tbody').each(function(index, row) {
      var cells = $('td', row);
      var sum = 0;
      var items = [];
    
      for (var i = 0; i < cells.length; i++)
      {
        if (i == cells.length - 1)
        {
          cells[i].innerHTML = sum / 5;
          items.push(sum / 5);
        }
        else
        {
          sum += parseInt(cells[i].innerHTML, 10);
          items.push(parseInt(cells[i].innerHTML, 10));
        }
      }
    
      data.push(items);
    });
    
    // сортируем массив
    data.sort(function (a, b) {
      return a[5] - b[5];
    });
    
    // создаем новую таблицу на основе массива
    var html = '<table><thead><tr>';
    html += '<th>price</th><th>price</th><th>price</th>';
    html += '<th>price</th><th>price</th><th>avrg</th></tr></thead>';
    html += '<tbody>';
    
    for (var i = 0; i < data.length; i++)
    {
      html += '<tr>';
    
      for (var j = 0; j < data[i].length; j++)
      {
        html += '<td>' + data[i][j] + '</td>';
      }
    
      html += '</tr>';
    }
    
    html += '</tbody></table>';
    
    // выводим таблицу (перезаписываем старую)
    $('#content').html(html);

    Набросал еще вариант со счетчиком и с 50 000 строками, но счетчик показывает неправильное время, видимо на отрисовку данных в браузере уходит больше времени.
    Ответ написан
    Комментировать
  • Почему phpDocumentor не подхватывает документацию в файле?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    /**
     * @see CommonModule::onLoad()
     * CommonModule constructor. 
    * You can not change the constructor directly, but you can use onLoad function instead.
     */
    final function __construct()

    Указывать @see перед описанием (summary) неправильно.

    https://www.phpdoc.org/docs/latest/guides/docblock...

    be57b9047f6548b1822476458e094357.png
    Нужно изменить порядок, сначала должно идти summary, затем может идти description и только потом tags (@see - относится к tags):

    /**
     * CommonModule constructor. 
     * You can not change the constructor directly, but you can use onLoad function instead.
     *
     * @see CommonModule::onLoad()
     */
    final function __construct()
    Ответ написан
    Комментировать
  • PHP: imagedestroy и unset - в чём отличия?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Разница может быть в работе методов освобождения ресурсов (объект может быть сложным) и в механизмах работы сборщика мусора. Особенно, если учесть, что GD - это отдельный модуль, а unset является частью ядра PHP.

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

    На этот вопрос наверное только разработчики PHP смогут ответить и то не всякий, кто участвовал в разработке. Версий PHP уже было много, что-то в процессе могло поменяться в логике. Полной картиной только старожилы могут обладать, которые участвовали в разработке всех версий PHP и находятся в здравом уме и твердой памяти :-)

    Исходный код открыт, можно в нем поискать :-)
    Ответ написан
    Комментировать
  • Как задать множество переменным одинаковое значение?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Для этого проще массивы использовать:

    $per = [0, 1, 2, 3, 4, 5];
    
    for ($i = 0; $i < count($per); $i++) 
    {
      $per[$i] = 0;
    }

    Если массив нужно просто обнулить, то проще удалить его (unset($per)) и создать новый.

    Если хочется по извращаться с именами переменных, то можно так:

    // предполагается наличие переменных $per1, $per2 ... $per24
    // если переменных в наличии не будет, то они будут созданы :-)
    for ($i = 1; $i <= 24; $i++) 
    {
      ${'per'.$i} = 0;
    }
    Ответ написан
    Комментировать
  • Как сделать конструктор класса правильно?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Обычно это делается в отдельном методе, наподобие Save.

    У пользователя, которого нет в базе, $this->id будет нулевым.

    И для загрузки данных лучше сделать отдельный метод - Load.

    public function __construct($id = NULL)
    {
      $this->id = $id;
      $this->Load();
    }
    
    public function Load()
    {
      // идентификатор не указан, загружать данные не нужно
      if (!isset($this->id) || (int)$this->id == 0)
      {
        return false;
      }
    
      // указан идентификатор, загружаем данные в текущий экземпляр класса
      $mysqli = db_connect();
    
      $req = 'SELECT u.ID, u.name, u.age, u.city_id, c.city_name FROM users AS u '.
             'INNER JOIN cities AS c ON (c.city_id = u.city_id) '.
             'WHERE u.ID = '.$this->id; // опасно так передавать в запрос данные
    
      $res = $mysqli->query($req);
    
      if ($res !== false){
        if ($res->num_rows == 1 )
        {
          // смысла в цикле нет, ожидается ведь одна строка данных
          while ($row = $res->fetch_assoc())
          {
            $this->id = $row['ID'];
            $this->username =  $row['name'];
            $this->city_name = $row['city_name'];
            $this->city_id = $row['city_id'];
            $this->age = $row['age'];
          }
        }
        else
        {
          return false;
        }
      }
      else
      {
        return false;
      }
    }
    
    public function Save()
    {
      $sql = '';
      $params = [];
    
      if (!isset($this->id) || (int)$this->id == 0)
      {
        // запрос на добавление данных в базу
        $sql = 'INSERT INTO users (name, city_id, age) VALUES (?, ?, ?)';
        // параметры запроса
        $params = [$this->username, $this->city_id, $this->age];
      }
      else
      {
        // запрос на обновление данных в базе
        $sql = 'UPDATE users SET name = ?, city_id = ?, age = ? WHERE ID = ?';
        // параметры запроса
        $params = [$this->username, $this->city_id, $this->age, $this->id];
      }
    
      // код выполнения запроса
      // не могу быть уверен в коде, давно не писал и проверять лень
      // должно быть что-то типа такого:
    
      $mysqli = db_connect(); // лучше сделать отдельный метод для создания и закрытия соединений
    
      // подготавливаем запрос
      $s = $mysqli->prepare($sql);
    
      // выполняем запрос с указанными параметрами
      $s->execute($params);
    
      // тут еще неплохо бы закрыть все соединения :-)
    }

    Можно пойти дальше и сделать базовый класс, который будет содержать готовые методы Load и Save.
    Либо сделать отдельный класс, который будет получать данные и заполнять экземпляры классов этими данными, сохранять и удалять данные. В таком случае классы таблиц (сущности) будут просто описывать структуру данных в базе и не будут выполнять никаких действий. Этот вариант мне нравится больше, т.к. он чище (проще) и более гибкий.

    Придется придумать, как сопоставлять данные, если имена свойств не соответствую именам полей в базе. Скорее всего интерфейсы нужно будет использовать. Также учесть свойства, которые не определены в базе (которые следует игнорировать).

    Для работы со структурой классов потребуется использовать Reflection.
    В общих чертах примерно следующим образом:

    // создаем экземпляр класса User
    $instance = new User();
    
    // получаем информацию об экземпляре класса
    $r = new \ReflectionClass($instance);
    
    // получаем список публичных свойств
    $propeties = $r->getProperties(\ReflectionProperty::IS_PUBLIC);
    
    // перебираем все свойства
    foreach ($propeties as $property)
    {
      // получаем имя свойства
      $propertyName = $property->getName();
      // получаем значение свойства
      $propertyValue = $property->getValue();
      // и далее можно использовать полученную информацию
      // для формирования динамических запросов к базе
    
      // полученные из базы данные можно передать в нужные свойства
      $property->setValue("значение из базы");
    }

    Готовое решение найти будет проще :-)
    Ответ написан
    1 комментарий
  • Как вырезать из строки слово?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Разобрать URL можно с помощью функции parse_url.
    Получить отдельные параметры строки запроса можно методом parse_str.

    $url = 'http://blog.des/?go=category&q=backend&page=2';
    // в элементе с именем query будет строка параметров запроса
    // go=category&q=backend&page=2
    $query = parse_url($url)['query'];
    // функция parse_str разберет строку параметров запроса
    // и передаст ассоциативный массив в переменную $params
    parse_str($query, $params);
    // выводим значение параметра page
    echo $params['page'];

    Либо можно сразу в parse_str передавать URL:

    $url = 'http://blog.des/?go=category&q=backend&page=2';
    parse_str($url, $params);
    echo $params['page'];

    Если вы хотите получить значение параметра для текущей страницы, то проще это делать через $_GET:

    echo 'Текущая страница: '.$_GET['page'];

    Удалить параметр из строки запроса можно просто собрав новую строку, опустив не нужные параметры. Для текущего адреса примерно так:

    $queryString = [];
    
    foreach ($_GET as $key => $value) {
      // если параметр page, пропускаем его
      if ($key == 'page') { continue; }
      // остальные добавляем в queryString
      $queryString[$key] = $value;
    }
    
    // собираем массив новых параметров в строку параметров запроса
    $queryString = http_build_query($queryString);
    
    // новые параметры
    echo $queryString;

    Получив новую строку параметров, можно сформировать новый URL и выполнить перенаправление на него:

    $url = "http://blog.des/";
    
    if ($queryString != '')
    {
      $url .= "?".$queryString;
    }
    
    // это следует делать до первого вывода, иначе могут быть ошибки/предупреждения
    header('HTTP/1.1 301 Moved Permanently');
    header('Location: '.$url);
    Ответ написан
    2 комментария
  • Как добавить php код в страницу html?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Получить в переменную обработанное содержимое PHP файла можно примерно так:
    <?php
    function GetContents($path)
    {
      ob_start();
      require($path);
      $result = ob_get_contents();
      ob_end_clean();
    
      return $result;
    }
    
    $jumi1= GetContents('admin/jumi/jumi1.php');
    ?>

    Если открыть код, то есть строчка <? include('admin/jumi/jumi1.php'); ?>.
    Но она не отображается при открытии страницы и php не выполняется.

    Если вообще никакой код не работает, то вероятно короткая форма записи (<? ?>) тегов PHP не включена. Нужно использовать полную форму:

    <?php include('admin/jumi/jumi1.php'); ?>

    Либо проблема с путями:

    <?php include($_SERVER['DOCUMENT_ROOT'].'/admin/jumi/jumi1.php'); ?>

    Если есть доступ к журналу, в нем можно узнать подробности проблемы.

    Если вы пытаетесь заставить работать код PHP на странице HTML (*.html), то необходимо настроить веб-сервер, чтобы он файлы с расширением .html обрабатывал как файлы .php, но лучше так не делать и ограничиться использованием PHP в файлах .php.
    Ответ написан
    Комментировать
  • Как вставить php в путь ссылки?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Лучше относительно корневого каталога делать:
    <link rel="stylesheet" href="/main.css">
    Ответ написан
    Комментировать
  • Зачем нужна отладка с брейкпоинтами?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Редко работаю с PHP. Механизмы отладки ужасные, зачастую их нужно самих отлаживать :-)

    Использование точек останова (breakpoints) существенно упрощает процесс отладки, поиска ошибок. В C# я иногда пишу код в режиме отладки, останавливая выполнение программы в нужном месте, вношу изменения или даже пишу существенные объемы кода с нуля, перемещаю управление в нужное место и могу тут же посмотреть, что получится, без лишних движений. Не видел подобного в PHP и сомневаюсь, что это возможно. Но даже обычный просмотр состояния переменных и объектов поможет сэкономить время. Без этого придется писать код вывода состояния через var_dump, print_r или echo, засорять вывод, ломать глаза. Придется прыгать между редактором кода и браузером, тратить драгоценные доли секунд за всякую ерунду с риском допустить еще большее количество ошибок.

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

    Поставил точки останова, посмотрел какое значение на каждом шаге имеет переменная с обработанным текстом. Определил потенциальное место ошибки. Поставил больше точек в этом месте и посмотрел детально. Оказалось, что проблема в работе функции preg_replace. Поскольку с PHP я работаю редко и все забыл, то не смог бы сразу написать правильный шаблон, так что пришлось провести эксперименты непосредственно в точке останова. Сделал остановку в проблемном месте, открыл окно быстрой проверки (у меня Visual Studio) и прям в режиме реального времени опробовал разные варианты использования функции preg_replace с теми данными (переменными), которые находились в памяти. Получив нужный результат, заменил проблемный фрагмент кода. Всё, проблема решена. Быстро и просто, без лишних движений в коде.
    Ответ написан
    6 комментариев
  • Как убрать символ переноса строки?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Пропустить через trim.

    $command_script = "create_first_file.sh $this->server_user_name " .
                      trim($id_app) . " index$type_ex_file";


    Откуда берется лишний перевод строки, сказать сложно. Нужно в живую смотреть :-) Не припомню подобного поведения с формами в PHP. Может проблема во входящих данных ($data->id). Кстати, точка с запятой там лишняя, достаточно: <?=$data->id?>.

    Или же данные меняются где-то между отправкой и передачей в $id_app.

    Точки останова можно расставить и посмотреть, что происходит.
    Ответ написан
    2 комментария
  • Пауза в цикле Foreach?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    for($i = 1; $i < 100; $i++)
    {
      echo "элемент_$i<br />";
    
      // делаем паузу, если текущий индекс делится на 10 без остатка
      // т.е. каждый 10 элемент будет пауза
      if (($i % 10) == 0)
      {
        echo "пауза 3 секунды :)";
        sleep(3);
      }
    
    }

    Для foreach придется счетчик делать (типа $i). Но если такая необходимость возникнет, то по возможности лучше использовать обычный цикл.

    UPD: В соответствии с обновлением текста вопроса:
    for($i = 0; $i < 100; $i++)
    {
      // каждые два элемента помещаем в div
      if (($i % 2) == 0)
      {
        if ($i != 0) 
        {
          // закрываем предыдущий блок, если это не первый блок
          echo "</div>";
        }
        // открываем блок
        echo "<div class='exmpl'>";
      }
      // выводим элемент
      echo "<span> элемент_массива_$i</span><br />";
    }
    // закрываем последний блок
    echo "</div>";

    Возможно, через переменную формировать вывод будет проще:
    $output = "";
    for($i = 0; $i < 100; $i++)
    {
      // каждые два элемента помещаем в div
      if ($i != 0 && ($i % 2) == 0)
      {
        // выводим
        echo "<div class='exmpl'>$output</div>";
        // обнуляем
        $output = "";
      }
      // добавляем элемент в очередь на вывод
      $output .= "<span> элемент_массива_$i</span><br />";
    }
    // выводим остатки
    echo "<div class='exmpl'>$output</div>";
    Ответ написан
    4 комментария
  • Ассоциативный массив как свойство объекта в PHP?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Вроде все работает:
    80adf4323aff4915b5bf94ebcd3438c1.png

    В каком состоянии находится $domains_ip на момент добавления данных?
    function get_ip($domain)
    {
      $ip = gethostbyname($domain);
    
      var_dump($this->domains_ip);
    
      if (!is_array($this->domains_ip))
      {
        echo 'domains_ip не является массивом!';
      }
    
      $this->domains_ip[$ip] = $domain;
      return $ip;   
    }

    Что происходит после добавления?
    function get_ip($domain)
    {
      $ip = gethostbyname($domain);		
      $this->domains_ip[$ip] = $domain;
    
      var_dump($ip);
      var_dump($this->domains_ip);
    
      return $ip;      
    }

    Что будет, если массив объявить вот так:
    private $domains_ip = [];
    Ответ написан
    7 комментариев
  • Как php ssh2 диалоги команд?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    sudo можно настроить, чтобы он не требовал пароль для определенных пользователей или групп пользователей.

    sudo visudo

    либо:

    sudo nano /etc/sudoers

    где nano - текстовой редактор, можно использовать любой. (через visudo безопасней, т.к. программа проверяет наличие ошибок, перед заменой основного файла конфигурации)

    В конец файла добавить строку:

    имяПользователя ALL=(ALL) NOPASSWD:ALL

    Для групп, перед именем следует указывать символ процента (%). Например, %admin - правило для группы admin.

    Затем перезапустить sudo:

    sudo service sudo restart

    После этого, для указанного пользователя пароль запрашиваться не будет.

    Запись лучше добавлять в конец файла, чтобы разрешающее правило не пересеклось с запрещающими/ограничивающими (иначе не будет работать).
    Ответ написан
    Комментировать
  • Как указать корень локального сайта?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Указать mysite.ru.local в файле конфигурации сайта:
    <VirtualHost 127.0.0.1:80>
      DocumentRoot /home/mysite.ru/www
      ServerName mysite.ru.local
      # ServerAlias mysite.ru
      # ...все остальное...
    </VirtualHost>

    Чтобы в браузере сайт открывался по указанному адресу, можно прописать его в файле hosts.

    Под Linux см. файл /etc/hosts.
    Под Windows см. C:\Windows\System32\drivers\etc\hosts.
    (с правами администратора)

    В файл hosts нужно указать имя хоста и IP сервера. Например:

    127.0.0.1 mysite.ru.local

    Вместо .local лучше использовать другую зону, т.к. с .local могут быть проблемы. Можно просто mysite, либо mysite.serverName.
    Ответ написан
    Комментировать