За последние 24 часа нас посетили 21969 программистов и 995 роботов. Сейчас ищут 703 программиста ...

Как быстро освоить PHP

Тема в разделе "PHP для новичков", создана пользователем fenix_63, 16 мар 2015.

  1. HeuPoH

    HeuPoH Новичок

    С нами с:
    2 фев 2017
    Сообщения:
    16
    Симпатии:
    0
    @mkramer@Fell-x27 я его использовал, чтоб исходный код страницы не был в каше. я немного запутался, то есть PHP_EOL использовать вообще нет смысла как и перевод строки \n?
     
  2. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    Нет смысла, если не для вывода в консоль или лог.
     
  3. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.155
    Симпатии:
    1.769
    Адрес:
    :сердА
    Исходный код нет смысла причесывать. Браузеры умеют делать это постфактум при просмотре, DOM-дерево в отладчике и так всегда красивое, плюс можно копипастить код из ответа сервера в IDE и там применять автоформатирование. Как ни крути, отдавать браузеру символы переноса не нужно.
     
  4. HeuPoH

    HeuPoH Новичок

    С нами с:
    2 фев 2017
    Сообщения:
    16
    Симпатии:
    0
    #404 HeuPoH, 8 мар 2017
    Последнее редактирование модератором: 8 мар 2017
  5. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.553
    Симпатии:
    1.754
    Ну хотя я это знаю, я не ставлю их удаление специально из HTML, мне кажется, сейчас это не сильно много смысла имеет. У меня они есть не потому, что я их специально вывожу, а потому что я выключаю режим PHP
     
  6. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.155
    Симпатии:
    1.769
    Адрес:
    :сердА
    Ну, я тоже их не выпиливаю, если они естественным путем образовались. Если где-то есть HTML, то в нем и отступы есть, и переносы, но это имеет свой смысл - так проще с ним работать в IDE. А вот добавлять специально переносы там, где смысла в них нет не нужно. Это, наверное, более правильная формулировка. Хотя, по-хорошему, советуют весь отдаваемый HTML минифицировать. Но это уже от ситуации плясать надо.
     
  7. TeslaFeo

    TeslaFeo Старожил

    С нами с:
    9 мар 2016
    Сообщения:
    2.989
    Симпатии:
    759
    никак
     
    SamyRed нравится это.
  8. acho

    acho Активный пользователь

    С нами с:
    28 дек 2016
    Сообщения:
    854
    Симпатии:
    210
    Адрес:
    Санкт-Петербург
  9. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.155
    Симпатии:
    1.769
    Адрес:
    :сердА
    Открыл видео. Увидел, "экспертное видео" с Brakets в качестве IDE. Закрыл видео.
     
    askanim, mahmuzar, SamyRed и 3 другим нравится это.
  10. acho

    acho Активный пользователь

    С нами с:
    28 дек 2016
    Сообщения:
    854
    Симпатии:
    210
    Адрес:
    Санкт-Петербург
    Я там так мельком глянул. Слово "эксперт" на странице ну просто в топ выведен, на сайте продают книжечки всякие с дисками, включая "Как продлить половой акт" за 2 тыщи. Бгг.
    А, ну гугл и яндекс в партнёрах, 50/50 делят прибыль походу.
    Угарненько.
     
    denis01 нравится это.
  11. jicool

    jicool Новичок

    С нами с:
    25 мар 2017
    Сообщения:
    20
    Симпатии:
    0
    Не знаю способа изменить значения кнопок ((
    И так же хотел через цикл с таблицей вывести много чисел 0 , чтобы они все записались в БД, но чтобы они были строго ограничены рамками экрана и замещали его полнстью..
    Есть подсказки?) Только для новичка )
     
  12. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.553
    Симпатии:
    1.754
    Не надо менять значения кнопок (хотя ничего сложного), просто - пользователь залогинился, вывелись другие кнопки
    А по-русски? И главное, как это всё соотносится с задачей суриката?
     
  13. TeslaFeo

    TeslaFeo Старожил

    С нами с:
    9 мар 2016
    Сообщения:
    2.989
    Симпатии:
    759
    это уже другая страница. Типа, личный кабинет.
     
  14. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.155
    Симпатии:
    1.769
    Адрес:
    :сердА
    Что это должно дать?
    --- Добавлено ---
    Ну так там же будет отправка формы, с последующей перезагрузкой страницы, верно? Вот ты эти данные прими, и, если все ок и пользователь залогинился, ты отдавай новую страницу. С новыми кнопками. "Меняется" - это то, что видит пользователь, а не то, что прям интерактивно должно на странице меняться. В задании стоит отдельным пунктом ограничение на использование JS. Оно тоже не просто так. Если ты начал загоняться и видишь решение, для которого нужен код на клиенте, то, в данном случае, это решение неправильное. Ищи другое.
     
  15. kirroyal

    kirroyal Новичок

    С нами с:
    5 дек 2016
    Сообщения:
    12
    Симпатии:
    2
    Всем доброго времени суток.
    Вот и я выполнил это задание и хочу критики.
    Мне интересно не только выполнил я задание или нет, но и если несложно, то прокомментируйте качество кода, в каких местах хочется выколоть себе глаза или отрубить автору руки.
    Это мой первый учебный проект на php и конструктивная критика важна.
    https://github.com/Wheiss/suricat
    https://suricat.000webhostapp.com/
     
  16. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.553
    Симпатии:
    1.754
    Ну из первого, что бросается в глаза - пароль светишь даже в куках. Нафига? Во-первых, там не было задания на галочку "оставаться в системе", а во-вторых, это тоже не делается через засвечивание пароля в куках
     
    denis01 нравится это.
  17. kirroyal

    kirroyal Новичок

    С нами с:
    5 дек 2016
    Сообщения:
    12
    Симпатии:
    2
    Спасибо за коммент.

    Я думал это из само-собой разумеющегося.
    Сегодня редко увидишь сайт, где нет как минимум возможности "оставаться в системе".

    Как следствие я теперь точно знаю, что стоит погуглить, как же правильно сохранять пароли или данные входа в куках. Думал сначала хеш от пароля хранить, но потом почему-то подумал, что легкая доступность кук это не моя проблема, а того, кто их хранит:D
     
  18. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.553
    Симпатии:
    631
    То есть ты настолько самоуверен, что твои админские куки никогда не сопрут? )))
     
  19. kirroyal

    kirroyal Новичок

    С нами с:
    5 дек 2016
    Сообщения:
    12
    Симпатии:
    2
    Я ни капли не самоуверен.

    Выполнил это задание как раз для того, чтобы разобраться, в какие стороны нужно копать, чтобы реализовывать вещи правильно.

    Пока что у меня в голове мысли о том, что нужно как можно глубже разбираться в том, как правильно строить архитектуру приложения, и как не делать дыры в безопасности.
     
  20. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.553
    Симпатии:
    1.754
    Галочка "Оставаться в системе" реализуется генерацией случайного токена. Этот токен записывается в базу данный, ассоциированный с id пользователя, и в куки.
    --- Добавлено ---
    Хешь пароля тоже светить не стоит. Хотя с использованием современных методов разгадать его очень трудно, но вдруг у кого-то таки получится.
     
  21. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    а если пойти дальше и постараться предотвратить атаку по вермени, то в базу надо писать случайный идентификатор токена, и токен. В бд писать идентификатор токена и токен. Выборку делать по идентификатору, а сравнивать значение токена постоянной по времени сравнивалкой. Иначе можно статистически анализируя задержки выборки подобрать.

    А если пойти ещё дальше, то не стоит хранить в базе идентификатор в открытом виде, ведь иначе тот, кто получит доступ к бд, сможет зайти под любым запомненым юзером. Нужно посчитать хеш пароля функцией password_hash(), и уже его сохранять в базу. Проверять как пароль.
     
    denis01 нравится это.
  22. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.155
    Симпатии:
    1.769
    Адрес:
    :сердА
    1) Про пароль в куке уже было все сказано, так делать не надо. Но что еще не надо делать - так это хранить пароль в сессии. Даже хэш. Зачем? Каждый раз аутентификацию проводить? Проще в той же сессии поставить флаг, мол, юзер вошел, все ок, права такие-то.

    2)
    PHP:
    1. spl_autoload_register(function ($class)
    2. {
    3.     $array_paths = array(
    4.         '/models/',
    5.         '/components/'
    6.     );
    7.     foreach ($array_paths as $path) {
    8.         $path = ROOT . $path . $class . '.php';
    9.         if (is_file($path)) {
    10.             include_once $path;
    11.         }
    12.     }
    13. });
    Я, в общем, понимаю логику, но перебирать подряд все возможные пути, до тех пор пока не наткнемся на файлик - это не самое лучшее решение, как мне кажется. У меня, к примеру, архитектура такова, что каждый модуль хранится в папке...с именем модуля. И класс, который этот модуль реализует, тоже называется так же. При этом используется парадигма "все есть модуль". В итоге, если надо дернуть, хз, модуль "builder", я просто дергаю, грубо, "/modules/builder/main.php"
    Это решение уровня архитектуры. Еще иногда практикуется добавление в имя класса постфикса, определяющего его тип, чтобы по постфиксу определять путь. Еще можно отдельно в системе хранить массив зарегистрированных в системе классов и путей к ним. И в автолоаде просто дергать путь из такого массива. Вариантов много. Стучаться же по каталогам с вопросом "а такой-то файл тут живет, не?" - спорное решение.

    3)
    PHP:
    1. $params = include($paramsPath);
    Вот так цеплять что либо вообще нежелательно. Использование include в таком ключе это экзотика и костыль сродни goto. В итоге получается какой-то недовызов недофункции. Include лучше использовать по назначению - для линковки кода. В твом случае, чем возвращать таким образом массив, правильнее было бы описать конфиг в виде статического класса и обращаться к его свойствам. Да и само по себе такое решение чище.

    4) В логауте:
    PHP:
    1. header('Location: /auth');
    2.         die;
    3.         return true;
    Ты уж определись :) IDE бы сразу на такой код ругнулась, потому что строчка с ретурном это "недостижимый код".

    5)
    PHP:
    1. $query = "SELECT * FROM users WHERE login = '$this->login'";
    2. $query = $db->prepare($query);
    3. $query->execute();
    SQL-инъекция. И дальше везде, где юзаешь БД, у тебя дыры. То есть, ты, конечно, используешь PDO->prepare(), но от этого нет никакого толка. Как работает prepare? Что ты подготовил в этом запросе? И как ты использовал эту подготовку? Ничего и никак. Перечитай еще раз доку.

    6) Ты в одной функции посылаешь запрос по всем полям users, чтобы узнать, существует ли такой логин. Потом в другой функции посылаешь запрос с теми же условиями к той же users, но только по полю password, чтобы узнать, какой у него был пароль. При том, что ты его и так вытащил в первом запросе, если тот оказался удачным. Так почему бы просто не тянуть все одним запросом?

    7)
    PHP:
    1. if($this->loginExists($this->login, $error_array)) {
    2.             //    Проверяем соответствие пароля
    3.             $this->passwordMatches($this->login, $this->password_hash, $error_array);
    4.             if(empty($error_array)) {
    5.                 return true;
    6.             }
    7.             else {
    8.                 return false;
    9.             }
    10.         }
    Почему бы просто не поставить вызовы проверяющих функций в одно условие через && ?

    8) Проверка на занятость логина тоже идет через select. Почему бы на уровне базы не сделать поле с логином уникальным, и, при попытке регистрации, просто не отдавать базе запрос на запись нового логина? Вернет окей, значит все хорошо. Вернет ошибку нарушения уникальности - упс, логин занят. Это же не ошибка синтаксиса. Этого бояться не надо. Вполне нормальная практика.

    9) Бабах:
    PHP:
    1. $db = Db::GetConnection();
    2.             $query = "INSERT INTO users (login, password, birth_date) VALUES (:login, :password, :birth_date)";
    3.             //    Подготавливаем запрос. В документации написано, что этот метод защищает от SQL-инъекций
    4.             $query = $db->prepare($query);
    5.             $query->bindParam(':login', $this->login);
    А тут ты как будто бы правильно используешь подготовку, но, почему-то, только на две трети. Странно, почему ты до этого так не делал. Но и странно, почему препейришь 3 параметра, а биндишь два.

    10)
    PHP:
    1. public static function months()
    2.     {
    3.         //    вывод месяцев в <select>
    4.         return array(Январь, Февраль, Март, Апрель, Май, Июнь, Июль, Август, Сентябрь, Октябрь, Ноябрь, Декабрь);
    5.     }
    Как-то странно это видеть в классе, отвечающем не за построение GUI. У тебя же есть отдельно вьюхи, прописал бы там :)

    Вердикт: в основном, на самом деле, к коду только придирки. Из фатальных недочетов только проблемы с безопасностью работы БД и хранение паролей в куках. В открытом виде.. Это вообще не круто.

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

    Теперь по верстке... На дворе 2017 год. Верстать таблицами не круто уже лет 15 как. Таблицы - это элемент для подачи табличных данных, а не для выравнивания разметки. Таблицы в качестве макета это плохо. Очень плохо. Ну и ничего не говорилось про два поля ввода для паролей. Говорилось не просто так. Это лишняя мишура, она тут просто не нужна. Но это не принципиально. А вот от таблиц надо уходить.
     
    SamyRed, acho и mahmuzar нравится это.
  23. kirroyal

    kirroyal Новичок

    С нами с:
    5 дек 2016
    Сообщения:
    12
    Симпатии:
    2
    Спасибо за все комментарии и такой детальный обзор.
    И правда перечитаю доки по PDO, токенам и отполирую сегодня.
     
    acho и Fell-x27 нравится это.
  24. kirroyal

    kirroyal Новичок

    С нами с:
    5 дек 2016
    Сообщения:
    12
    Симпатии:
    2
    Итак, проделал работу над ошибками, переписал часть кода.
    По пунктам:

    Я думал, что сессия ломается так же легко, как кука, поэтому думал, что лучше каждый раз проводить аутентификацию( хотя все-равно человек, который украдет сессию в данном случае будет иметь данные для входа и проверки будут только грузить сервер).
    Особо не углублялся, только прочитал, что в сессиях можно хранить данные и их не так легко сломать, особенно если привязывать к ip( этого пока не делал).
    А вопрос с куки я решил так:
    В куки записал чистый id и хешированный random_bytes(12), а в БД записал чистый random_bytes(12) и время его записи.

    PHP:
    1. public static function authCheckToken($id, $token_hash, &$error_array)
    2.    {    
    3.      //   В этом блоке достаем токен и время его создания
    4.      try {
    5.      $db = Db::GetConnection();
    6.      $query = 'SELECT token,token_time FROM users WHERE id=:id';
    7.      $query = $db->prepare($query);
    8.      $query->bindParam('id', $id);
    9.      $query->execute();
    10.      $result = $query->fetchAll();
    11.      $db_token = $result[0]['token'];
    12.  
    13.      //   Вытаскиваем время создания токена из БД
    14.      $token_time = new DateTime($result[0]['token_time']);
    15.  
    16.      //   Вычисляем, когда кончается срок годности токена
    17.      $token_time = $token_time->add(new DateInterval('PT1H'));
    18.      } catch (PDOException $e) {
    19.        echo 'Ошибка базы данных';
    20.      }
    21.  
    22.      $current_time = new DateTime();
    23.  
    24.      //   Если токен совпадает и срок его годности не подошел к концу - записываем ID в сессию
    25.      if(password_verify($db_token, $token_hash) && ($current_time<$token_time)) {
    26.        $_SESSION['user_id'] = $id;
    27.        return true;
    28.      }
    29.      else {
    30.        $error_array['false_cookies'] = 'Ложные куки';
    31.        return false;
    32.      }
    33.    }
    Естественно тут можно еще улучшить безопасность, каким-нибудь образом скрыть id, вычисляя-сопоставляя хеш.
    Но пароль в куках я скрыл от глаз:)

    Тут ничего не менял, еще потестирую разные способы.

    Исправил, теперь все настройки - статические свойста класса Config

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

    Подправил.

    Так и сделал.
    И тут тоже, даже не думал, что так можно.
    А вот тут все было правильно:D
    В случае когда забиндено кол-во параметров не равное кол-ву подготовленных, возвращается ошибка.
    У меня там чуть ниже был еще один bindParam, скорее всего вы его недоглядели.

    Это я отправил в конфиг, там как раз и хранятся массивы с различными данными.

    Я думал, что за формочку никто не наругает.
    Ошибался:D
     
    #424 kirroyal, 11 апр 2017
    Последнее редактирование: 11 апр 2017
  25. kirroyal

    kirroyal Новичок

    С нами с:
    5 дек 2016
    Сообщения:
    12
    Симпатии:
    2
    Не ошибка, а Warning.