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

    +155

    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
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    67. 67
    68. 68
    69. 69
    70. 70
    71. 71
    72. 72
    73. 73
    74. 74
    75. 75
    76. 76
    77. 77
    78. 78
    79. 79
    /**
         * Обновление информации о пользователе
         *
         * @param integer $user_id
         * @param array $data
         * @return Zend_Db_Statement_Pdo
         */
        public function updateProfile($user_id, $data)
        {
            // TODO: сделать человеческую валидацию
            $params = $keys = array();
    
            if ($data['login'] !== NULL) {
                $keys[] = 'u_login = ?';
                $params[] = $data['login'];
            }
    
            if (Zend_Validate::is($data['email'], 'EmailAddress')) {
                $keys[] = 'u_email = ?';
                $params[] = $data['email'];
            }
    
            if ($data['sname'] !== NULL) {
                $keys[] = 'u_sname = ?';
                $params[] = $data['sname'];
            }
    
            if ($data['name'] !== NULL) {
                $keys[] = 'u_name = ?';
                $params[] = $data['name'];
            }
    
            if ($data['fname'] !== NULL) {
                $keys[] = 'u_fname = ?';
                $params[] = $data['fname'];
            }
    
            if ($data['birthdate'] !== NULL) {
                $keys[] = 'u_birthdate = ?';
                $params[] = $data['birthdate'];
            } else {
                $keys[] = 'u_birthdate = NULL';
            }
    
            if ($data['city'] !== NULL) {
                $keys[] = 'u_c_id = ?';
                $params[] = (int) $data['city'];
            }
    
            if ($data['info'] !== NULL) {
                $keys[] = 'u_info = ?';
                $params[] = $data['info'];
            }
    
            if ($data['sign'] !== NULL) {
                $keys[] = 'u_sign = ?';
                $params[] = $data['sign'];
            }
    
            if ($data['sex'] === 'M' OR $data['sex'] === 'F') {
                $keys[] = 'u_sex = ?';
                $params[] = $data['sex'];
            }
    
            if ($data['subscribe'] === 'on' AND ($data['subtype'] === 'T' OR $data['subtype'] === 'H')) {
                $keys[] = 'u_subscribed = ?';
                $params[] = $data['subtype'] === 'T' ? 1 : 2;
            } else {
                $keys[] = 'u_subscribed = ?';
                $params[] = 0;
            }
    
            $sql = 'UPDATE users SET ' . implode(', ', $keys) . ' WHERE u_id = ' . (int) $user_id;
            $query = $this->db->query($sql, $params);
    
            $this->clearUserCache($user_id);
    
            return $query;
        }

    Запостил: nergal, 26 Августа 2010

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

    • //TODO: Нанять человеческого программиста
      //TODO: Выучить ООП, перестать юзать хеши хешей
      //TODO: Научится пользоваться константами
      //TODO: Научится отделять логику от DAO
      //TODO: Изучить prepared statemenets
      Ответить
      • все верно, но поправочка
        //TODO: Нанять человеческого программиста
        не нанимать парней с некоторых стран Азии
        Ответить
      • > хеши хешей
        у нас это называется "массив массивович"
        Ответить
      • а где здесь "хеши хешей"? насколько я вижу, два массива (оба одномерные)
        Ответить
        • эта идиома означает использование ассициативных массивов вместо объектов
          Ответить
    • в целом не вижу ничего плохого в использовании массивов, но копипаста действительно многовато
      Ответить
      • Особенно вот это круто:
        $keys[] = 'u_sex = ?'; //и такое повторяется стопицот раз
                    $params[] = $data['sex'];


        а Вы реально думаете что вместо объектов или структур лучше исползовать ассоциативные массивы?
        Ответить
        • А зачем там объекты, если реально удобнее использовать хэши? Структура данных - таблица, у неё нет ветвеления и иерархии - зачем объекты?
          Ответить
          • 1) если нужны какие-то действия с данными -- их можно поместить в тот же самый класс. Это называется "разместить данные и методы для работы с ними в одном классе". Очень популярный прием в мире ООП. Я бы сказал основной.:))
            2) Если опечататься, и вместо "sex" написать "six" (кстати пол по-английски будет "gender"), то у объекта PHP ругнется, что метода "getSix" нет. А так не ругется.

            Вообще честно говоря я так вот не готов взять, и одним постом объяснить приимущества объектно-ориентированого подхода. Тут нужно читать серию лекций.
            Ответить
            • имхо подход $a['prop'] равнозначен $o->prop, за некоторыми исключениями
              Ответить
              • ...описанных выше.

                Вы тоже не понимаете зачем применять ООП?
                Ответить
                • я не понимаю, зачем его применять вот совсем-совсем везде.
                  Если мы организовываем только структуру данных (как вот struct в С или record в Pascal) и нам не нужны действия с ними, то за ДРУГИМИ некоторыми исключениями подходы равнозначны.
                  Но если вдруг нам нужны и действия, то, конечно, лучше связать их с данными в традициях ООП
                  Ответить
                  • Это не структура и не запись. Это -- ассоциативный массив.
                    Причем он не только в DAO, но и в бизнес-логике (хотя они тут и перемешанны).

                    Вы в джаве тоже Map используете вместо DTO? А в .NETе -- Dictionary?
                    Ответить
                    • в пхп настолько убогая обьектная модель, что именно в пхп предпочитаю продолжать использовать ассоциативные массивы, если не вижу выгоды от ООП подхода.
                      в джаве противоположная ситуация: предпочтительнее создать POJO сущность, поля и аксессоры, а Картами пользоваться только если требуется динамичность
                      Ответить
                      • Что мешает в PHP сделать объект?
                        phpstorm даже геттеры и сеттеры умеет генерить.

                        Знаю-знаю, необходимость его подключения, правда?
                        Ответить
                        • усилия при взаимодействии с другими данными. Например, запрос из мускула мне вернет ассоц.массив, с 20, к примеру, полями. значит, если я хочу использовать ООП, то написать такой класс, инитиализировать... Потом, допустим, мне нужно эти данные вставить в виде массива - опять производим "обратное преобразование"... И это все с учетом того, что процесс должен быстро выполнить свою задачу и умереть
                          Ответить
                          • ну во-первых есть mysql_fetch_object.)
                            Ответить
                            • который вернет обьект с аксессорами, да? :)
                              Ответить
                              • нет, но даже это будет лучше.

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

                                  А кроме того, можно воспользоваться ORM
                                  Ответить
                                  • Зато классы, которые работают с этими объектами можно параметризовать моками и оттестировать, например.

                                    Потому что обращение к свойству можно переопределить (__get)
                                    Ответить
                              • кстати таки да
                                с помощью __get -- мы получим их практически с аксессорами
                                Ответить
                                • ох, не трогайте волшебные методы )
                                  Ответить
                                  • Это эмуляция аксессоров/мутаторов и (страшно сказать!) в некотором смысле позволяет сэмулировать Properties в C#.
                                    Ответить
                                    • знаю, я с ними всяк игрался. даже сделал класс-обертку навроде jquery, т.е. можно писать выверты вроде $w=$w('a'): $w[0]->strlen()->value() // даст 1
                                      Ответить
            • 1. В данном конкретном случае класс - модель с пачкой методов, вроде getUser(), addUser() и т.д. Если создавать дополнительные структуры данных для каждого набора входных параметров в метод, то кол-во классов в проекте станет просто мягко говоря неоправданным. Если же просто брать данные, как объект, т.е. "$object = (object) $array;", но ничего не измениться, кроме способа доступа к данным, с $array['value'] на $object->value. А расширять проект внедрением ORM, либо реально кошерными структурами с методами доступа к данными и инкапсулированными свойствами - нужно время на рефакторинг, если это не закладывалось в первоначальном архитектурном дизайне. А со временем, думаю, знаете как всегда получается.
              2. Вы не внимательны - если в хэше не будет ключа sex, то он не пройдет по условию (хотя, по-хорошему там следовало бы добавить isset()) и не добавиться в запрос.

              Объектно-ориентированный подход - это, конечно-же хорошо, но не стоит его применять полностью везде, как уже сказал Lure Of Chaos.
              Ответить
              • Почему пэхэпэшники так боятся большого количества классов?
                Ответить
                • А зачем создавать их там, где не попадя? Если у нас структура данных встречается в одном-единственном методе, зачем её организовывать в класс? Зачем тогда массивы вообще придуманы?
                  Ответить
                  • Какое отношение массив имеет к классам?
                    Вы наверное имеете ввиду ассоциативный массив? Так вот он сделан для динамически изменяющихся данных.
                    Ответить
                • чисто по-человечески я их понимаю...
                  Ответить
                • Потому что в API PHP не принято использовать ООП, да и подключать каждый раз классы неудобно
                  Ответить
          • Вот наглядный пример. Представим себе пользователя - у него есть first name и last name. Представим его в двух реализациях, в виде объекта класса User и массива $user. Внезапно нам понадобилось выводить некоторое виртуальное св-во 'full name'. Итого получаем:
            $user = array('first_name' => 'Vasya', 'last_name' => 'Pupkin');
            return $user['first_name'] + $user['last_name'];
            
            $user = new User(array('first_name' => 'Vasya', 'last_name' => 'Pupkin'));
            return $user->fullName();


            Т.е получается, что в случае с объектом мы реализовали совсем простой и функциональный интерфейс. А представьте теперь, что у пользователя есть какой-то счёт/аккаунт в торговой системе, и нужно вывести его баланс, а для этого нужно приконнектиться к удалённой торговой системе и спросить этот самый баланс. Какой интерфейс вы будете использовать, уже определились?
            Ответить
            • Это всё верно, но в данном случае, как Вы видите, идёт апдейт профиля, следовательно на входе - не объект пользователя, а данные, полученные из запроса - они могут быть как полными (пользователь поменял всю информацию о себе), так и заполненными частично (например, изменил город). Структура User на входе (если я правильно понял, Вы предлагаете в ней хранить все данные о пользователе и методы для работы с ним) не подходит для этих целей, поскольку потеряет целостность. Да и формировать объект из непроверенных данных (если пользователь впишет почту в поле даты рождения, например) - не комильфо. В остальных же случаях, для представления именно пользователя (а не частичных данных о нём), естественно, предпочтительнее использовать указанный Вами вариант.
              Ответить
              • Про целостность не понял совсем, ну да ладно.
                Во всех приличных фреймворках за валидацию отвечает ORM - это централизованно, удобно и "правильно", как я поясню ниже. Один из вариантов:
                try {
                  $user = new User($params['user']);
                  $user->save();
                } catch (ValidationFailed $e) {
                }

                Честно говоря смотря на код, не вижу почему нельзя было бы сделать как в примере выше. Данные на входе - это данные пользователя. В каком виде они должны храниться и что из себя представлять (структура, формат, допустимые значения) должен знать сам объект класса User, а не какой-то там хитрый кастомный валидатор в виде массива.
                Ответить
                • ОRM - удобно с точки зрения сопровождения и разработки, но с точки зрения производительности - зачастую не слишком хорошо. В ранних стадиях на проекте, из которого вынут кусок кода выше (осмелюсь заявить, что таких мест там всего 2-3 штуки), использовалась Doctrine, но по ряду причин, как невозможность строить реально тяжелые запросы (например с CASE и IF конструкциями внутри), обилие и нерациональность этих запросов и пр. пришлось отказаться от неё в пользу таких вот моделей - набор методов с plain-sql запросом внутри каждого. Со стороны контроллера обычно это приблизительно так и выглядит, как описали Вы.
                  Ответить
                  • ORM мапит данные из реляционной БД в объекты. Запросы можно писать вручную.
                    Ответить
            • return $user['first_name'] + $user['last_name'];

              вернет 0
              Ответить

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