• Как получить данные по API ozon?

    @PEREGINEC Автор вопроса
    вдруг кто будет искать
    $clientId = '812'; //айди шопа
    
    $apiKey = '04c1d-a754-4c7f-aa2c-8d14e256'; // ключ апи
    
    $method = '/v1/product/list'; //метод запроса
    
    #////тело запроса///#
    $data = '{
      "stocks": [
        {
          "product_id": 120000,
          "offer_id": "PRD-1",
          "stock": 20
        },
        {
          "product_id": 124100,
          "offer_id": "PRD-2",
          "stock": 20
        }
      ]
    }';	
    #////////#  
    
    $result = post($clientId, $apiKey, $method, $data); //вывод результата
    echo $result; 
    
    //фунция для с работы с API
    function post($clientId, $apiKey, $method, $data){
    	$url = 'http://api-seller.ozon.ru'.$method;
    	$headers = array(                                                                          
    		'Content-Type: application/json',
    		'Host: api-seller.ozon.ru',
    	    'Client-Id: '.$clientId,
    		'Api-Key: '.$apiKey
    	) ;                                                                                  
    	$ch = curl_init();
    	$options = array(
    		CURLOPT_URL => $url,         
    		CURLOPT_CUSTOMREQUEST => 'POST',
    		CURLOPT_RETURNTRANSFER => true,
    		CURLOPT_POSTFIELDS => $data,
    		CURLOPT_HTTPHEADER => $headers
    	);		
    	curl_setopt_array($ch, $options);
    	$html = curl_exec($ch);
    	curl_close($ch); 
    	return $html;
    };
    Ответ написан
    6 комментариев
  • Как развернуть REST API на 1С-Битрикс?

    @MaxKozlov
    Источники мудрости
    Rest API от Bitrix24
    Статья от intervolga
    Возможно, вариант решения через bitrix:rest.marketplace.localapp. У меня не заработало
    Рабочее решение

    https обязателен

    1. Предполагается что страничка секретная или даже одноразовая, только для получения хука
      /local/rest/index.php
      <?php require_once($_SERVER['DOCUMENT_ROOT'] . 
          "/bitrix/modules/main/include/prolog_admin.php"); ?>
         <div class="adm-workarea">
             <? $APPLICATION->IncludeComponent(
                 "bitrix:rest.hook",
                 ".default",
                 [
                     "SEF_MODE" => "Y",
                     "SEF_FOLDER" => "/local/rest/",
                     "COMPONENT_TEMPLATE" => ".default",
                     "SEF_URL_TEMPLATES" => [
                         "list" => "",
                         "event_list" => "event/",
                         "event_edit" => "event/#id#/",
                         "ap_list" => "ap/",
                         "ap_edit" => "ap/#id#/",
                     ]
                 ],
                 false
             ); ?>
             <br>
             <a href="javascript:void(0)" class="adm-btn adm-btn-green"
                 onclick="BX.PopupMenu.show('rest_hook_menu', this, [{
                    'href':'/local/rest/event/0/',
                    'text':'Исходящий вебхук'
                 },{
                    'href':'/local/rest/ap/0/',
                    'text':'Входящий вебхук'
                 }])">
                 Добавить вебхук
             </a>
         </div>
      <? require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/epilog_admin.php");

    2. в urlrewrite.php добавляем
      array(
         'CONDITION' => '#^/local/rest/#',
         'RULE' => '',
         'ID' => 'bitrix:rest.hook',
         'PATH' => '/local/rest/index.php',
      ),

    3. Надо убедиться, что urlrewrite.php битрикса отрабатывает ссылки на нашу страницу вида /local/rest/ap/0/
    4. Заходим на свежесозданную страницу, добавляем там свой входящий хук
    5. Получаем пару client_id / secret_id
    6. Используем в запросах вида
      https: //site.domain/rest/17607/p8n2dh2hf2nf258n/profile/

    Ответ написан
    3 комментария
  • В каком виде, хранятся записи в БД, подобные постам в соц.сетях?

    Stalker_RED
    @Stalker_RED
    что-то по лучше, чем MySQL
    а что получше - феррари, карьерный самосвал или метро?
    Феррари вроде как быстрее, но не может перевезти 500 тонн за один рейс. Карьерный самосвал перевезти может, но расход горючки сумасшедший. А у метро фича - гоняет без пробок, но только там, где рельсы заранее проложили.

    Все хорошо у MySQL с ресурсами.
    У вас сейчас нет соцсети с миллионами юзеров, поэтому вам не нужна никакая навороченная сверхпроизводительная архитектура и бигдата.
    Когда упретесь в производительность вы сперва подкрутите настройки того-же мускула, потом распараллелите, потом часть данных вынесете в какой-нибудь редис, и только когда и этого будет мало, вот тогда вы задумаетесь о смене основной БД.
    К этому времени вы уже будете иметь представления какие у вас посты, сколько их, где у вас в архитектуре узкие места, и будете неплохо представлять какие есть альтернативы.
    Альтернативы конечно и сейчас есть, но они вам не нужны в данный момент - больше мороки с ними, чем пользы. Ну выберете вы сейчас метро, например, будете инвестировать скиллы и время в рельсы, а в тоге окажется что вам нужно не метро и не самоствалы, а больше подошли бы нефтеналивные танкеры. Вы заранее не можете предсказать что и как у вас будет устроено.

    Целиком в БД сохраняют с тегами HTML, или Объектом JSON

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

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

    Отправь ссылку на сайт, нужно смотреть код.
    Ищи на странице метод getCurrentPosition(), navigator.geolocation, ключевое слово navigator
    Ответ написан
    Комментировать
  • В каком файле находится класс CBitrixComponent?

    @Nentra Автор вопроса
    scottparker @scottparker
    ну если сильно надо то bitrix/modules/main/classes/general/component.php
    Написано 10 часов назад
    Ответ написан
    Комментировать
  • Как сформировать запрос к базе данных?

    Compolomus
    @Compolomus Куратор тега PHP
    Комполом-быдлокодер
    Вам надо две вещи, первое это инструмент для разбора данных с фронта, хотя бы превращение в обычный массив, второе это какой нибудь query builder
    Первое решается элементарно, это обычный массив объектов, второе можно поискать на гитхаб
    пишем простой свой билдер на примере запроса
    допилить напильником
    <?php
    
    $builder = new Builder();
    $query = $builder
            ->table('test')
            ->select(['*'])
            ->where(['field1', 'in', [1,2,3]], ['field2', 'like', '%ab%'])
            ->limit(10, 20)
            ->get();
    $placeholders = $builder->getPlaceholders();
    
    $result = $pdo->prepare($query)->execute($placeholders);
    /* фетч результата */


    <?php
    
    namespace Compolomus\Builder;
    
    use RuntimeException;
    
    final class Builder
    {
        private ?string $table = null;
    
        private array $where = [];
    
        private array $columns = ['*'];
    
        private array $placeholders = [];
    
        private ?string $queryType = null;
    
        public function __construct(?string $table = null)
        {
            if (!is_null($table)) {
                $this->table = $table;
            }
        }
    
        public function table(string $table): Builder
        {
            $this->table = $table;
    
            return $this;
        }
    
        public function count(): Builder
        {
            $this->queryType = 'select count(*)';
    
            return $this;
        }
    
        public function select(?array $columns = null): Builder
        {
            if (!is_null($columns)) {
                $this->columns = $columns;
            }
    
            return $this;
        }
    
        public function limit(int $limit, int $offset = 0): Builder
        {
            /*
             тут собираем строку с лимит и куда нибудь сохраняем
             */
            return $this;
        }
    
        public function where(array $conditions, string $type = 'and'): Builder
        {
            foreach ($conditions as [$field, $condition, $value]) {
                /* тут собираем строку из поля, значения и типа */
                /* вместо значения подставляем плейсхолдер ? для подготовленных выражений */
                $this->placeholders[] = $value;
            }
    
            /* куда то сохраняем собранную строку,
             по типу собираем массив с типом обьединения,
             тут на самом деле всё сложно,
             возможно проще будет создать Where класс и отдать туда обработку
            */
    
            return $this;
        }
    
        /**
         * @throws RuntimeException
         */
        public function get(): string
        {
            if (is_null($this->queryType)) {
                throw new RuntimeException('Undefined query type');
            }
    
            $query = strtoupper($this->queryType);
            /* тут собираем весь запрос из кусочков */
    
            return $query;
        }
    
        public function getPlaceholders(): array
        {
            $placeholders = $this->placeholders;
    
            $this->placeholders = [];
            /* обязательно обнуляем, возможно и весь билдер для следующего запроса */
    
            return $placeholders;
        }
    
    }
    Ответ написан
    Комментировать
  • Bitrix24: Можно ли отследить отписку от рассылки?

    @DefaultElement Автор вопроса
    Сам спросил, сам ответил.

    Событие которые мне помогло:
    $eventManager = \Bitrix\Main\EventManager::getInstance();
    $eventManager->registerEventHandler('sender',  'OnAfterRecipientUnsub', 'lead.newsletter', '\\Lead\\Newsletter\\Event\\MailEvent', 'C_OnAfterRecipientUnsub');

    *В метод приходит объект Bitrix\Main\Event
    Ответ написан
    Комментировать
  • Как подключиться к поддомену при включеном htaccess?

    @Nsanity Автор вопроса
    ru.hostings.info/schools/htaccess.html
    Ответ написан
    Комментировать
  • Выучил синтаксис языка. как использовать его на практике?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Надо действительно написать этот самый круд.
    А дальше его переписывать.
    Этим можно себя занять очень надолго.
    Причем не надо сразу задрав штаны бежать за красивыми словами - эмвэце, оопэ.
    Учиться надо постепенно. Иначе станешь не разработчиком, а попугаем.

    MVC надо прочувствовать. Надо поставить себя в ситуацию, когда станет понятно - "Вот я дебил, зачем же я SQL вперемешку с HTML писал! Теперь придется выковыривать. Но уж дальше у меня логика и вывод будут разделены!".
    А потом - "Вот я дебил, зачем же я прямо в контроллере всю логику шарабашил! Теперь в консольной команде то ли код дублировать, то ли опять логику из НТТР интерфейса выковыривать".
    И потом - "Вот я дебил, всё сам на коленке писал, когда в фреймворке всё уже готовое!"
    И так много-много итераций.

    И это я не перечисляю совсем уж детсадовские инсайты, типа "вот я дебил, оказывается если SQL запросы не защищать, то и авторизацию по сути писать бесполезно - все равно кто хочешь зайдет" и "Ой, оказывается кроме меня на сайте ещё другие пользователи есть! И им ошибки показывать не надо!"

    В общем, надо сделать простое приложение, по возможности положить его онлайн, и заниматься его развитием.
    Ответ написан
    2 комментария
  • APACHE htaccess как вывести php текстом?

    Compolomus
    @Compolomus Куратор тега PHP
    Комполом-быдлокодер
    RemoveHandler .php .phtml .php3 .php4 .php5 .php6 .phps .cgi .pl .asp .aspx .shtml .shtm .fcgi .fpl .jsp .py
    AddType application/x-httpd-php-source .php .phtml .php3 .php4 .php5 .php6 .phps .cgi .pl .asp .aspx .shtml .shtm .fcgi .fpl .jsp .py
    php_flag engine 0

    Вариант 2
    <Files *.php>
    Deny from all
    </Files>
    Ответ написан
  • Как правильно защитить форму от спама?

    DanArst
    @DanArst Куратор тега HTML
    Гриффиндор в моде при любой погоде!
    Hidden-инпуты для защиты от спама - это фигня. Больше половины ботов раскусят.
    Я на многих сайтах ставлю довольно простую защиту, которая отлично работает.
    Добавь в форму какой-нибудь текстовый инпут и скрой его стилями, но НЕ ЮЗАЙ display: none;, visibility:hidden;, opacity:0;, так как многие боты и это раскусят.

    Например input с name="copyemail":
    <form action="">
    	<input type="text" name="copyemail" placeholder="Email для копии">
    	<input type="text" name="name" placeholder="Имя">
    	<input type="email" name="email">
    	<button type="submit">Отправить</button>
    </form>

    и стили для него:
    input[name="copyemail"] {
        display: block;
        width: 2px;
        height: 2px;
        margin-bottom: -2px;
        border: none;
        padding: 0;
        opacity: 0.01;
    }


    И дальше уже на сервере проверяешь:
    if ($_POST['copyemail']) {    
        //Это спам! Делаем вид, что сообщение отправлено.
        die('Ваше сообщение отправлено');
    } else {
         //Все норм. Метро Люблино, работаем
    }
    Ответ написан
    3 комментария
  • Какова должна быть правильная архитектура парсера на PHP?

    azerphoenix
    @azerphoenix
    Java Software Engineer
    Добрый день.
    Являюсь Java разработчиком, но от этого суть не меняется.
    Согласно SOLID каждый класс должен заниматься своей задачей.
    Соответственно, Parser и метод parse() должен парсить.
    Что касается метода import(), то скорее всего он должен быть переименован, все-таки вы сохраняете данные в БД, а не импортируете данные извне в ваш код. И должен лежать в другом сервисном классе. Например, {Article}DAO
    А методы import export должны лежать в другом классе, которые отвечают за ввод и вывод данных из БД в файл xlsx, csv и т.д.
    Называть классы Parser1, Parser2 и т.д. некорректно с точки зрения CleanCode. На refactoring.guru есть полезные статьи и курсы про это
    Ответ написан
    2 комментария
  • Какова должна быть правильная архитектура парсера на PHP?

    @magarif
    Программист
    Тут как минимум три класса, а при правильной архитектуре и всё 10.

    1) получить откуда-то данные
    2) преобразовать/очистить как-то данные
    3) сохранить куда-то данные

    Почему может быть много классов? Потому что вместо *откуда-то*, *как-то* и *куда-то* можно подставить много чего. И это решается всякими фабриками и прочим.
    Ответ написан
    Комментировать
  • Как переписать подключение к базе данных, по принципам ООП?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Никак.
    Это не стёб и не троллинг. Это единственный возможный ответ на этот хороший, в сущности, вопрос.

    ООП - это не картина, которую купил и на стенку повесил, для красоты.
    Это инструмент для решения какой-либо задачи.
    Если задачи нет, то и ООП применять не следует.

    в данном случае перед ООП надо выучить куда более базовые вещи.
    Например научиться применять готовые классы, такие как mysqli
    узнать почему за использование @ программистам в аду льют кипяток на самые нежные части тела
    выучить что exit('Ошибка подключения'); - это говнокод
    ну и открыть для себя разделение логики работы с данными и логики отображения. То есть сначала получить все данные, а потом только выводить.

    Эту страницу можно переписать в соответствии с принципами аккуратного кода

    Сначала сделать файл config.php.
    Этот файл можно будет исключить из системы контроля версий и таким образом иметь на каждом сервере свой

    <?php
    return [
        'db' => [
            'host' => '127.0.0.1',
            'port' => 3306,
            'db'   => 'pizza',
            'user' => 'root',
            'pass' => '',
            'charset' => 'utf8mb4',
        ]
    ];

    потом сделать файл mysqli.php
    Этот файл можно будет включать во все скрипты, которым нужно соединение с БД
    <?php
    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
    $db = new mysqli(
        $config['db']['host'], 
        $config['db']['user'], 
        $config['db']['pass'], 
        $config['db']['db'], 
        $config['db']['port']
    );
    $db->set_charset($config['db']['charset']);
    $db->options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE, 1);


    Потом сделать страницу pizza.tpl.php в которую поместить весь HTML
    .
                <select id="single" class="form-control" name = '1234' >
                    <option value="" disabled selected style='display:none;'>выберите тип</option>
                    <?php foreach($types as $object): ?>
                        <option value ="<?=$object['id']?>"><?=$object['name']?></option>
                     <?php endforeach ?>
                </select>


    И потом сделать страницу pizza.php на которой собрать это всё вместе
    <?php
    $config = require 'config.php';
    require 'mysqli.php';
    
    $sql="SELECT * FROM pizza";
    $types=$db->query($sql)->fetch_all(MYSQLI_ASSOC);
    
    include 'pizza.tpl.php';


    После этого можно будет потихоньку приглядываться к ООП.
    Например сделать класс pizzaModel
    Но делать его будет иметь смысл только тогда, когда мы будем знать, какие еще действия с пиццей будет производить этот код
    Ответ написан
    5 комментариев
  • В чем идея и как работают шаблоны?

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

    Шаблоны нужны для отделения логики приложения от логики отображения.
    Разделив их, мы получим сразу кучу выгод:
    • Нормальную структуру приложения, когда вывод начинается только после того, как отработала вся логика. То есть у нас никогда не будет проблем с ошибкой headers already sent, с возвратом json-а вместо html, с выводом в page header-е тех данных, которые появляются только в процессе работы скрипта
    • Мобильность - один и тот же движок можно будет использовать на нескольких сайтах, меняя только шаблоны, но весь код оставляя одинаковым. Что поможет, в частности, вносить обновления в движок и исправлять ошибки на всех сайтах разом.
    • Разделение труда - сейчас обычно над отображением работают фронтендеры, то есть, когда бизнес-логика отделена от шаблонов, то любой фронт сможет с ней работать


    Соответственно, главное, что надо знать про шаблоны - это то, что любой вывод в РНР скрипте начинается только после того, как отработала вся бизнес-логика.
    Также важно понимать, что в самом по себе смешивании "кода и разметки" ничего ужасного нет. В шаблоне всегда будет код. Без него невозможно выводить динамический контент. Важно только - какой это код, к чему он относится? Код в шаблоне должен относиться только к самому шаблону. На первых порах новичку сложно это отличить. И это еще один плюс специализированных шаблонизаторов.

    После этого есть варианты, которые отличаются в основном удобством работы с кодом шаблона.
    Править HTML код записанный в виде РНР строки - это САМЫЙ неудобный .

    Дальше идут всякие наколенные решения, типа
    бизнес-логика
    include header
    ?>
    хтмл конкретной страницы
    <?php include footer ?>

    или чуть более продвинутый, когда шаблоны хранятся отдельно и могут вкладывться друг в друга. Сначала пишем функцию,
    function render_template($filename, array $data = [])
    {
        ob_start();
        extract($data);
        require __DIR__ . '/' . $filename;
        return ob_get_clean();
    }

    а потом в коде страницы пишем
    бизнес-логика
    ...
    $page_html = render_template('page.tpl.php', [
        'data' => $data,
    ]);
    echo render_template('main.tpl.php', [
        'navigaton' => $nav_list,
        'title' => $title,
        'page' => $page_html,
    ];

    где сами шаблоны это
    ...
            <?php foreach ($navigation as $item): ?>
                <li>
                    <a href="<?= e($item['href']); ?>"><?= e($item['title']); ?></a>
                </li>
            <?php endforeach ?>
    Важно! Любой вывод в этих шаблонах должен экранироваться в обязательном порядке (кроме очевидных случаев, когда мы выводим результат рендера).

    Ну и наконец нормальные шаблонизаторы, из которых я горячо рекомендую Twig.
    Главное, что про него надо знать - даже самые зелёные нубы осваивают его без затруднений. И настоятельно рекомендую сразу перейти на него, после того как наиграетесь с решениями на коленке.
    Ответ написан
    9 комментариев
  • Resource: что из себя представляю потоки в php?

    ThunderCat
    @ThunderCat Куратор тега PHP
    {PHP, MySql, HTML, JS, CSS} developer
    Официальная дока же вполне нормально объясняет. Если коротко - это общий интерфейс к последовательному набору данных, который позволяет читать, писать и искать в этих данных (как в файле). И все это в едином стиле. Интерфейс такой, типа. Грубо говоря нечто вроде юниксовского подхода "все на свете это файл".

    Мне не понятно, где тогда хранится весь ответ клиента, если не в памяти ?
    В памяти конечно, но так как это оболочка над данными, то реализация скрыта, условно вы можете считать это файлом, который может активно меняться.
    Ответ написан
  • Resource: что из себя представляю потоки в php?

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

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

    Например, когда мы вызываем функцию fopen, то в результате мы получаем ресурс, который в себе содержит дескриптор файла, и далее мы уже можем работать с этим файлом не считывая его полностью в память.
    Как я понимаю, через потоки.. но что это за потоки ? где именно про них почитать ? это какие-то механизмы операционной системы ?

    Вот даже здесь, поскольку fopen работает поверх абстракции, нельзя говорить о едином подходе.
    Если у нас самый простой случай - локальный файл - то РНР оборачивает функции для работы с файлами языка С в свою собственную абстракцию. Но ниже - на уровне этих самых функций языка С - никаких потоков нет. Есть обращение к функциям операционной системы, которые просто позволяют прочитать выбранный кусок файла.
    Тут никаких вопросов нет, всё честно - если мы прочитали из файла 5 килобайт - значит потратили ровно 5 килобайт памяти.
    Но работаем мы с файлом не считывая его весь в память не потому что поток, а потому что так устроена файловая система. А поток этой возможностью только пользуется.

    Если же мы открываем не файл, а URL, то РНР начинает извращаться, пытаясь предоставить те же самые инструменты, какие мы используем для работы с файлами, для доступа к ресурсам совершенно другого типа.
    И здесь возможны нюансы. Я не знаю, как реализован HTTP wrapper, но в теории HTTP позволяет чтение произвольного объема данных через заголовок Range:. То есть РНР вполне может читать и из НТТР кусками, а не целиком.

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

    А упомянутый в вопросе PSR-7 вообще никакого отношения к потокам в РНР не имеет. Это совершенно отдельная реализация принципа потоков, которая не имеет отношения к потокам в РНР.
    Ответ написан
    Комментировать
  • Как очищать текст в php?

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

    На самом деле этот вопрос встречается довольно часто. Вот например популярный ответ на Stack Overflow, который подробно разбирает этот распространённое заблуждение: https://stackoverflow.com/a/3126175. И основная мысль там:

    Понятие такой генерализованной "очистки данных" изначально бессмысленное и вредное.

    Особенно такой вот индусской функцией, которая сама по себе - пример редкого идиотизма: сначала заменяем символы < и > на HTML сущности... а потом бодро пытаемся вырезать HTML теги. Которых к этому моменту в тексте не останется ни одного!
    Или функция stripcslashes, которая здесь вообще ни к селу, ни к городу. Если я хочу написать сочетание \n, то с какой стати эта функция будет заменять его на перевод строки?
    Всё что можно оставить из этого безумного набора - это trim(). Да и то не всегда. Как правильно заметил Rsa97, могут быть случаи, когда лидирующие пробелы имеют значение, например, при выводе форматированного кода. Кстати, этим как раз грешит Хабр. Если запостить код с отступами, то первый будет "съеден"!


    Очистка

    Любая "очистка" (хотя правильнее говорить про форматирование), имеет смысл только в определённом контексте.
    И поэтому "очищать" надо только адресно, строго перед использованием в том или ином конкретном случае.

    Например, базе данных ни жарко, ни холодно от наличия HTML тегов.
    А проблемы могут начаться только при выводе данных в HTML. Но если мы будем предотвращать эти проблемы заранее, то просто попортим кучу данных. Поэтому форматировать данные для использования в контексте отрисовки HTML следет строго перед этой отрисовкой. То есть при выводе.
    Что и делают все популярные РНР шаблонизаторы автоматически.
    То есть вручную колупаться с "очисткой" вообще не нужно.

    Больше того, "очистка" HTML поможет данным, выводимым в яваскрипт, как мёртвому припарки. То есть опять же - всегда надо понимать, в какой именно контекст мы выводим данные, и форматировать соответствующим образом. В частности любые данные передавать в яваскрипт только через json_encode()

    И таких контекстов неисчислимое множество. Например, если мы используем переменную для передачи параметров в консольный скрипт, то надо обязательно обрабатывать её через escapeshellarg(). Если в регулярку - то preg_quote(). Имя файла для инклюда из переменной (хотя так делать вообще не стоит) надо хотя бы обрабатывать через basename(). И так далее.

    Валидация

    Если же наличие HTML тегов в поступающих данных противоречит техническому заданию, то надо заниматься не "очисткой", а валидацией: проверить регулярным выражением, есть ли в строке HTML теги. И если есть, то вернуть пользователю с сообщением об ошибке.

    Защита БД

    И кстати, по поводу "использую pdo".
    На всякий случай уточню, что само по себе использование PDO не защищает ни от каких проблем
    Важно помнить, что защита - это когда в базу данных отправляется строго константная строка запроса, полностью на 100% составленная из значений, прописанных в коде РНР, и в ней не используется ни одно значение, пришедшее в код извне. Причем PDO помогает здесь только наполовину, позволяя использовать в запросе подстановки вместо самих данных.
    Но при этом для всех остальных частей запроса - например имен полей - у ПДО нет никакой защиты и её надо организовывать самостоятельно. Либо проверяя по белому списку, лабо, по крайней мере, прогоняя через регулярку.
    Ответ написан
    13 комментариев
  • Как написать кастомную активити для бизнес-процесса для коробочного Битрикс24?

    gromdron
    @gromdron Куратор тега Битрикс24
    Работаю с Bitrix24
    Существует не потерявшая актуальность статья с записью вебинара Малышына и Калинина с разбором создания активити.

    От себя могу добавить: посмотрите современные активити (bitrix/activities/bitrix/crmsetshipmentfield) и простые (bitrix/activities/bitrix/logactivity) - они помогут быстрее разобраться.
    Ответ написан
    Комментировать