Ответы пользователя по тегу PHP
  • Что я в итоге реализовал?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Эм... есть несколько вопросов по Вашему "чуду".
    Отбросив велосипедизм и костылестроение есть пара вопросов по логике работы.

    То что у Вас есть константа MAX_AGE_IN_YEARS (кстати почемы бы просто не спрашивать дату рождения?) это ок (смущает конечно _IN_YEARS, но да ладно), то что у Вас 3 пола это тоже допустимо (по крайней мере в нашей адекватной России), то что у Вас есть допустимый ростовой диапазон тоже, но во чего я точно не могу понять, так это блин STATUSES.

    Почему бы не сделать 2 "статуса" (на самом деле эт о скорее "признак жизни субьекта") - DEAD или ALIVE, то есть живой или не живой.
    child, adult, old и т.п. можно получить при помощи отдельного метода исходя из возраста обьекта (ведь они же зависят от возраста, а не от каких либо правил).
    "Статусы" buried и cremated это не статусы, а виды погребения.

    Велосипедизм вызван именно нежеланием разделять физические сущности на их логические составляющие.

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

    gromdron
    @gromdron
    Работаю с Bitrix24
    Проверьте директиву allow_url_fopen в php.ini.
    Ответ написан
    Комментировать
  • Что за ошибка mysqil?

    gromdron
    @gromdron
    Работаю с Bitrix24
    "(NULL, '$cart_id_product', '123', '44', '$cart_ip'


    А скобку кто закроет?
    Ответ написан
  • Как сделать кнопку отправки вложения?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Загрузка файлов
    Для отправки почты использовать что-нибудь попроще: PHPMailer или Swift Mailer

    Неплохо было бы почитать по Чистый код на php и PHP: The Right Way
    Ответ написан
  • Какой способ получения IP лучше?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Ну хз, на мой взгляд это не равноценные примеры: субьективно читать первый не проще, я бы отдал предпочтение функции get_ip(), с другой стороны второй пример не делает того же, что делает первый (например валидацию не проводит).

    /**
     * Return client ip if find, or null
     * @return string|null
     */
    function getUserIp()
    {
        static $ip;
    
        if ( !is_null($ip) )
        {
            return $ip;
        }
    
        $candidates = [
            @$_SERVER['HTTP_CLIENT_IP'],
            @$_SERVER['HTTP_X_FORWARDED_FOR'],
            @$_SERVER['REMOTE_ADDR']
        ];
    
        foreach ($candidates as $candidate)
        {
            if ( \filter_var($candidate, \FILTER_VALIDATE_IP) )
            {
                $ip = $candidate;
                break;
            }
        }
    
        return $ip;
    }
    
    var_dump(getUserIp());
    Ответ написан
    Комментировать
  • Как из двух массивов сделать один двумерный массив?

    gromdron
    @gromdron
    Работаю с Bitrix24
    В Вашем случае есть 2 ограничения:
    1) Если у Вас будет 2 пользователя с одинаковым именем, то их данные смешаются в одну кучу
    2) Если немного изменить формат $users то будет значительно проще получить результирующий массив (не нужен будет первый цикл на ассоциативность)

    /**
     * Шаг 1 - разворачиваем $users в плоский массив
     * Если есть возможность получить его сразу ассоциативным,
     * то это было бы лучше
     */
    $usersAssoc = [];
    
    foreach ($users as $user)
    {
    	$usersAssoc[ $user['id'] ] = $user['name'];
    }
    
    /**
     * Шаг 2 - выполяем группирующее преобразование наших $punch
     */
    $result = [];
    
    foreach ($punch as $time)
    {
    	if ( !array_key_exists($time['user_id'], $usersAssoc) )
    	{
    		// В punch есть массив, который относится к пользователю
    		// о окотором мы не знаем
    		continue;
    	}
    
    	$result[ $usersAssoc[ $time['user_id'] ] ][ $time['id'] ] = $time;
    }
    
    
    echo "<pre>";
    var_dump($result);
    echo "</pre>";
    Ответ написан
  • Кто-то видел Blueprint Interface для php?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Эм.. а какой кейс это закроет?
    А UE насколько я знаю, это заменяет все - и подход стандартизирован и действия и взаимоотношения.
    В вебе нет такой проблемы - классы обычно запиливаются для конкретного ORM/DataMapper и где-то, даже есть свой скаффолдинг.
    Ответ написан
  • Как выполнить поиск в JSON?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Если Вы не хотите работать с json, то почему вы не пробовали работать с ним как с строкой?
    Ответ написан
    Комментировать
  • Как закодировать строку в Unicode последовательность?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Если Вы уверены что на входе будут только a-zA-Z0-9-=+- (похоже на base64) то можно упростить и не перекодировать, например так:

    $uncomingString = 'W+I4zLZyeJDAhQMe33tYRcXC+Falj9baMfjJw5yOijaPNHDYcnNlRlTGm3rvA6cn2hXMmW4ZKEyTphwzNMQlOlnNiCHK2LLpJLgXK6JHKuTYeParwqCud5Vn2dZXpxctrQf8OkbCqF12u0GcBR2or2HFBrEV13Jd5YAX4bRbUBk=';
    
    
    function forceUnicode( $str = '' )
    {
    	$result = '';
    
    	for( $i=0,$length=strlen($str); $i<$length; $i++)
    	{
    		$result .= "\\u".str_pad(bin2hex($str[$i]), 4, '0', STR_PAD_LEFT);
    	}
    
    	return $result;
    }
    
    echo forceUnicode($uncomingString);
    
    /*
    Выведет: 
    \u0057\u002b\u0049\u0034\u007a\u004c\u005a\u0079\u0065\u004a\u0044\u0041\u0068\u0051\u004d\u0065\u0033\u0033\u0074\u0059\u0052\u0063\u0058\u0043\u002b\u0046\u0061\u006c\u006a\u0039\u0062\u0061\u004d\u0066\u006a\u004a\u0077\u0035\u0079\u004f\u0069\u006a\u0061\u0050\u004e\u0048\u0044\u0059\u0063\u006e\u004e\u006c\u0052\u006c\u0054\u0047\u006d\u0033\u0072\u0076\u0041\u0036\u0063\u006e\u0032\u0068\u0058\u004d\u006d\u0057\u0034\u005a\u004b\u0045\u0079\u0054\u0070\u0068\u0077\u007a\u004e\u004d\u0051\u006c\u004f\u006c\u006e\u004e\u0069\u0043\u0048\u004b\u0032\u004c\u004c\u0070\u004a\u004c\u0067\u0058\u004b\u0036\u004a\u0048\u004b\u0075\u0054\u0059\u0065\u0050\u0061\u0072\u0077\u0071\u0043\u0075\u0064\u0035\u0056\u006e\u0032\u0064\u005a\u0058\u0070\u0078\u0063\u0074\u0072\u0051\u0066\u0038\u004f\u006b\u0062\u0043\u0071\u0046\u0031\u0032\u0075\u0030\u0047\u0063\u0042\u0052\u0032\u006f\u0072\u0032\u0048\u0046\u0042\u0072\u0045\u0056\u0031\u0033\u004a\u0064\u0035\u0059\u0041\u0058\u0034\u0062\u0052\u0062\u0055\u0042\u006b\u003d
    */


    Для конкретно Вашего примера выдает тот же результат, что и требовалось, но нужно на разных данных потестировать конечно - мог и налажать
    Ответ написан
    1 комментарий
  • Как исправить фильтр?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Замените
    if (isset($brand)){
    На
    if ( !empty($brand) ) {
    И еще:
    $query = "SELECT * FROM products WHERE brand =  '".$_POST["category"]."' ";

    Почитайте про SQL Injection
    Ответ написан
    Комментировать
  • Почему не удается получить ответ от сервера soap wsdl php Curl?

    gromdron
    @gromdron
    Работаю с Bitrix24
    А зачем Вы вручную это делаете?
    Начнем с того, что в php есть расширение php-soap, которому только скормить адрес wsdl и вызывать уже готовые методы.

    В крайнем случае, можно воспользоваться готовой библиотекой nusoap
    Ответ написан
    Комментировать
  • Получить значения чекбоксов из базы данных?

    gromdron
    @gromdron
    Работаю с Bitrix24
    А что Вы хотите? Вы же его явно затираете в строке:
    $data[$row['question_id']] = $row['answer_id'] ;
    Запихивайте массив:
    $data[$row['question_id']][] = $row['answer_id'] ;

    При складывании 1к1 (1 вопрос = 1 ответ) - Ваша структура подойдет, а при 1 вопрос => много ответов уже нет.
    Ответ написан
    Комментировать
  • $_POST принимает NULL при AJAX запросе и мешает использовать PDO, как исправить?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Если Вы НЕ отметили ни одного чек-бокса, то Вам ничего и не прилетит.
    Т.е. если отправить форму из моего примера, в $_POST будет:
    array(2) {
      ["a"]=>
      string(1) "0"
      ["b"]=>
      string(1) "5"
    }

    Т.е. никакого day у Вас и нет.
    Я так понимаю, Вы делаете вывод данных на основе значения этого day. А значит ничего не и должно вывестись.

    То есть, Ваш код сведется к:
    $result = [];
    
    $a = (int) $_POST['a'];
    $b = (int) $_POST['b'];
    
    $c = array_filter( (array) $_POST['day'] );
    
    if ( !empty($c) )
    {
    	$c = implode(',', $_POST['day']);
    	$in = str_repeat('?,', count($c) - 1) . '?';
    	$sql = "SELECT * FROM table WHERE day IN ($in) ASC LIMIT :a, :b";
    	$stmt = $pdo->prepare($sql);
    	$stmt->execute($с, [$a, $b]);
    	$data = $stmt->fetchAll();
    
    	$result = $data;
    }
    
    echo json_encode($result);


    P.S. А так ли Вам нужна именно ручная сборка значений? Почему бы не вынести в саму форму?

    <form id="filter">
    	<input type='hidden' name='a' value='0' />
    	<input type='hidden' name='b' value='5' />
    	<input type="checkbox" name="day[]" value="1"> 
    	<input type="checkbox" name="day[]" value="2">
    	<input type="checkbox" name="day[]" value="3"> 
    </form>


    $.ajax({
        url: 'index.php',
        method: 'POST',
        data: $("#filter").serialize()
    });
    Ответ написан
    1 комментарий
  • Не могу понять почему не работает var_dump?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Меняем:
    if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['edit'])) {
        $editServiceById = $services->editServiceById($_GET['service_id'], $_POST);
    }


    На:
    // Display errors 
    ini_set('display_errors', 1);
    ini_set('display_startup_errors', 1);
    error_reporting(E_ALL);
    // Log values
    echo "<pre>";
    var_dump($_SERVER['REQUEST_METHOD'], $_POST['edit'], isset($_POST['edit']));
    echo "</pre>";
    
    if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['edit'])) {
        $editServiceById = $services->editServiceById($_GET['service_id'], $_POST);
    }


    Повторяем отправку формы и смотрим что и куда не ушло. А дальше учимся дебажить банальные вещи.

    P.S. leni_m - сполерит :P
    Ответ написан
    Комментировать
  • Как объединить три массива?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Как вариант, еще один:

    /**
     * Prepare array for our job
     */
    $arrayOne = [
    	0 => 80,
    	1 => 80,
    	2 => 90,
    ];
    
    $arrayTwo = [
    	0 => [
    		0 => 190,
    		1 => 195,
    	],
    	1 => [
    		0 => 200,
    	],
    	2 => [
    		0 => 190,
    		1 => 195,
    	],
    ];
    
    $arrayThree = [
    	0 => 1,
    	1 => 2,
    	2 => 3,
    ];
    
    /**
     * @var array Array with actual data in our structure
     */
    $arResult = [];
    
    foreach ( $arrayTwo as $iKeyOne => $arrayTwoElement )
    {
    	// if in second array exist unknown key
    	if ( !array_key_exists($iKeyOne, $arrayOne) )
    	{
    		continue;
    	}
    
    	// if in third array exist unknown key
    	if ( !array_key_exists($iKeyOne, $arrayThree) )
    	{
    		continue;
    	}
    
    	// if in second array no elements
    	if ( empty($arrayTwoElement) || !is_array($arrayTwoElement) )
    	{
    		continue;
    	}
    
    	/* @var integer Key for first depth level  */
    	$iLevelKey = (int) $arrayOne[ $iKeyOne ];
    
    	/* @var integer Value for second depth level */
    	$iLevelValue = (int) $arrayThree[ $iKeyOne ];
    
    	foreach ($arrayTwoElement as $k => $v)
    	{
    		$arResult[ $iLevelKey ][ $v ] = $iLevelValue;
    	}
    }
    
    var_dump($arResult);
    /*
    Will display:
    array(2) {
      [80]=>
      array(3) {
        [190]=> int(1)
        [195]=> int(1)
        [200]=> int(2)
      }
      [90]=>
      array(2) {
        [190]=> int(3)
        [195]=> int(3)
      }
    }
    */
    Ответ написан
    Комментировать
  • Почему не работает return?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Ну так все правильно!
    Вы же получаете результат для своей строки на второй итерации, а return на первой не работает.
    Заменяем:
    encrypt($text, $m);
    На
    return encrypt($text, $m);

    И видим результат: s eT ashi tist!
    Можно конечно еще и функцию упростить:
    function encrypt($text, $n)
    {
    	if ( $n < 1 )
    	{
    		return $text;
    	}
    	$str1 = $str2 = "";
    	for($i = 0, $len = strlen($text); $i < $len; $i++)
    	{
    		if ( $i%2 == 0 )
    		{
    			$str2 .= $text[$i];
    		}
    		else
    		{
    			$str1 .= $text[$i];
    		}
    	}
    
    	return encrypt( $str1.$str2, ($n-1));
    }
      
    echo encrypt('This is a test!', 2);
    Ответ написан
    Комментировать
  • Как усовершенствовать функцию?

    gromdron
    @gromdron
    Работаю с Bitrix24
    А что Вы в ней хотите усовершенствовать?
    Ну например можно добавить typehint array у $requestTags и избавиться от проверки:

    public static function getTags(array $requestTags): array
    {
        $tags = [];
    
        foreach ($requestTags as $tag) {
            if (is_numeric($tag)) {
                $tags[] = $tag;
            } else {
                $newTag = Tag::upsert(['name' => $tag]);
                $tags[] = $newTag->id;
            }
        }
    
        return $tags;
    }


    Либо можно вынести в отдельную функицю сохранение тегов, например:

    function mapTags( array &$value )
    {
        if ( is_numeric($value) )
        {
            return $value;
        }
    
        $newTag = Tag::upsert(['name' => $tag]);
        return $newTag->id;
    }


    И тогда весь код метода свернется в:

    public static function getTags( array $requestTags ): array
    {
        return array_map('mapTags', $requestTags);
    }


    Можно просто уменьшить вложенность оставив скрипт (меньше уровней будет):

    public static function getTags($requestTags): array
    {
        $tags = [];
    
        if ( !$requestTags )
        {
            return $tags;
        }
    
        foreach ($requestTags as $tag) {
            if (is_numeric($tag)) {
                $tags[] = $tag;
            } else {
                $newTag = Tag::upsert(['name' => $tag]);
                $tags[] = $newTag->id;
            }
        }
    
        return $tags;
    }


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

    public static function getTags(array $requestTags): array
    {
        if ( empty($requestTags) )
        {
            return $requestTags;
        }
    
        $existedTags = array_filter($requestTags, 'is_numeric');
        $newTags = array_diff($requestTags, $existedTags);
    
        /**
         * Тут единый batch-метод который отправляет 
         * 1 запрос на все теги сразу.
         * В results - массив Tag, обработанных batch-методом
         */
        foreach ($results as $tag)
        {
            $existedTags[] = $tag->id;
        }
    
        return array_unique($existedTags);
    }
    Ответ написан
    1 комментарий
  • Как сделать временную ссылку на файл в PHP?

    gromdron
    @gromdron
    Работаю с Bitrix24
    В этом нет ничего сложного или необычного - все уже изобрели до Вас.
    Не виду смысла отвечать подробно ибо эту тему разобрали на хабре по косточкам от и до.

    Читать можно по ссылке: https://habrahabr.ru/post/151795/

    P.S. Скажу за себя - X-Accel-Redirect наше все :)
    Ответ написан
    Комментировать
  • Как можно оптимизировать код?

    gromdron
    @gromdron
    Работаю с Bitrix24
    Если я все правильно понял и нигде не ошибся, то можно попробовать и так:

    <div class="currency">
      <ul>
        <? foreach ($obj as $element):?>
          <? $color = ($element['percent_change_24h'] > 0) '#4ac06a' : '#ff8d8d'; ?>
          <? $plus = ($element['percent_change_24h'] > 0) '+' : ''; ?>
          <li>
            <i class="cc <?=$element["symbol"];?> iconsi" title="<?=$element["name"];?>"></i>
            <div class="block_coin">
              <span class="coin_name"><?=$element["name"];?></span>
              <span style="color: '<?=$color;?>';" class="coin_price"><?=$element['price_usd'];?></span>
              <span style="color: '<?=$color;?>';" class="coin_change">(<?=$plus;?><?=$element["percent_change_24h"];?>%)</span>
            </div>
          </li>
        <? endforeach; ?>
      </ul>
    </div>
    Ответ написан
    2 комментария
  • Где могут пригодиться итераторы PHP?

    gromdron
    @gromdron
    Работаю с Bitrix24
    На эту тему есть замечательная статья: ashep.org/2013/using-spl-iterators-1

    Коротко пару выжимок:
    Цикл foreach создаёт копию полученного массива. Если вы имеете дело с большими объёмами данных, такой подход не годится по очевидной причине: снижение производительности. Итератор SPL работает по другому: он обрабатывает один элемент итерируемого списка за раз, делая это куда более эффективно, нежели foreach.


    При создании поставщиков данных (data providers) итераторы помогают сделать их более эффективными, предлагаю возможности ленивой загрузки (lazy loading). «Ленивая загрузка» означает то, что фактическое получение данных из источника выполняет только тогда, когда эти данные нужны. Помимо прочего, вы получаете возможность трансформации данных перед тем, как отдавать их клиенту объекта.
    Ответ написан
    Комментировать