Задать вопрос
Ответы пользователя по тегу PHP
  • Безопасный интерпретатор пользовательской логики (кода)?

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    Понятно, что "по феншую" надо вывести универсальный набор параметров, подходящий для любой логики

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

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

    Это возможно только в случае, если "любая задача" - это одна из реализованных задач.

    при этом соблюсти безопасность при выполнении этого кода

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

    наверняка, есть какие-то готовые инструменты для подобной задачи

    Нанимается инженер, который решает задачи изменения ПО под ваши нужды.

    А на что еще стоит посмотреть?

    На переосмысление задачи. Сейчас вы на пороге выстрела себе в ногу.
    Ответ написан
  • Как правильно написать маршрутизация на php с регулярными выражениями?

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    1. Что такое роут?
    Это некая сущность, умеющая проверять, подходит ли она для запроса, или нет.
    2. Что такое роутер?
    Это объект, умеющий выбирать подходящий роут по запросу и возвращать его.

    Рекомендую создать:
    1. RouteInterface с методами: supports(Request $request): bool
    2. Создайте интерфейс RequestRunnerInterface: run(Request $request): Response
    3. Создайте RegExpRoute, который будет уметь по регулярке проверять запрос. Там же имплементируйте оба интерфейса.
    4. Создайте Router, в который можно будет по интерфейсу насетапать роуты
    5. Процесс выполнения будет примерно такой:
    - создать объект Request
    - насетапать роуты
    - занести роуты в роутер
    - получить роут по запросу
    - для роута с имплементацией 2-го интерфейса выполнить run
    - отрендерить ответ
    - завершить выполнение

    НЕ используйте глобальные и суперглобальные переменные, начале выполнения создайте HttpFoundation Request и работайте с ним.
    Ответ написан
  • Существуют ли сервисы просмотра php кода сайта?

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    Gitlab/github/bitbucket
    Ответ написан
    Комментировать
  • Как узнать сколько тактов уходит на исполнение чего ни будь написанного на PHP?

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    Как узнать, сколько литров бензина уходит на преодоления какого ни будь пространства на фольксвагене?
    Ни модели машины, ни дорог, ни погодных условий вам не дано))

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

    Что касается самих опкодов - можете покурить https://derickrethans.nl/projects.html#vld на досуге, как пример, это выглядит так: https://3v4l.org/Zu5rp/vld#output

    Если же вам нужно оптимизировать производительность - xhprof ваше все.
    Ответ написан
    Комментировать
  • Можно ли получить public переменную не инициализируя сам класс?

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    нет, при условии, что она не статическая
    Ответ написан
    3 комментария
  • Как правильно использвать базы данных на странице php?

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    в каком месте нужно закрывать соединение с БД?

    Перед завершением процесса. Хотя оно и так закроется.

    В каждом методе?

    Нет, постоянные реконнекты будут дорого стоить.

    --- Немножко Code Review ---

    // Не давайте общие имена конкретным реализациям
    // Почитайте, проникнитесь и используйте PSR-2 и PSR-4
    class DataBase
    {
        private $mysqli;
        private $dbConfig;
    
        public function __construct()
        {
    // Класс по работе с БД не должен знать даже о существовании неких файлов, где-то там. Это не его забота.
    // Передавайте в конструктор готовое подключение к БД, если нужно.
            $this->dbConfig = require "db/database_config.php";
    // Вот никак понять не могу, за что так любят этот mysqli, ну что в нем прям такого раз такого, по сравнению с PDO?
            $this->mysqli = mysqli_connect($this->dbConfig['host'], $this->dbConfig['username'], $this->dbConfig['password'], $this->dbConfig['db_name']);
    // Почему вдруг класс по работе с БД занимается операцией вывода?
    // Если что-то не так - бросайте исключение, ни каких echo, die, exit, trigger_error
            if (mysqli_connect_errno($this->mysqli)) {
                echo "Не удалось подключиться к MySQL: " . mysqli_connect_error();
            }
        }
    // Вы не проверяете аргументы, это плохо, очень.
    // Что бы нагнуть ваш проект достаточно передать в любой из аргументов: '1; DROP TABLE employees;'
      public function getEmployees($where='1',$start, $perPage){
    // ЗАБУДЬТЕ про подстановку данных через конкатенацию, используйте плейсхолдеры
    // http://php.net/manual/ru/pdo.prepared-statements.php
            $sql="SELECT e.name,e.birthday,d.title_dep,p.title_pos,t.title_type,e.salary FROM `employees` AS e INNER JOIN departments AS d ON e.id_dep=d.id
    INNER JOIN positions AS p ON e.id_pos=p.id
    INNER JOIN payment_types AS t ON e.id_type=t.id  where $where LIMIT $start,$perPage";
    
    // Вам ни переменная $res, ни $row не нужны
            $res = $this->mysqli->query($sql);
            $row=$res->fetch_all(MYSQLI_ASSOC);
            return $row;
        }
    }
    Ответ написан
    2 комментария
  • Возможно ли написать универсальный обработчик форм?

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    Это бессмысленно. Чем универсальнее будет ваш обработчик - тем сложнее будет им пользоваться. Что произойдет, когда данные будут отправляться в виде json например, а не url-кодированной строки?

    Вместо этого рекомендую следующий подход

    use Symfony\Component\HttpFoundation\Request;
    
    class LoginForm
    {
        /** @var string */
        private $login;
        /** @var string */
        private $password;
    
        /**
         * @param Request $request
         */
        public function __construct(Request $request)
        {
            $login    = $request->request->get('login');
            $password = $request->request->get('password');
    
            if (is_null($login)) {
                throw new \InvalidArgumentException('Parameter "login" is required');
            } elseif (!is_string($login)) {
                throw new \InvalidArgumentException('Parameter "login" must be string');
            } elseif (strlen($login) < 3) {
                throw new \InvalidArgumentException('Length of parameter "login" must be greater than 3');
            } elseif (strlen($login) > 64) {
                throw new \InvalidArgumentException('Length of parameter "login" must be less than 64');
            } elseif (preg_match('/^[a-z\d]+$/i', $login) === 0) {
                throw new \InvalidArgumentException('Parameter "login" contain not allowed symbols');
            }
    
            if (is_null($password)) {
                throw new \InvalidArgumentException('Parameter "password" is required');
            } elseif (!is_string($password)) {
                throw new \InvalidArgumentException('Parameter "password" must be string');
            } elseif (strlen($password) < 6) {
                throw new \InvalidArgumentException('Length of parameter "password" must be greater than 6');
            }
    
            $this->login    = $login;
            $this->password = $password;
        }
    
        /**
         * @return string
         */
        public function getLogin(): string
        {
            return $this->login;
        }
    
        /**
         * @return string
         */
        public function getPassword(): string
        {
            return $this->password;
        }
    }


    Да, кода получается много, но вы гарантировано получаете корректные данные с помощью геттеров. Если нужно будет создавать некие DTO, или VO - прямо в конструкторе это можно сделать. Такой класс прост в тестировании и поддержке.
    Ответ написан
  • Грамотно-ли написан класс работы с БД?

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    Используйте доктрину DBAL для начала, если будет мало - ORM.

    -- Немножко Code Review --
    // Используйте PSR-2. Стандарт оформления кода не просто так придуман.
    // Кстати, это MySQL БД, или PostgreSQL, или sqlite? Не стоит давать общие имена для конкретных реализаций.
    class DataBase {
    // Достаточно такого:
    // /** @var \PDO */
    // private $connection;
        private $connectDataBase;
    
        // конструкция подключения к БД
        function __construct () {
    // Вот никак не могу понять, чего народ так упорно  mysqli любит, ну что там такого прям раз такого, по сравнению с PDO?
    // Передавайте готовое подключение в конструктор, а не создавайте его там.
            $this->connectDataBase = new mysqli(DB_HOST, DB_USERNAME, DB_PASSWORD, DB_DATABASE);
            if ($this->connectDataBase->connect_errno) {
    // С какого класс по работе с БД управляет процессом и выводом? Если что-то пошло не так - бросайте исключение. Конструкцию die - забудьте.
                die('Connect Error (' . $this->connectDataBase->connect_errno . ') ' . $this->connectDataBase->connect_error);
            }
        }
    
    // Не пишите бесполезных комментариев
        // метод подготовленного запроса к базе
        function query ($sql) {
    // Зачем вам переменная $result?
            $result = $this->connectDataBase->query($sql);
            return $result;
    
        }
    
    }
    Ответ написан
    2 комментария
  • Куда правильнее поместить и как назвать файл с функциями?

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    Существует. Откажитесь от функций и суффиксов .class.php. Прочитайте про PSR-4 и пользуйтесь им вместе с composer
    Ответ написан
    Комментировать
  • Как не начать говн*кодить?

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    Попробуйте следовать этим требованиям и ваш код будет далеко не совсем говном.
    Ответ написан
    Комментировать
  • Почему не работает require_once?

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    {} - для получения элемента массива, так не пишут.
    Не используйте суперглобальные переменный там, где в этом нет необходимости. Есть замечательная константа __DIR__, используйте ее
    Ответ написан
    Комментировать
  • Проясните проблему с автозагрузкой composer?

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    разве Composer не должен автоматически это делать?

    Если автор библиотеки не умеет пользоваться композером - то это не проблема композера.

    Если автолодер в подключаемой библиотеке не настроен, но она капец как вам нужна - пропишите автолоадинг для классов этой библиотеки в своем composer.json.
    Ответ написан
    Комментировать
  • Статические классы и синглтоны?

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    Но вопрос в том что все это по сути не имеет смысла потому что при каждом запросе к серверу будет заново создаваться синглтон

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

    Возможно ли как то изменить это поведение или хотя бы закэшировать данные?

    memcache, redis, xcache, apcu,... выбирайте

    У меня в xml файле хранятся какие-то настройки.

    Как минимум можете перевести xml в php код, который в свою очередь закешируется через opcache. При следующем запросе этот код будет браться из пямяти.

    Самый логичный способ использовать для такой цели статический класс или синглтон.

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

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    Вы пытаетесь отстрелить себе яйцы, причем баллистической ракетой.

    1. Скачиваете файл
    2. Сохраняете его во временный файл
    3. require-ите его
    4. Удаляете временный файл
    Ответ написан
  • Нововведения в php, использование?

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    Дык уже ж на обсуждении, PSR-12
    Ответ написан
    Комментировать
  • Что стоит изменить в классе PHP для работы с файлами?

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    Конкретно по коду отписал ниже. Как хелпер - ну может быть, почитайте на досуге php.net/manual/ru/spl.files.php
    // Я надеюсь вы знаете про PSR4 и символ подчеркивания тут случайно
    class MV_Files
    {
        // PSR2: методы пишутся в lowerCamelCase
        // Нет проверки аргументов. что произойдет, если $name будет массивом?
        // Не ясно, на кой вам тут возврат bool? Если что-то не так - бросайте исключение.
        public function CreateFile($path, $name, $right = 0777)
        {
            if (!file_exists($path . '/' . $name)) {
                // Посмотрите http://php.net/manual/ru/function.touch.php
                fclose(fopen($path . '/' . $name, 'w'));
                chmod($path . '/' . $name, $right);
                // PSR2: Перед return перевод строки
                return true;
                // Не ясно, зачем вам тут else?
            } else {
                return false;
            }
        }
    
        // PSR2: методы пишутся в lowerCamelCase
        // Нет проверки аргументов. что произойдет, если $name будет массивом?
        // Не ясно, на кой вам тут возврат bool? Если что-то не так - бросайте исключение.
        public function CreateFileContent($path, $name, $text, $right = 0777)
        {
            if (!file_exists($path . '/' . $name)) {
                // file_put_contents, не?
                $file = fopen($path . '/' . $name, 'w');
                fwrite($file, $text);
                fclose($file);
                chmod($path . '/' . $name, $right);
                // PSR2: Перед return перевод строки
                return true;
                // Не ясно, зачем вам тут else?
            } else {
                return false;
            }
        }
    
        // PSR2: методы пишутся в lowerCamelCase
        // Нет проверки аргументов. что произойдет, если $path будет массивом?
        // Не ясно, на кой вам тут возврат bool? Если что-то не так - бросайте исключение.
        public function AddFileContent($path, $text)
        {
            if (file_exists($path)) {
                // file_put_contents($path, $content, FILE_APPEND)
                $file = fopen($path, 'a');
                fwrite($file, $text);
                fclose($file);
                // PSR2: Перед return перевод строки
                return true;
                // Не ясно, зачем вам тут else?
            } else {
                return false;
            }
        }
    
        // PSR2: методы пишутся в lowerCamelCase
        // Нет проверки аргументов. что произойдет, если $path будет массивом?
        // Не ясно, на кой вам тут возврат bool? Если что-то не так - бросайте исключение.
        public function OverwriteFileContent($path, $text)
        {
            if (file_exists($path)) {
                // file_put_contents($path, $content)
                $file = fopen($path, 'w');
                fwrite($file, $text);
                fclose($file);
                // PSR2: Перед return перевод строки
                return true;
                // Не ясно, зачем вам тут else?
            } else {
                return false;
            }
        }
    
        // PSR2: методы пишутся в lowerCamelCase
        // Нет проверки аргументов. что произойдет, если $oldname будет массивом?
        // Не ясно, на кой вам тут возврат bool? Если что-то не так - бросайте исключение.
        // Чего вдруг метод статический?
        public static function RenameFile($oldname, $newname) {
            if (file_exists($oldname)) {
                return rename($oldname, $newname);
            } else {
                return false;
            }
        }
    
        // PSR2: методы пишутся в lowerCamelCase
        // Нет проверки аргументов. что произойдет, если $path будет массивом?
        // Не ясно, на кой вам тут возврат bool? Если что-то не так - бросайте исключение.
        public function DeleteFile($path)
        {
            if (file_exists($path)) {
                return unlink($path);
            } else {
                return false;
            }
        }
    
        // Нет проверки аргументов. что произойдет, если $path будет массивом?
        // Не ясно, на кой вам тут возврат bool? Если что-то не так - бросайте исключение.
        public function getFileContent($path)
        {
            if (file_exists($path)) {
                return file_get_contents($path);
            } else {
                return false;
            }
        }
    
        // Нет проверки аргументов. что произойдет, если $path будет массивом?
        // Не ясно, на кой вам тут возврат bool? Если что-то не так - бросайте исключение.
        // "size" обычно трактуется как число, а не форматированная строка.
        public function getFileSize($path)
        {
            if (file_exists($path)) {
                // Конструкция - гавно)). Если хотите интовый $size - то сохраняйте в него инт
                (int)$size = filesize($path);
                switch (true) {
                    case $size >= 1073741824:
                        $size = round($size / 1073741824 * 100) / 100 . ' GB';
                        break;
                    case $size >= 1048576:
                        $size = round($size / 1048576 * 100) / 100 . ' MB';
                        break;
                    case $size >= 1024:
                        $size = round($size / 1024 * 100) / 100 . ' KB';
                        break;
                    default:
                        $size .= ' Bytes';
                        break;
                }
                return $size;
            } else {
                return false;
            }
        }
    
        // Нет проверки аргументов. что произойдет, если $path будет массивом?
        // Не ясно, на кой вам тут возврат bool? Если что-то не так - бросайте исключение.
        // Прочитайте http://php.net/manual/ru/class.splfileinfo.php
        public function getFileInfo($path)
        {
            if (file_exists($path)) {
                return pathinfo($path);
            } else {
                return false;
            }
        }
    
        // Нет проверки аргументов. что произойдет, если $dirname будет массивом?
        // Прочитайте http://php.net/manual/ru/class.directoryiterator.php
        public function getFileList($dirname)
        {
            $dir = array_diff(scandir($dirname), ['.', '..']);
            $files = [];
            // Рекомендую перед управляющими конструкциями делать перевод строки, так читать проще
            foreach ($dir as $value) {
                if (is_file($value)) {
                    $files[] = $value;
                }
            }
            // PSR2: перед return перевод строки
            return $files;
        }
    // Лишний перевод строки
    }
    Ответ написан
    2 комментария
  • Switch с нулевым условием в php?

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    Вы сравниваете красное и мягкое (int с bool), понятное дело, что результат будет не очевидным)). По сути вы сравниваете примерно так:echo 0 == (0 >= 1073741824);
    Ответ написан
    3 комментария
  • Правильно ли я понимаю принцип модульной архитектуры приложения?

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    Зависит от проекта конечно, но в понятие модуль обычно вкладывается что-то очень больше и независимое, например система управления пользователями, система управления платежами и т.д. В терминологии Symfony - это называется Bundle.

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

    А если мне нужно написать модуль регистрации пользователя? Как здесь быть?

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

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

    З.Ы. Битрикс и "качественная архитектура" - это вещи не совместимые))
    Ответ написан
    Комментировать