• Спустя сколько времени после запуска сайта поисковики проиндексируют первую страницу?

    opium
    @opium
    Просто люблю качественно работать
    обычно в первый день все проходит
    Ответ написан
    Комментировать
  • Как поставить многоточие в конце блока с текстом без использование js??

    Petroveg
    @Petroveg
    Миром правят маленькие с#@&ки
    Для неразрывных строк всё просто

    ... {
    	white-space: nowrap;
    	overflow: hidden;
    	text-overflow: ellipsis;
    }

    Для нескольких строк, увы, всё куда хуже.

    Для webkit есть правило -webkit-line-clamp, позволяющее задать количество строк. Естественно, white-space не нужен.

    Для остальных это всегда будут эмуляции — либо JS-решения, либо абсолютно позиционированная псевдобласть (чаще всего ::after) с многоточием.
    Ответ написан
    Комментировать
  • Как включить полосы в коде для Atom?

    Ответ написан
    Комментировать
  • Как включить полосы в коде для Atom?

    @Melagomania
    В настройках Indent Guides включи)
    Ответ написан
    Комментировать
  • Как настроить редактор atom?

    alleroy
    @alleroy Автор вопроса
    Изучаю фреймворк laravel
    А всё сам разобрался, в настройках находим Show Indent Guide и ставим галочку
    Ответ написан
    1 комментарий
  • Как правильно написать свой обработчик ошибок php?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Перед тем как писать обработчик, надо сначала понять, а зачем он нужен.
    Потому что вот эта вот функция - она совершенно бессмысленная.
    Вся "обработка", которой она занимается - это добавляет бессмысленные фразы типа "Error_message" к тому что РНР выведет и так.

    Обработчик ошибок не должен заниматься удалением файлов. Обработчик вступает в дело, когда ничего исправить уже нельзя, и всё что остаётся - это показать пользователю страницу с извинениями и корректным НТТР кодом. Пример можно взять здесь: https://phpdelusions.net/articles/error_reporting

    А вот обрабатывать ошибки надо с помощью оператора try catch
    Если надо откатить транзакцию, то всю её целиком надо поместить внутрь try catch, в котором ловить ВСЕ ошибки, то есть \Throwable и после этого скорее всего добавить throw с тем же исключением, поскольку вряд ли при ошибке БД имеет смысл продолжать работу скрипта. Но зависит от обстоятельств.

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

    Vamp
    @Vamp
    Как правило, обычные ошибки не обрабатывают в таком обработчике, а конвертируют в ErrorException.

    function error_handler(
        $error_code,
        $error_message,
        $error_file_name,
        $error_line
        // $error_context - не объявляйте этот аргумент. Он не существует.
      ){
    
        throw new ErrorException($error_message, 0, $error_code, $error_file_name, $error_line);
    
      }
    
      set_error_handler('error_handler', -1);

    Ну а дальше ловите исключения как обычно.

    // some code...
    
    $host_db = '127.0.0.1';
    $login_db = 'root';
    $password_db = '';
    $database_db = 'some_db';
    
    $DB = new PDO('mysql:host=' . $host_db . ';dbname=' . $database_db, $login_db, $password_db);
    $DB -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    try {
        $DB -> beginTransaction();
    
        // some code...
    
        $DB -> commit();
    } catch (\Throwable $e) {
        $DB->rollback();
    }
    // some code...
    Ответ написан
    6 комментариев
  • Как правильно написать свой обработчик ошибок php?

    @rPman
    Если в скрипте произошла ошибка, то как мне откатить транзакцию
    старайся чтобы все, что касается работы с каким то объектом, у которого состояние требует реакции (закрытие файла, транзакции бд и т.п.) то настоятельно рекомендуется описывать всю логику примерно на одном уровне/в одном месте

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

    Язык программирования php рекомендует и предлагает для этого конструкцию try catch finaly, там где может произойти ошибка, в catch прописывай логику завершения именно данной секции (откатить транзакцию) и вызывай следующий throw по цепочке, в finaly же прописывай то что нужно исполнить в любом случае.

    Да это потребует вдумчиво везде где только можно следить за ошибками, но такова селяви, либо ты надеешься на авось и автоматизацию либо следишь за всем сам.
    Ответ написан
    2 комментария
  • Чем веб-дизайн для Shopify отличается от обычного дизайна?

    KEugene
    @KEugene
    В Shopify свой язык разметки. Точнее, это смесь html+css+js+"еще что-то, напоминающее PHP". Назывется Liquid. Много специфических объектов. Так что простой копипаст из другой системы не заработает. Посмотреть можно тут https://shopify.dev/api/liquid
    Но лучше создать свою учетную запись, подключить дефолтовую тему и посмотреть встроенный редактор кода. А потом уже читать мануалы.
    Ответ написан
    1 комментарий
  • Как обработать возникшую ошибку в PHP скрипте загрузки страницы?

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

    Во-первых, очень хорошо что он сам по себе поставлен. Обычно пользователи РНР не задумываются о таких "мелочах". Но на самом деле об этом должен думать каждый программист, делающий сайты
    Во-вторых, здесь мы можем видеть довольно характерный баг Апача, который действительно, почему-то не выполняет директиву ErrorDocument для 500 ошибок, полученных от РНР. Ну и вообще, завязываться на Апач во времена доминирования Нжинкса как-то не очень дальновидно.
    В-третьих, как правильно заметил Stalker_RED, сделать редирект при 500 статусе (или 500 статус при редиректе) невозможно - статус может быть только один. Да это и нет смысла делать - проще сразу на месте нужную страницу и прочитать.
    В-четвертых, текущий подход, прямо скажем, не очень оптимальный:
    - о роботах мы позаботились, о пользователе позаботились, но надо ещё не забыть и программиста. Которому как раз сообщение об ошибке-то нужно видеть во всех подробностях!
    - просто отдать нужный НТТР код недостаточно - надо бы ещё и завершить работу скрипта.
    - ловить все ошибки вручную через try-catch так себе удовольствие. И код раздувает,и поведение потом быстро не поменяешь. А если в какой-то момент захочется для отладки прикрутить whoops - это придётся по всем блокам бегать?

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

    В самом простом варианте это будет что-то вроде такого:

    set_exception_handler(function ($e)
    {
        error_log($e);
        http_response_code(500);
        if (ini_get('display_errors')) {
            echo $e;
        } else {
            include 'pages/error_500.php';
        }
    });

    В теории, конечно, можно заменить error handler на глобальный try-catch который оборачивает точку входа, но это менее удобно. Тем более, что для обработки фатальных ошибок нужен свой отдельный обработчик, и в итоге код обработки ошибок начинает занимать довольно значительный объем и лучше конечно его инициализацию вынести отдельно.
    Ответ написан
    Комментировать
  • Как отразится на сайте публикация чужих статей?

    @Awwwayzxc
    Можете, если на вас не накатают в DMCA. Лучше заранее договориться с владельцем контента.

    Под фильтр за такое сложно попасть. Если взять контент за основу, добавить новые материалы и всячески его улучшить, то можно даже встать выше, чем "оригинал".

    Один лишь возраст сайта такое себе мерило. Смотреть, в целом, стоит на "трастовость" ресурса.
    Ответ написан
    Комментировать
  • Редирект при множественном "///"?

    shambler81
    @shambler81 Куратор тега htaccess
    RewriteCond %{THE_REQUEST} //
    RewriteRule .* /$0 [R=301,L]

    - единственный нормально работающий способ.
    А вот тебе в добавок дополнительные, тут доп исключения.

    ############################################################################
    #### Cтандартный .htaccess для проектов студии Клондайк, версия 2.4     ####
    ############################################################################
    RewriteEngine On
       #  Директива включает редиректы.
    RewriteBase / 
       # Без директивы (.*) = /$1 будет /var/wwww/site/web/$1  с директивой  = /$1
    Options +FollowSymLinks
       # Разрешает переход по символическим ссылкам.
    
    ############################################################################
    #### Перенаправляем протокол https на http                              ####
    ############################################################################
    RewriteCond %{HTTPS} on
       # Проверяем наличие https в URL.
    RewriteRule ^.*$ http://%{SERVER_NAME}%{REQUEST_URI}
       # Перенаправляем протокол на http.
    
    ############################################################################
    #### Выбор основного зеркала (или с www или без www)                    ####
    ############################################################################
       # 1. Редирект с www на без www. (раскоментировать директивы пункта 1)
    #RewriteCond %{HTTP_HOST} ^www\.(.*) [NC]
       # Проверяем, содержит ли домен www (в начале URL).
    #RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
       # Перенаправляем URL на домен без www.
    ####
       # 2. Редирект без www на www. (раскоментировать директивы пункта 2)
    #RewriteCond %{HTTP_HOST} !^www\.(.*) [NC]
       # Проверяем, не содержит ли домен www (в начале URL).
    #RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
       # Перенаправляем URL на домен c www.
    
    ############################################################################
    #### Убираем повторяющиеся слеши (/) в URL                              ####
    ############################################################################
    RewriteCond %{THE_REQUEST} //
       # Проверяем, повторяется ли слеш (//) более двух раз.
    RewriteRule .* /$0 [R=301,L]
       # Исключаем все лишние слеши.
    
    ############################################################################
    #### Убираем слеши в конце URL для статических файлов (содержит точку)  ####
    ############################################################################
    RewriteCond %{REQUEST_URI} \..+$  
       # Если файл содержит точку.
    RewriteCond %{REQUEST_FILENAME} !-d   
       # И это не директория.
    RewriteCond %{REQUEST_FILENAME} -f
       # Является файлом.
    RewriteCond %{REQUEST_URI} ^(.+)/$      
       # И в конце URL есть слеш.
    RewriteRule ^(.+)/$ /$1 [R=301,L]     
       # Исключить слеш.
    
    ############################################################################
    #### Добавляем слеш(/), если его нет, и это не файл.                    ####
    ############################################################################
    RewriteCond %{REQUEST_URI} !(.*)/$
       # Если слеша в конце нет.
    RewriteCond %{REQUEST_FILENAME} !-f
       # Не является файлом.
    RewriteCond %{REQUEST_URI} !\..+$
       # В URL нет точки (файл).
    RewriteRule ^(.*)$ $1/ [L,R=301]
       # Добавляем слеш в конце.
    
    ############################################################################
    #### Убираем index.php, если он есть в конце URL                        ####
    ############################################################################
    RewriteCond %{REQUEST_METHOD} =GET
       # Выявляем GET запрос в URL (не POST).
    RewriteCond %{REQUEST_URI} ^(.*)/index\.php$
       # URL cодержит index.php в конце.
    RewriteRule ^(.*)$ %1/ [R=301,L]
       # Удалить index.php из URL.
    
    ############################################################################
    #### Компрессия статического контента для гугл  спид тест               ####
    ############################################################################
    <IfModule mod_deflate.c>
      # Compress HTML, CSS, JavaScript, Text, XML and fonts
      AddOutputFilterByType DEFLATE application/rss+xml
      AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
      AddOutputFilterByType DEFLATE application/x-font
      AddOutputFilterByType DEFLATE application/x-font-opentype
      AddOutputFilterByType DEFLATE application/x-font-otf
      AddOutputFilterByType DEFLATE application/x-font-truetype
      AddOutputFilterByType DEFLATE application/x-font-ttf
      AddOutputFilterByType DEFLATE application/x-javascript
      AddOutputFilterByType DEFLATE application/xhtml+xml
      AddOutputFilterByType DEFLATE application/xml
      AddOutputFilterByType DEFLATE font/opentype
      AddOutputFilterByType DEFLATE font/otf
      AddOutputFilterByType DEFLATE font/ttf
      AddOutputFilterByType DEFLATE image/svg+xml
      AddOutputFilterByType DEFLATE image/x-icon
      AddOutputFilterByType DEFLATE text/css
      AddOutputFilterByType DEFLATE text/html
      AddOutputFilterByType DEFLATE text/javascript
      AddOutputFilterByType DEFLATE text/plain
      AddOutputFilterByType DEFLATE text/xml
      AddOutputFilterByType DEFLATE image/svg+xml
    </IfModule>
    <IfModule mod_expires.c>
      ExpiresActive on
      ExpiresByType image/jpeg "access plus 3 day"
      ExpiresByType image/svg "access plus 3 day"
      ExpiresByType image/gif "access plus 3 day"
      ExpiresByType image/png "access plus 3 day"
      ExpiresByType text/javascript "access plus 3 day"
      ExpiresByType text/css "access plus 3 day"
      ExpiresByType application/javascript "access plus 3 day"
    </IfModule>
    ############################################################################
    #### Конец общей части, далее следует собственные директивы .htaccess   ####
    ############################################################################
    Ответ написан
    1 комментарий
  • Как спроектировать систему подписок на сайте?

    @jazzus
    Второй вариант, без префиксов subscribe_ итак понятно, что от subscribers. И связь полиморфную, чтобы подписываться на кучу объектов с одним функционалом через трейт модели. для соцсетей актуально. В дальнейшем можно оптимизировать коунтерами итд
    Ответ написан
    Комментировать
  • Как спроектировать систему подписок на сайте?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    одна таблица subscribes с вот такой структурой:

    subscribe_id
    subscribe_author_id
    subscribe_object_id

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

    Если оставить в стороне нелепые вопросы "а для запроса на удаление тыщи записей какой-то другой SQL нужен?", и вернуться проектированию подписок, то, как правильно подсказывает Slava Rozhnev,

    Во-первых, в таблицу подписок необходимо добавить два составных индекса,
    subscribe_author_id, subscribe_object_id
    subscribe_object_id, subscribe_author_id
    и тогда ужасный запрос count(*) перестанет быть ночным кошмаром, а будет выполняться мгновенно

    А во-вторых, в неё можно добавить внешние ключи, которые будут ссылаться на таблицу users, с опцией каскадного удаления. Тогда отдельный запрос на удаление подписок и вовсе не придётся писать руками, достаточно будет удалить только юзера.

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

    LightAir
    @LightAir
    LA
    Ответ на этот вопрос есть в stackoverflow

    stackoverflow.com/questions/9550769/passing-additi...

    До 5.3
    class MyCallback {
        private $key;
    
        function __construct($key) {
            $this->key = $key;
        }
    
        public function callback($matches) {
            return sprintf('%s-%s', reset($matches), $this->key);
        }
    }
    
    $output = 'abca';
    $pattern = '/a/';
    $key = 'key';
    $callback = new MyCallback($key);
    $output = preg_replace_callback($pattern, array($callback, 'callback'), $output);
    print $output; //prints: a-keybca-key


    5.3 и выше (для лучшего понимания что к чему)
    $output = 'abca';
    $pattern = '/a/';
    $key = 'key';
    $output = preg_replace_callback($pattern, function ($matches) use($key) {
                return sprintf('%s-%s', reset($matches), $key);
            }, $output);
    print $output; //prints: a-keybca-key
    Ответ написан
    2 комментария
  • Как заменить все символы переноса только между тегами?

    @IS-Builder
    ~ PHP-8 & REGEXP - This is a really powerful kit ~
    Если тег параграфа невложенный:
    $line = "text <p>text \n\n   \n text   \n text </p> text  \n\n \n text";
    
    $line = preg_replace_callback(
        '~<p>[^<]+</p>~',
        function($m){
            return str_replace("\n", '<br>', $m[0]);
        },
        $line
    );
    
    echo $line;
    Ответ написан
    2 комментария
  • Как заменить все символы переноса только между тегами?

    @dodo512
    $line = "text <p>text \n\n   \n text   \n text </p> text  \n\n \n text\n";
    $line = preg_replace('#(?:^|</p>).*?(?:\z|<p>)(*SKIP)(*F)|\n#is', '<br />', $line);
    echo $line;
    Ответ написан
    3 комментария
  • Как вернуть 2 значения в PHP return?

    SerafimArts
    @SerafimArts
    Senior Notepad Reader
    Вариант 1 - Деструктуризация:
    // Возврат нескольких значений:
    function some() {
        return [23, 42];
    }
    
    // Получение
    [$a, $b] = some();
    
    \var_dump($a, $b);


    Вариант 2 - Деструктуризация с ключами:
    // Возврат нескольких значений:
    function some() {
        return ['a' => 23, 'b' => 42];
    }
    
    // Получение
    ['a' => $a, 'b' => $b] = some();
    
    \var_dump($a, $b);


    Вариант 3 - Генераторы с ключами:
    function some() {
        yield 'a' => 23;
        yield 'b' => 42;
    }
    
    foreach (some() as $key => $value) {
      echo $key . ':' . $value; // a:23 b:42
    }


    Вариант 4 - Генераторы без ключей:
    function some() {
        yield 23;
        yield 42;
    }
    
    foreach (some() as $value) {
      echo $value; // 23 42
    }


    Вариант 5 - Генераторы с возвратом:
    function some() {
        yield 23;
        return 42;
    }
    
    $value = some();
    echo $value->current(); // 23
    $value->next();
    echo $value->getReturn(); // 42


    Вариант 6 - DTO:
    class DataTransferObject
    {
        private $a;
        private $b;
    
        public function __construct($a, $b)
        {
            $this->a = $a;
            $this->b = $b;
        }
    
        public function getA()
        {
            return $this->a;
        }
    
        public function getB()
        {
            return $this->b;
        }
    }
    
    function some() {
        return new DataTransferObject(23, 42);
    }
    
    $value = some();
    echo $value->getA(); // 23
    echo $value->getB(); // 42


    И ещё куча всяких вариантов, но мне влом придумывать уже)
    Ответ написан
    4 комментария