Ответы пользователя по тегу PHP
  • Добавить в массив rows (vue.js) данные из базы mysql (php)?

    dubr
    @dubr
    пыхарь
    Если я правильно понимаю, тут не SPA со сборкой, а олдскульные пхп-шаблоны, верно?
    Тогда можно данные пихать в дата-атрибут примерно так:
    <div id="app" data-rows='<?=json_encode($rows)?>'>...</div>

    А потом читать их примерно так:
    data() {
       return { rows: JSON.parse(this.$el.getAttribute('data-rows')) };
    }

    Но вообще да, лучше, как писали выше, отдавать апишкой и забирать аксиосом =)
    Ответ написан
    Комментировать
  • Как на сервере вставить картинку в видео?

    dubr
    @dubr
    пыхарь
    Плюсую за ffmpeg, вот это похоже на ваш случай?
    Ответ написан
    Комментировать
  • Как разделить динамический вывод элементов на группы?

    dubr
    @dubr
    пыхарь
    <?php
    function group_by_number($arr, $number) {
       $res = [];
       $counter = 0;
       foreach ($arr as $item) {
           if ($counter % $number === 0) {
               $res []= [];
           }
           $res[ count($res) - 1] []= $item;
           $counter++;
       }
       return $res;
    }
    
    $arr = ['a','b','c','d','e','f','g','h'];
    
    $groupped = group_by_number($arr, 3);
    foreach ($groupped as $group) {
       ?><div class="group"><?php
       foreach ($group as $item) {
           ?><span><?= $item ?></span><?php
       }
       ?></div><?php
    }


    Но вообще я бы сперва подумал, нельзя ли поправить верстку =)
    Ответ написан
    Комментировать
  • Как запретить рассылку спама в форме?

    dubr
    @dubr
    пыхарь
    Спам-боты (пока) не выполняют JS. При показе формы пишите в сессию код, передавайте на клиент в любом виде, на клиенте пишите из JS в скрытое поле. Пока оно не оформлено в массово используемый плагин, будет работать =)

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

    <?php
    session_start();
    $secret_error = false;
    $is_sent = count($_POST);
    if (
        $is_sent && 
        (
            !isset($_POST['secret']) || 
            !isset($_SESSION['secret']) || 
            $_POST['secret'] !== $_SESSION['secret']
        )
    ) {
        $secret_error = true;
    }
    
    if ($is_sent && !$secret_error) {
        // обрабатываем, шлем письмо
        ?>
        Ваш звонок очень важен для нас!
        <?php
    } else {
        if ($secret_error) {
            ?>
            <p>Вы бот или у вас не включен JavaScript, сделайте с этим что-нибудь!</p>
            <?php
        }
        $multiplier = rand(10, 99);
        $secret = (string) rand(1000,9999);
        $_SESSION['secret'] = $secret;
        ?>
        <form action="" method="post" data-secret="<?= $secret * $multiplier ?>" data-multiplier="<?= $multiplier ?>">
            <label>Ваше имя <input name="name" /></label>
            <input type="hidden" name="secret" />
            <input type="submit" />
        </form>
        <!-- вот это можно вынести в отдельный файл -->
        <script type="text/javascript">
            document.querySelectorAll('form[data-secret]').forEach(function(form) {
                var secret = form.getAttribute('data-secret') / form.getAttribute('data-multiplier');
                form.querySelector('[name="secret"]').value = secret;
            });
        </script>
        <?php
    }


    В принципе можно с тем же успехом написать

    <script type="text/javascript">
            document.querySelector('[name="secret"]').value = "<?= $secret ?>";
    </script>


    Скорее всего кодеру, который делает бота, будет лень разбираться, как оно у вас работает, если оно работает только у вас (то есть не является тиражным решением). Магия со множителями или чем-то таким просто не позволяет вытащить значение одной регуляркой, еще немного снижая шансы заинтересовать злодея =)
    Ответ написан
    1 комментарий
  • PHP: Почему Class not found если use в другом файле?

    dubr
    @dubr
    пыхарь
    Почитайте доку для разнообразия.
    Неймспейсы и директивы use работают на уровне файлов. То есть use связывает полное имя с кратким/алиасом только в том файле, где его написали.
    Ответ написан
    Комментировать
  • Как удалить все переменные созданные внутри цикла по его окончанию?

    dubr
    @dubr
    пыхарь
    Поддерживаю мысль Василий - если имеется php 5.4+, можно даже так:

    $res = [];
    array_walk(
        $arr,
        function($k, $v) use (&$res) {
             // создаем любые переменные в любом количестве
             // при необходимости пишем что-нибудь в $res
        }
    );

    И посмотрите еще на array_map.

    Либо можно вынести сам цикл в отдельный метод.

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

    dubr
    @dubr
    пыхарь
    * влияет на предыдущий символ. Ваша регулярка ищет символы: "n" (1 шт), "i" (1 шт), "c" (0 и более шт).

    Зачем вам тут вообще регулярка - не понимаю, по ощущениям скорее всего надо делать как-то иначе =) Если таки хочется получить регуляркой часть после nic (если я правильно понял ход мысли), то как-то так:

    <?php
    preg_match("~^nic(.+)$~", "nic0000-0000-0000", $matches);


    В $matches будет
    array (
      0 => 'nic0000-0000-0000',
      1 => '0000-0000-0000',
    )


    А, ну вот GTRxShock воспроизвел примерно то же самое, пока я писал =) Его вариант ловит цифры и дефис после nic в любом месте строки. Мой - все, что после nic, если строка начинается с nic. Какой лучше - хз, надо смотреть на ваши строки =)
    Ответ написан
    5 комментариев
  • Как правильно поступить с EAV архитектурой, где для каждого типа значения своя таблица?

    dubr
    @dubr
    пыхарь
    Вместо дополнительных таблиц под каждый тип можно создавать дополнительные столбцы.

    entity_id       # INT, ссылка на объект, которому принадлежит свойство
    attribute_id    # INT, ссылка на инфу о свойстве
    value_int       # INT, значение целочисленное
    value_varchar   # VARCHAR, короткий текст
    value_text      # TEXT, длинный текст
    value_whatever  # и так далее: DATETIME, ENUM, DECIMAL


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

    Отдельная таблица на тип создается, например, в Magento (опять же надо проверить, но раньше было так, и вряд ли они радикально меняли схему). Можете посмотреть, какие запросы генерирует их ORM.

    Ну и вообще поковыряйте разные e-commerce продукты, EAV в каком-то виде реализован у всех.

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

    Если вас пугает производительность схемы - ну, в идеале надо тестировать на ваших данных с вашими сценариями. Если лень или пока нет ни данных, ни сценариев ;) погуглите бандл / модуль для своего фреймворка и пляшите от него.
    Ответ написан
    1 комментарий
  • Как решить проблему с ошибкой: open_basedir restriction in effect. File(/home/u314597346/public_html/tmp) is not within the allowed path(s)?

    dubr
    @dubr
    пыхарь
    open_basedir - настройка, которая ограничивает места, куда php может "лезть".

    В вашем случае это директории:

    /home/u850868817
    /tmp
    /var/tmp
    /opt/php-7.0/pear
    /usr/local/bin // вау!
    /etc/pki/tls/certs

    На шаред-хостингах значение задается "сверху" хостером и переопределить его из скрипта нельзя.

    На картинке: Джумла взяла значение upload_tmp_dir - это временная директория для загрузки файлов на сервер, и попыталась проверить, можно ли туда писать. Но проверить не получилось, потому что open_basedir не пустил is_writable() к этой директории, потому что ее и ее родителей нет в списке разрешенных.

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

    <?php
    echo 'tmp dir: '.ini_get('upload_tmp_dir')."<br />";
    echo 'doc root: '. $_SERVER['DOCUMENT_ROOT'];


    и посмотрите, что он выведет. Если там будут разные uXXXX - надо спрашивать хостера, чо за. Если оба будут u850868817 - надо искать, откуда взялся u314597346.
    Ответ написан
    7 комментариев
  • Какие кавычки следует использовать в массиве и почему?

    dubr
    @dubr
    пыхарь
    1) Решительно пофигу, где используются кавычки - в массиве или где-то еще. При обращении к индексу массива $a["key"] в квадратные скобки попадает выражение "key", состоящее из одного строкового литерала. Кавычки - это не часть магии, достающей что-то из массива =) Так тоже можно:

    $a = ['key' => 'val'];
    $k = "key";
    
    // вау! вот это магия!!!
    echo $a[$k]; 
    
    // просто невероятно!
    echo $a[ strrev('ek') . substr($k, -1, 1) ];


    2) По поводу "одинарные быстрее работают": надо понимать, за счет чего они "работают быстрее". Пхп пытается найти в них переменные и специальные последовательности типа \n при разборе скрипта. То есть один раз в самом начале, а не каждый раз, когда выражение исполняется. То есть:

    for ($i = 0; $i < 100500; $i++) {
    	$b = $a["key"];
    }


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

    3) И я вот решил наконец выяснить, какая она, это разница =)

    <?php
    $s = 'return count([';
    
    ini_set('memory_limit', '900M');
    
    $rands = [];
    $num = 1000000;
    $quot = '"';
    
    // я турбо-кавычка!
    // $quot = "'"; 
    // ^ ^ ^ ^ ^
    // раскомментируй меня и почувствуй настояющую скорость!
    
    for ($i = 0; $i < $num; $i++) {
        $s .= $quot. md5( rand(100000000, 999999999) . rand(100000000, 999999999) ).$quot.' => 1';
        if ($i !== $num - 1) {
        	$s .= ',' ;
        }
    }
    $s .= ']);';
    
    // получилось строка:
    // return count(['a' => 1, 'b' => 1, ... 1kk раз ])
    
    $start = microtime(true);
    // вот тут будет работать парсер
    eval($s);
    
    // например, 1.4128859043121 сек.
    echo (microtime(true) - $start) . " сек.";


    Мы генерим строку с кодом, который создает массив с миллионом ключей, каждый ключ - md5 от двух случайных чисел. eval запускает парсер и он типа 1.4128 сек отрабатывает.

    Теперь раскомментируем одинарную кавычку, и видим... 1.2484261989594 сек.! То есть разница в 0.16 с на дичайшем и нереальнейшем примере =) Повторим 100 раз, у меня получилось в среднем 0.12 сек. в пользу одинарных. Это на маке с php 5.6. Погонял на VPS с php 7 - там разница 0.36 сек, но между отдельными замерами одинакового способа разброс получается сильно больше этих 0.36, так что не показательно.

    4) Поэтому ориентироваться на "быстродействие" надо в последнюю очередь. На возможность вставлять переменные внутрь двойных кавычек ориентироваться тоже не надо, потому что так делать плохо, потому что читать сложнее, хорошо - закрыть кавычку, поставить точечку и дальше уже доллар (как эс) =)

    В первую очередь надо ориентироваться на вероятность появления переносов строки, которые могут возникнуть в этой строке. Во вторую - на вероятность появления собственно кавычки одного из типов, потому что экранирование снижает читаемость (особенно если это регулярка, где сам слеш тоже надо экранировать). В остальных случаях можно юзать любую, но желательно одну и ту же. Например одинарную, потому что ее на клавиатуре нажимать удобнее =)
    Ответ написан
    Комментировать
  • Как сделать очередность товаров?

    dubr
    @dubr
    пыхарь
    1. Как советовали выше, добавляем колонку (у меня называется priority - дело вкуса).
    2. Определяем ее, например, как decimal(6,3) - то есть число с тремя знаками после запятой.
    3. Для новых объектов заполняем ее значением max(priority)+1 - вставка в конец.
    4. Когда пользователь решает перетащить объект на другую позицию, получаем значения предыдущего и следующего элементов. Если нет предыдущего, считаем его за 0, если нет следующего - за предыдущий+1. Записываем для сортируемого объекта priority = (prev + next) / 2.
    5. Если очень много раз таскать туда-сюда, можем получить ситуацию, когда соседние priority отличаются на 0.001 - обрабатываем этот случай в коде, пересчитывая приоритеты так, чтобы увеличить интервал. Или просто переиндексируем все целиком в фоне с какой-то разумной регулярностью.

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

    Вместо дробных значений можно тупо добавлять новые с большим шагом - max(priority)+1000.
    Ответ написан
    Комментировать