PHP: if ($_POST['input']){ $input=$_POST['input']; } ? это решит все предупреждения или там еще что-то есть? По поводу вывода ошибок, переключил хостинг на php 7, установил вывод ошибок, все равно нотисов нет. А что если xDebug попробовать? . Так, что касается линукса, это не прерогатива сисадмина, например? Не хотелось бы лезть в другую область.
Вывод ошибок устанавливается одновременным применением двух директив: Код (Text): ini_set('display_errors', 'on'); error_reporting(E_ALL);
На элементарном уровне знать необходимо. Асы могут сконфигурировать свой комп для того, чтобы безопасно шарить с него сайты в нете. Я, конечно, не рискну. А вообще, виртуальная машина - это на любителя, и если свой комп достаточно сильный. Я взял самый дешёвый VPS за 200 р в месяц, на нём играюсь и выкладываю предварительные версии сайтов, чтоб показать клиентам.
Сегодня уже нет. Сегодня виртуалки используют паравиртуализационные интерфейсы, и производительность гостевых систем почти ничем не уступает производительности хоста, при этом сам хост тоже не тормозит совершенно. То есть, работа с процессором и памятью идет напрямую, а не через костыльные костыли, как цать лет назад. Главное, чтобы мать поддерживала это. --- Добавлено --- В идеальном мире версткой занимается верстальщик, серверсайдом серверник, клиентской логикой яваскриптер, сервером БД администратор БД, а остальным ПО и железкой - системный администратор. Плохая новость в том, что в мире реальном этим всем заниматься должен ты сам. А линукс для php - нативная среда. Ты не обратил внимание на странную иерархию папок в денвере? Со странными названиями. Какие-то opt, etc, var, home? В opt нет ничего про оптику, etc вообще хз накой, в var не лежат переменные, а в home нет домашней страницы твоего сайта, хотя это ж home. Это линуксовая организация ФС. Кроме того, если ты хочешь, чтобы твои майскули, phpшечки, и прочие апаче-нжингсики всегда были свежими, тебе на линукс. Там передовая. Этого всего. На винде уже портированные версии. Причем с сильным отставанием. Именно порты, потому что у винды и линукса свои особенности есть в некоторых областях, и просто пересборка проекта не поможет. Кстати, а нжинкс на винде вообще есть? Как в нем модули запиливать? Собирать в какой-нибудь VisualStudio?
Хочу, но повелся на название темы) В общем ждите через пару месяцев, не забывайте кликать на +1) А если серьезно, то я уже запилил один сайт на php, и в общем то советы Fell-x27 помогли в его доработке, например переделал его в UTF-8, касаемо реальной практики же, что нужно знать php-программисту среднего уровня, работающему с чужим кодом или просто по тз, пока не определился. Например, рекомендуют использовать фремворки и jquery, однако загружать кучу стороннего кода, который будет использован на 90%, не вижу оснований, но если разобратся, почему в требованиях к профи пишут знание фреймворков, получается, что даже серьезные крупные проекты пишут полагаясь на сторонние дополнения, в которых может быть уязвимость или еще что-то.
А в названии темы нет ничего про "освоить php на винде". Ну и да, код работать-таки заставь как следует. Там внутри еще немало проблем может быть.
@Frai я тоже новичек, вчера включил xdebug и даже в моём примитивном, работающем коде он показал мне кучу ошибок, так что советую им тоже проверять))
Ну без jQuery-то сейчас можно обойтись, по-моему, как раз сурикат где-то пропагандировал современные функции JavaScript вместо jQuery. Хотя лично я всё равно предпочту jQuery, поскольку короче, быстрее пишется код, привычнее. А вот по поводу фреймворков - если ты без них будешь делать проекты хотя бы средней сложности, тебе просто придётся рано или поздно запилить свой фреймворк. Я вот не уверен, что у меня при этом получится лучше, чем у разрабов Yii2 или Laravel. Если ты считаешь, что можешь лучше - пили свой Во фреймворках решены задачи, которые встречаются практически в каждом проекте, такие, как роутинг, удобная работа с базами данных и т.п. Вот я тут выложил решение этой задачи с использованием микрофреймворка Slim, даже там видно, сколько рутины за меня решил фреймворк. Найди, посмотри ради интереса.
Вуаля http://fomiaspa.bget.ru/ --- Добавлено --- http://e.bug.kmk.4nmv.ru/ ? также 31-го февраля (не придираюсь, только что обдумывал, как для своего варианта реализуется), код смотрю
Надо же. Сейчас посмотрю что в базе. Я думал DateTime::createFromFormat такую не пропустит автоматом (что логично) --- Добавлено --- Прикольно. А в базе как март эта дата. Значит при форматировании он её преобразует. Прикольно. Сейчас поправим --- Добавлено --- Поправил. Можешь посмотреть в гите, как. В принципе, наверно можно было и лучше, но отсекает неверные даты
Поехали: 1) Взаимодействие со страницей. HTML: <div class='tab' > <form id='form' method='post' action="/DELETE/test.php"> <button type='submit' name='input' value='showcode' class='code' >посмотреть код</button> </form> <form id='form' method='post' action="/DELETE/test.php"> <button type='submit' name='input' value='rating' class='code' >рейтинг</button> </form> </div> <div align=center> <form id='form' method='post' action="/DELETE/test.php"> <input id='login' name='login' type='text' placeholder='ник' value='' maxlength='150'> <input id='pass' name='pass' type='password' placeholder='паролька' value='' maxlength='150'> <button type='submit' name='input' value='enter'>войти</button> </form> <form method='post' action="/DELETE/test.php"> <button type='submit' name='input' value='reg'>зарегаться</button> </form> </div> Форма на форме формой погоняет. При этом скинуть страничку на регистрацию я не могу. Открыть страницу в новой вкладке, кликнув на замаскированные под ссылки кнопки я тоже не могу. Тебе следует разобраться с таким явлением как GET-параметры. Делать через форму то, что можно сделать ссылкой - не здорово. 2) id='form' повторяется многократно. По спецификации HTML, давать один id разным элементам запрещено. 3) heredoc... Тысячу лет его не видел, но ладно. PHP: $showCode= <<<_CODE <div class='tab' > <form id='form' method='post' action="$thisPage"> <button type='submit' name='input' value='showcode' class='code' >посмотреть код</button> </form> <form id='form' method='post' action="$thisPage"> <button type='submit' name='input' value='rating' class='code' >рейтинг</button> </form> </div> _CODE; $formReg=<<<_REG $showCode <form id='form' method='post' action="$thisPage"> <div align=center> <input id='login' name='login' type='text' placeholder='ник' value='' maxlength='150'> <input id='pass' name='pass' type='password' placeholder='паролька' value='' maxlength='150'> <div>дата рождения</div> <div> $day $month $year </div> <button type='submit' name='input' value='set' >зарегистрироваться</button> </div> </form> _REG; $formInput=<<<_INPUT $showCode <div align=center> <form id='form' method='post' action="$thisPage"> <input id='login' name='login' type='text' placeholder='ник' value='' maxlength='150'> <input id='pass' name='pass' type='password' placeholder='паролька' value='' maxlength='150'> <button type='submit' name='input' value='enter'>войти</button> </form> <form method='post' action="$thisPage"> <button type='submit' name='input' value='reg'>зарегаться</button> </form> </div> _INPUT; Но зачем заранее создавать весь контент, чтобы потом, выборочно его отдавать?То есть получается, в память пишутся данные, которые заведомо будут стерты с определенной долей вероятности. Это при том, что форма с кликером вынесена в отдельный код: PHP: function addPlusForm($newnum, $newsess, $thisPage, $nik ){ $formClick=<<<_CLICK <div class='tab'>ник: <span class='scroll'><nik>$nik</nik></span></div> <div align=center> <H1>$newnum</H1> <form method='post' action="$thisPage"> <button type='submit' name='input' value='$newsess'>+1</button> </form><br><br> <form method='post' action="$thisPage"> <button type='submit' name='exit' value='$newsess'>Выход</button> </form> </div> _CLICK; return $formClick; } Это создает какую-то двойную логику и, если честно, поначалу некисло запутало. По-хорошему весь контент должен генерироваться только тогда, когда он нужен. 4) dataCreator - очепятка, date же. И в целом половина имен в snake_case, а другая половина camelCase. Но это уже придирки по стилю. 5) Формат хранения данных: PHP: $newuser=$loginValue.$bd_pass.$passValue.$bd_pass.$newsess.$bd_pass.'0'.$bd_pass; Не годится. Он генерирует строку: mylogin<--xXx-->mypass<--xXx-->ZZZ_13485614103866<--xXx-->0<--xXx--> Не, <--xXx--> это, конечно, круто, все такое, но так делать не стоит. Если это окажется ником или паролем, все сломается. Вместо этого лучше пользоваться настоящей сериализацией или, что я больше предпочитаю, использовать JSON. 6) PHP: $fp=fopen('.'.$_SERVER['PHP_SELF'],"a"); Если файл исполняется из подкаталога, например "test/test.php", это обернется ошибкой, так как будет попытка записи в файл, лежащий в папке test рядом с исполянемым. Если этой папки нет, никто ее нам не создаст в данном случае. Соответственно, работать ничего не будет, и в коде эта ситуация никак не обрабатывается. До кучи никак не обрабатывается параллельный доступ, блокировки на запись, обработка блокировок. Это очень важно для файловых операций. Об этом надо знать, этим надо пользоваться, иначе можно словить неприятные сюрпризы конкурентного доступа. Ну или так: 7) Ты хранишь пароли в открытом виде. Так делать не надо. Подставляешь пользователя. Ты сказал, что уже сделал какой-то сайт. Если и там пароли хранятся в чистом виде, это надо срочно исправить. СРОЧНО. 8) PHP: $newsess="ZZZ_".rand(99, 99999999999999); Я так и не понял, зачем это нужно, и что дает его добавление к хранимым данным.
В защиту проекта могу сказать следующее: 1) Но тем не менее это вариант, если рядовой пользователь не смотрит в код, то формы вполне себе ничего. Опять же - не делай так, у меня вообще бы не появилось желания сделать это тз, просто хотелось попробовать все через post-параметры. Я не всегда так пишу) Работает же и не ошибочно. И кнопку назад в браузере не отменяли. Хотя время от времени появлялась идея на регистрации сделать кнопку "На главную" или "Войти", но это бы слишком ужасным отклонением от тз) 2)Здесь они вообще и не нужны эти id, вставлял по привычке, чтоб через js обращатся. Удалил их нафиг. 3)Если бы с этим подходом подразбить контент на кнопки и инпуты, то там мне бы сложно было тестировать его и вообще по быстрому вносить исправления. Было бы там этих полей больше ста, еще был бы резон. Но в целом да, кажется громоздкой конструкцией, согласен, наверное можно было бы более элегантно. Есть идеи? На примере одного такого блока. 5) Не, не сможет такой пароль задать или имя, угловые скобки запрещены в них. К слову, читая до этого обсуждение про свободу пользователя вносить какие ему угодно символы и пароли, столкнулся с тем, что пробел уж точно нужно запрещать, так как для рейтинга любого или чата, форума, имя "Логин" и "Логин " во всех вариациях смотрятся одинаково. Здесь я решил это тем , что задал им цветной фон. Но не делать же так везде. 6)А я предупреждал, что нужно в корневой каталог класть, чтобы мне удобнее было получить доступ к серверу через этот файл) Про постановление в очередь на запись я где-то читал, но пока не приходилось писать в файл в несколько потоков, использую базу данных для этого. 7) Мне лично всегда представлялось удобным для пользователя, если можно восстановить тот пароль который был, просто выслав его на емайл по требованию, соответственно если был взлом аккаунта - тут же его и поменять. Но обычно просто забывают. Поэтому хранить в БД хэши и сравнивать их как-то не подошло. Так при взломе базы данных, пароли это не так уж и важно, за что нужно опасаться, восстановить легко, а вот другие индивидуальные данные из базы они же вместе с прочим окажутся в руках злоумышленников, им и пароль не нужен. Только если пользователь везде использует один и тот же. Но я не даю возможности использовать спецсимволы для имен и так же предупреждаю при входе, что пароль рекомендуется делать уникальным и менять два-три раза в год. У меня сайт с техническим уклоном, так смайлики в имени там и не нужны.Но речь не про это, а про кодирование пароля. Пока пишу свой простой способ кодирования, учитывая, что он самописный, это будет лучше хэша. Показывать не буду) 8) Замена сессии пользователя, то есть переходя по кнопкам его страницы опознают, поэтому кроме кнопок нет вариантов (есть но на js), в get-запросе шла бы передача сессии в адресную строку со всеми последствиями, если кто-то захотел поделится ссылкой, мол какой это классный кликальный ресурс. Что там по сдаче-приемке?)
Ну нет. Если чел при взломе получает не хеш, который хрен расшифруешь (а в случае с password_hash это действительно так - там и соль используется, и сложные достаточно алгоритмы хеширования), то он тем самым получает доступ к закрытой части твоего интерфейса, и может, к примеру, как часто происходит при взломе контакта, рассылать от имени пользователя его контактам сообщения с просьбой кинуть денег. И кто-то может даже повестись. Правда, в случае контакта это происходит не потому, что они не хешируют пароли, там хакеру надо больше постараться, чтоб доступ к чужому акку получить. Веб-индустрия не зря вся ушла от хранения паролей в открытом виде, и не зря специальные функции были добавлены в php. Ну, в принципе, оттримить ведущие и хвостовые пробелы в логине можно - не повредит. А в середине логина или пароля он никому не мешает. А пароль трогать не надо, если всё правильно организовано. --- Добавлено --- А почему ты не редиректишь нигде после отработки post-формы? Будет проблема двойной отправки данных, а её быть не должно. Есть стандарты, которые необходимо соблюдать --- Добавлено --- А куда мне надо ввести от 5 до 150 символов? --- Добавлено --- А, понял, я это в коде должен посмотреть И в ТЗ не было ничего про то, что пароль или логин надо ограничить по длине - самодеятельность. --- Добавлено --- Вот это окошко после успешной обработки формы никогда не должно показываться. Решается редиректами
Ты не на защите, а я не препод. У тебя есть проблемы, я их обозначил. Проблемы нужно решить, и, впредь, не допускать подобное. И тогда у тебя все будет хорошо. Все остальное - отмазки. Мне до них дела нет. Ничего. Проблемы не решены, я вижу только отговорки, эффект даннинга-крюгера, синдром фатального недостатка и переносы ответственности. Я хз, зачем ты мне все это понаписал.
Будет проблема в том, что пользователь не знает, что там оттримлено, и будет долбить форму ввода с пробелами на концах. Вообще зачем в логине пробел? Имя и фамилию вводят обычно в разных формах и хранятся они отдельно, если только название организации, но это уже другая тема. Там нет двойной отправки и лишнего ничего не показывается. Знаю-знаю, пользователь должен иметь свободу выбора регистрироватся с одним символом в никнейме и одним в пароле) --- Добавлено --- Почитаю как нибудь на досуге. Спасибо за развернутый анализ кода.
Это тоже можно оттримить. И да, вот только из пробелов как раз таки стоит запретить логин, единственное, что стоит запретить. Остальное - не обязательно (разве что, такова будет придурь заказчика). Если при выводе логина пропускать его через htmlspecialchars (что необходимо делать с любыми пользовательскими данными в принципе), то пусть у него будет логин <script>alert("Я крутой хакер, поломал твой сайт"); </script>. Ну вот хочет он такой логин, и ладно. Чтоб алерт не сработал - это уже твоя забота, обернуть вывод этого логина в один вызов функции.
Мы это с сурикатом обсуждали. Можно было сделать проверку каждого месяца, и в придачу - високосного года, но мне как-то впадлу заниматься этим. При том - на нерабочем проекте. --- Добавлено --- Можно просто запретить пробел в конце и начале, например, с помощью регулярки. --- Добавлено --- А если я 2 раза быстро нажму на кнопку "Регистрация" (Пока страница не начала грузиться)
Если после регистрации нажать кнопку "обновить страницу", браузер предложит отправить данные ещё раз. Этого быть не должно.
http://san4ez.esy.es/index.php Спойлер: Код PHP: <?php session_start(); $db = new mysqli('localhost','mysql','mysql','dbname'); $login = $_SESSION['name']; if (isset($_POST['exit'])) { unset($_SESSION['name']); header("Location: /index.php"); } function ifAuth($login, $db) { $query = $db->query("SELECT * FROM `user` WHERE `login`='$login'"); $result = $query->fetch_assoc(); $schet = $result['schet']; if (isset($_POST['plus'])) { $schet = $result['schet'] + 1; $update = $db->query("UPDATE `user` SET `schet`='$schet' WHERE `login`='$login'"); $serv = $_SERVER['SERVER_NAME']; header("Location: /index.php"); } top(); echo ' <div class="auth">'.$schet.'</div>'; echo '<form method="POST"> <input type="submit" name="plus" value="+1"> <input type="submit" name="exit" value="Выйти"> </form>'; } function top() { echo '<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Fell-x27</title> <style type="text/css"> body, html { text-align: center; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } input[type=text], input[type=password], input[type=date] { border: 1px solid #bbb; width: 200px; } .auth { border: 1px solid #ccc; border-radius: 5px; width: 150px; font-size: 54pt; } </style> </head> <body>'; } if (isset($_SESSION['name'])) { ifAuth($login, $db); } else { $date = date('Y-m-d'); $mindate = date_create($date); date_sub($mindate, date_interval_create_from_date_string("150 years")); $mindate = date_format($mindate,"Y-m-d"); $maxdate = date_create($date); date_sub($maxdate, date_interval_create_from_date_string("5 years")); $maxdate = date_format($maxdate,"Y-m-d"); if (isset($_POST['reg'])) { if (isset($_POST['regi'])) { if (empty($_POST['login'])) { top(); echo 'Вы не ввели Логин'; } elseif (empty($_POST['pass'])) { top(); echo 'Вы не ввели пароль'; } elseif (empty($_POST['date'])) { top(); echo 'Вы не ввели Дату рождения'; } elseif ($_POST['date'] <= $mindate) { top(); echo 'Too old!'; } elseif ($_POST['date'] > $maxdate) { top(); echo 'Too young!'; } else { /* Обрезка пробелов, преобразование html символов, шифрование пароля */ $login = htmlspecialchars(trim($_POST['login'])); $pass = htmlspecialchars($_POST['pass']); $pass = password_hash($pass, PASSWORD_DEFAULT); $bdate = $_POST['date']; /* экранирование спец. символов данных */ $login = $db->real_escape_string($login); $query = $db->query("SELECT `login` FROM `user` WHERE `login`='$login'"); $result = $query->fetch_assoc(); if ($result) { top(); echo 'Такой логин существует'; } else { $insert = $db->query("INSERT INTO `user` (`login`,`pass`,`bdate`,`schet`) VALUES ('$login','$pass','$bdate','0')"); if ($insert) { $_SESSION['name'] = $login; header("Location: /index.php"); } } } } if (!isset($_SESSION['name'])) { top(); echo '<form method="POST" action="index.php"> <input type="text" name="login" placeholder="Логин"><br> <input type="password" name="pass" placeholder="Пароль"><br> Дата рождения:<br> <input type="date" name="date"><br> <input type="hidden" name="reg"> <input type="submit" name="regi" value="Зарегаться"> </form>'; } } else { if (isset($_POST['auth'])) { if (!empty($_POST['login']) and isset($_POST['pass'])) { $login = htmlspecialchars(trim($_POST['login'])); $pass = htmlspecialchars($_POST['pass']); $login = $db->real_escape_string($login); $query = $db->query("SELECT `login`,`pass` FROM `user` WHERE `login`='$login'"); $result = $query->fetch_assoc(); if ($result) { if (password_verify($pass, $result['pass'])) { $_SESSION['name'] = $result['login']; header("Location: /index.php"); ifAuth($login, $db); } else { echo 'Неверный пароль'; } } else { echo 'Такого логина не существует'; } } else { echo 'Логин не введен'; } } if (!isset($_SESSION['name'])) { top(); echo '<form method="POST" action="index.php"> <input type="text" name="login" placeholder="Логин"><br> <input type="password" name="pass" placeholder="Пароль"><br> <input type="submit" name="auth" value="Войти"> <input type="submit" name="reg" value="Зарегаться"> </form>'; } } } echo '</body> </html>'; $db->close(); ?>
А сразу и не догадаешься) В реализации, где единственно возможный результат быть авторизированным - это проходя только по кнопкам, причем с каждым переходом код сессии меняется всё это баловство может привести только к выводу главной страницы с формой входа, на записанное значение это не повлияет.