1. PHP / Говнокод #26698

    +1

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    <?php
        echo count($arr);
        $i = count($arr) - 1;
        for ($i; $i >= 0; $i--) {
        ?>
        <div class="post" id="p<?php echo $arr[$i]->_id; ?>">
          <div class="p_title"><?php echo $arr[$i]->title; ?></div>
          <div class="p_content"><?php echo $arr[$i]->content; ?></div>
          <div class="p_date"><?php echo $arr[$i]->date; ?></div>
          <form id="<?php echo $arr[$i]->_id; ?>" action="index.php" method="get">
            <!--<textarea rows="4" cols="50" name="removid" style="display: none;" ><?php echo $arr[$i]->_id; ?></textarea>-->
              <input type="text" name="removid"  form="<?php echo $arr[$i]->_id; ?>" value="<?php echo $arr[$i]->_id; ?>"/>
            <input type="submit" class="p_remove" onclick="dele('<?php echo $arr[$i]->_id; ?>');" form="<?php echo $arr[$i]->_id; ?>" value="Удалить"/>
          </form><!--</div>-->
          <?php echo $arr[$i]->_id; ?>
        </div>
        <?php
        }
        ?>
    
    <script>
          function dele(param){
            var jsVar = "<?php
            $removid = $_GET['removid'];
            $bulk = new MongoDB\Driver\BulkWrite;
            //$bulk->delete(['_id'=> new MongoDB\BSON\ObjectId($removid)]);
            $query = new MongoDB\Driver\Query(['_id'=> new MongoDB\BSON\ObjectId($removid)]);
            $bulk->delete(['_id'=> new MongoDB\BSON\ObjectId($removid)]);
            $writeConcern = new MongoDB\Driver\WriteConcern(MongoDB\Driver\WriteConcern::MAJORITY, 1000);
            try {
              $result = $manager->executeBulkWrite('forum.posts', $bulk, $writeConcern);
              //header('Location: https://benar.wtf/index.php');
    
            }
            catch (MongoDB\Driver\Exception\BulkWriteException $e) {
              $result = $e->getWriteResult();
            }
    
            ?>";
    
    
          }
    
        </script>

    Сделал вещь

    Запостил: bodix, 27 Мая 2020

    Комментарии (37) RSS

    • С точки зрения программиста этот код -- полное дерьмо, его надо просто выкинуть, а его автору запретить писать код навсегда.

      Но с точки зрения ПХП разрабочтика это самый обычный код.


      Ментальная разница
      Ответить
    • Идеальный говнокод.

      Начнём с того, что т со второй строки. Куда выведется это echo count($arr);? В каком блоке оно окажется?

      Далее: закомментированный HTML-код (<!--) в шаблоне лучше не оставлять. Это приводит к трудноуловимым ошибкам в вёрстке. Сам на такое

      onclick="dele... тоже не рекомендуют. Лучше в HTML оставить разметку, а обработчики событий навесить отдельным скриптом после загрузки страницы (google: «ненавязчивый js», «unobtrusive js»). Хотя в принципе пойдёт.

      Всё выше — это мои придирки. А теперь о серьёзном. Кошмар начинается на 24-й строке. Код для обращения к СУБД прямо в шаблоне да ещё и в том месте, где должна быть константа для js. Не надо так. Что в итоге сохранится в jsVar?

      Ну и наконец, значение $removid, полученное как $_GET['removid'], никак не проверяется, да?

      В общем, классика: «just stringing random characters together until it compiles».

      Годно.
      Ответить
      • >Что в итоге сохранится в jsVar?
        Notice
        Ответить
      • А по делу есть что сказать?
        Ответить
        • >А по делу есть что сказать?

          Это хороший аргумент.
          Вот тебе еще немного

          1.Код может и не идеальный, зато понятный в отличие от других языков
          2. Ой, можно подумать на ваших С++ было бы лучше
          Ответить
          • Это правда, переведи этот код на плюсы и поймешь, что они не нужны
            Ответить
            • В С++ я взял бы шаблонизатор, и разумеется код получился бы в тысячу раз лучше
              И на любом другом языке -- тоже

              Вообще сложно представить кейс, когда переписывание кода с ПХП на любой другой язык не сделает код в тысячу раз лучше
              Ответить
          • Давно не брал я в руки PHP, поэтому для меня кажется тупизной генерить JS из PHP (ну кроме тривиальных примеров и отладки всякой).
            Либо по-старинке генеришь html на PHP с обычными формами, либо html, js-скрипты и RestAPI отдельно.
            Ответить
            • На «PHP» можно генерировать «JSON» или «JSONP», которые будут потребляться «JS». А вот генерировать произвольный код на «JS» из «PHP» обычно и вправду не нужно.
              Ответить
        • Напишу по делу. В коде для вычисления начального значения jsVar есть строка:
          $bulk->delete(['_id'=> new MongoDB\BSON\ObjectId($removid)]);

          Судя по названию функции, автор ожидает, что этот пыхокод будет выполняться по вызову js-функции dele, т. е. по клику пользователя.

          На самом же деле этот код будет выполняться при каждой загрузке страницы, ещё до того, как пользователь куда-нибудь кликнет.

          Однако, это может работать, если атрибут action у формы указывает на эту же страницу. Просто когда никаких GET-параметров не передавали, на 24-й строке (где $removid = $_GET['removid'];) вылезет нотис, а в «MongoDB» передастся null, поэтому ничего не удалится. А когда пользователь нажмёт кнопку отправки формы, произойдёт отправка GET-запроса (поскольку функция dele НЕ возвращает false), и код, размещённый с 23-й строки получит нужный GET-параметр.

          Итак, обезьяна, написавшая этот код, не думает о том, что исполняется у клиента, а что на сервере, и течёт, а код оказался рабочим (хотя и с пачкой нотисов) по счастливой случайности. Именно поэтому я за «PHP».

          Чуть не забыл: использовать метод GET для удаления данных не рекомендуется. Метод POST тут был бы более уместен.
          Ответить
          • Чтоб было совсем наглядно: оригинальный код функционально эквивалентен такому:
            <?php
                echo count($arr);
                $i = count($arr) - 1;
                for ($i; $i >= 0; $i--) {
                ?>
                <div class="post" id="p<?php echo $arr[$i]->_id; ?>">
                  <div class="p_title"><?php echo $arr[$i]->title; ?></div>
                  <div class="p_content"><?php echo $arr[$i]->content; ?></div>
                  <div class="p_date"><?php echo $arr[$i]->date; ?></div>
                  <form id="<?php echo $arr[$i]->_id; ?>" action="index.php" method="get">
                    <!--<textarea rows="4" cols="50" name="removid" style="display: none;" ><?php echo $arr[$i]->_id; ?></textarea>-->
                      <input type="text" name="removid"  form="<?php echo $arr[$i]->_id; ?>" value="<?php echo $arr[$i]->_id; ?>"/>
                    <input type="submit" class="p_remove" form="<?php echo $arr[$i]->_id; ?>" value="Удалить"/>
                  </form><!--</div>-->
                  <?php echo $arr[$i]->_id; ?>
                </div>
                <?php
                }
            
                    $removid = $_GET['removid'];
                    $bulk = new MongoDB\Driver\BulkWrite;
                    //$bulk->delete(['_id'=> new MongoDB\BSON\ObjectId($removid)]);
                    $query = new MongoDB\Driver\Query(['_id'=> new MongoDB\BSON\ObjectId($removid)]);
                    $bulk->delete(['_id'=> new MongoDB\BSON\ObjectId($removid)]);
                    $writeConcern = new MongoDB\Driver\WriteConcern(MongoDB\Driver\WriteConcern::MAJORITY, 1000);
                    try {
                      $result = $manager->executeBulkWrite('forum.posts', $bulk, $writeConcern);
                      //header('Location: https://benar.wtf/index.php');
            
                    }
                    catch (MongoDB\Driver\Exception\BulkWriteException $e) {
                      $result = $e->getWriteResult();
                    }
            
                    ?>


            Удаляем атрибут onclick и теги <script>, </script> (оставив то, что было в кавычках), в итоге код работает точно так же.
            Ответить
          • Какой багор )))

            Кстати, полезно было бы иметь какую-то РПЦ для того, чтобы такое работало. Только синтаксис поудобнее - чтобы меньше вопросушни.

            Либо вложенные блоки <client> и <server>, либо вообще полная неявнушня:
            <html>
              <body>
                <h1>Pituxes</h1>
                <?
                  var d = loadData();
                  for (var i=0; i<d.length; i++) ?>
                  <p><? i + ' ' + d[i].name + ' ' + d[i].pitux ?></p>
                <?
                  const mysql = require('mysql');
                  const fs = require('fs');
                  
                  function loadData() {
                    return mysql.exec('select name, pitux from pituxes');
                  }
                  
                  function readFile(user) {
                    assert(/^[a-z0-9]+$/.test(user));
                    return fs.readFileSync('/etc/pituxes/' + user)
                  }
                  
                  function $(s) {
                    return document.querySelector(s);
                  }
                  
                  $('input.pituzz').addEventListener('click', event => {
                    $('textarea').value = readFile($('input.name').value);
                  });
                ?>
                
                <h1>Me</h1>
                <input type="text" class="name" value="perdolia" />
                <input type="button" class="pituzz" value="PITUZZ" />
                <textarea></textarea>
              </body>
            </html>


            Приложение понимает, какой список функций есть у клиента или сервера, и вызывает их при наличии. Рефлексия и эквивалентность [] и . убраны по максимуму. Компилятор старается объединить или переставить блоки так, чтобы управиться минимумов запросов. Никаких явных запросов нет, только вызовы функций. Асинхрушня спрятана под капотом. Есть стратегии компиляции - "больше на сервере", "больше на клиенте", "минимум передачи данных" и хинты "server function() {}", "client function() {}".
            Ответить
            • Ничего не понял. Именно поэтому я за «PHP».

              Кстати, в ASP.NET есть атрибуты runat="server" и runat="client". Как они работают? Какой в итоге HTML- и JS-код получает клиент и что отправляется от клиента серверу?
              Ответить
              • >Как они работают?

                <script runat="server">
                </script>

                это тоже, что

                <?
                ?>
                в пых

                а

                <script runat="client">
                </script>

                превращается в
                <script>
                </script>
                Ответить
                • Допустим. А какой смысл в <button runat="server"> ?
                  Ответить
                  • Эта кнопка сохраняет свой стейт на сервере и там же обрабатываается

                    По сути нажатие её это сабмит формы и вызов обраточика на сервере
                    Ответить
                    • Т. е. пользователь получает просто <button> (возможно, в форму что-то втыкается, чтобы можно было отличить эту кнопку от других), а на сервере запрос, который отправляет форма, перехватывается, и вне очереди вызывается назначенный нами обработчик. Так?
                      Ответить
                      • Рассмотрим простое приложение, состоящее из одной странички веб-формы.

                        У нас есть файлы
                        * SomePage.aspx: сама форма (щаблон)
                        * SomePage.aspx.cs: т.н. Code Behind: сюда идет код для ее обработки
                        * SomePage.aspx.designer.cs: Это автогенеренный код (он будет генерится, когда я буду править шаблон), он мерджится с кодом в Code Behind.

                        Используются partial классы C#: часть класса описана в одном файле, часть в другом. До 2008 так было нельзя, и генерился код прямо в Code Behind.

                        SomePage.aspx:
                        <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="SomePage.aspx.cs" Inherits="WebApplication1.SomePage" %>
                        
                        <!DOCTYPE html>
                        
                        <html xmlns="http://www.w3.org/1999/xhtml">
                        <head runat="server">
                            <title></title>
                        </head>
                        <body>
                        
                        <form runat="server">
                            <button runat="server" OnServerClick="ButtonClicked">Click me</button>
                            <input runat="server" id="Display" value="0"/>
                        </form>
                        
                        </body>
                        </html>

                        "WebApplication1.SomePage" это класс в SomePage.aspx.cs, который наследует эта страница.

                        "ButtonClicked" -- метод того класса.
                        "Display" его Property, правда его автоматом сгенерила студия в SomePage.aspx.designer.cs когда я прописал ID.


                        продолжение следует
                        Ответить
                        • ----
                          SomePage.aspx.cs
                          using System;
                          using System.Web.UI;
                          
                          namespace WebApplication1
                          {
                              public partial class SomePage : Page
                              {
                                  protected void Page_Load(object sender, EventArgs e)
                                  {
                                  }
                          
                                  protected void ButtonClicked(object sender, EventArgs e)
                                  {
                                      var currentValue = short.Parse(Display.Value);
                                      Display.Value = (currentValue + 1).ToString();
                                  }
                              }
                          }

                          Тут виден наш метод, который вызовется, а образение к проперти Display.

                          SomePage.aspx.designer.cs
                          //------------------------------------------------------------------------------
                          // <auto-generated>
                          //     This code was generated by a tool.
                          //
                          //     Changes to this file may cause incorrect behavior and will be lost if
                          //     the code is regenerated. 
                          // </auto-generated>
                          //------------------------------------------------------------------------------
                          
                          namespace WebApplication1 {
                              
                              
                              public partial class SomePage {
                                  
                                  /// <summary>
                                  /// Display control.
                                  /// </summary>
                                  /// <remarks>
                                  /// Auto-generated field.
                                  /// To modify move field declaration from designer file to code-behind file.
                                  /// </remarks>
                                  protected global::System.Web.UI.HtmlControls.HtmlInputText Display;
                              }
                          }

                          Вот наше проперти.


                          продолжение следует
                          Ответить
                          • При нажатии на кнопку число растет.
                            В HTML форма выглядит так
                            <form method="post" action="./SomePage" id="ctl01">
                            <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
                            <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
                            <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="n6T+n2lrjcDu8RIcHzEwFtv9FC7WKOJLElLatmR48aowClJrKFCWuyJHOIPu6laRGPjnTZ7h5H5H/BwmVeto5DR/utQFY9gM58BUBbHVE+g=" />
                            
                            <script type="text/javascript">
                            //<![CDATA[
                            var theForm = document.forms['ctl01'];
                            if (!theForm) {
                                theForm = document.ctl01;
                            }
                            function __doPostBack(eventTarget, eventArgument) {
                                if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
                                    theForm.__EVENTTARGET.value = eventTarget;
                                    theForm.__EVENTARGUMENT.value = eventArgument;
                                    theForm.submit();
                                }
                            }
                            //]]>
                            </script>
                            
                            
                                <button onclick="__doPostBack('ctl03','')">Click me</button>
                                <input name="Display" type="text" id="Display" value="3" />
                            </form>

                            В INPUT зашит стейт объектов.
                            Ответить
                            • И ксьаьи не путайте ASP.NET и asp.

                              В asp был только <script runat=server
                              В asp.net есть формы и code behinв
                              Ответить
                              • Да, могут ведь напутать. Скажут, что никакой он не «ASP.NET», а «ASP».

                                Спасибо. Теперь ясно, откуда берутся «ctl» с цифрами на сайтах.

                                Я подозревал, что через input type="hidden" должно что-то добавляться, чтобы опознать нажатую кнопку. Значит, ещё добавляется скрипт на стороне клиента, чтобы корректировать это скрытое значение, если кнопок в форме много.
                                Ответить
                                • Да, примерно так.

                                  Общий смысл в том, что ты пишешь так, словно бы у тебя обычная винформа, а не веб.

                                  Нажал кнопк -- вызвался код на C#. Можно переиспользовать веб-форм макак в задачах для веба
                                  Ответить
                                  • А случайно не привычка к runat="server" приводит к деформации, когда вебмакака не знает, где исполняется код на других платформах: на сервере или на клиенте?

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

                                      Был WinForms, стал WebForms.

                                      Кстати, веб-формы (эта питушня так и называется WebForms) -- не единственный "фреймворк" под ASP.NET.

                                      Можно писать и без них. Можно писать более низкоуровнево, обрабатывая HTTP запросы, и был еще MVC.NET.

                                      Формы, внезпано, действительно удобны иногда: вот у тебя есть база данных, и тебе нужно дать питузу возможность получить из нее таблицу

                                      Как ты понимаешь, есть готовый компонент под фомры, который эту таблицу выводит, и он ничем не отличается (с точки зрения питуха) от такого же компонента для винфомы:)
                                      https://docs.microsoft.com/en-us/dotnet/api/system.web.ui.webcontrols.datagrid?view= netframework-4.8
                                      Ответить
                            • Кстати, document.forms['ctl01'] вместо document.getElementById('ctl01') — это же DOM1 или вообще DOM0. Какой антиквариат )))
                              Ответить
              • Я предлагаю всю логику писать в одном месте, а решение о том, что пойдёт на клиент и сервер и как между ними пойдут данные - отдать компилятору.

                Такой подход позволит меньше пердолиться по поводу взаимодействия, быстро писать небольшие сайты и прототипы. Если развить инструменты (хинты и другие средства языка, подсказки компилятора), то можно будет писать на таком и приложения побольше.

                Например,
                var x = readFile('xxx');
                var y = $('y').attr('pituz');
                var z = loadDB('z');
                $('x').text(x+y+z);

                можно решить за один запрос. Поскольку x, y, z ортогональны, можно переставить их получение и собрать получение x, z в один запрос к серверу.
                Ответить
                • По-моему ты сейчас DCOM заново изобретаешь. Там тоже было похуй на какой стороне находится объект, ты просто вызываешь его методы и течёшь. А система сама проксирует эти вызовы на другую сторону если надо.
                  Ответить
                  • Странно, что такую питушню не завезли в веб. От смузихлёбов слышно только про пердолинг с асинками, реактивнушню и 1001й инструмент для решения проблем, которые создал 1000й, созданный для решения проблем 999го, ... А самое главное, что нужно для написания кода, не используется.
                    Ответить
                  • Когда ты итерируешься по массиву в тысячу элментов, и у каждого дергаешь метод, передавая туда десять килобайт даннных, и сам ты при этом в Москве, то совсем не важно конечно где находятся объекты: в адресном пространстве твоего процесса или на удаленной машине в Киото
                    Ответить
                    • Какой багор )))

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

    Добавить комментарий