выкладываю заготовку на php для все беслпатно Логин, регистрация, простейшая защита, график захода на посты ну и еще по мелочи, не за что NEWLINIXPROJECT - основная папка и то, что ней находится: Как выглядит дерево проекта: index.php login.php css - файл scripts - файл include - файл img - файл tmp.log - файл index.php: <?php include("include/index.php") ?> PHP <?php include("include/index.php") ?> login.php: <?php <!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="css/login.css"> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <form action="/action_page.php"> <div class="container"> <h1>Register</h1> <hr> <label for="email"><b>Email</b></label> <input type="text" placeholder="Enter Email" name="email" required> <label for="psw"><b>Password</b></label> <input type="password" placeholder="Enter Password" name="psw" required> <label for="psw-repeat"><b>Repeat Password</b></label> <input type="password" placeholder="Repeat Password" name="psw-repeat" required> <hr> <button type="submit" class="registerbtn">Register</button> </div> </form> </body> </html> ?> PHP <?php <!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="css/login.css"> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <form action="/action_page.php"> <div class="container"> <h1>Register</h1> <hr> <label for="email"><b>Email</b></label> <input type="text" placeholder="Enter Email" name="email" required> <label for="psw"><b>Password</b></label> <input type="password" placeholder="Enter Password" name="psw" required> <label for="psw-repeat"><b>Repeat Password</b></label> <input type="password" placeholder="Repeat Password" name="psw-repeat" required> <hr> <button type="submit" class="registerbtn">Register</button> </div> </form> </body> </html> ?> css - файл admin_panel.css, admin.css, index.css, login.css: admin_panel.css *{ padding: 0; margin: 0; } .nav__bar{ width: 100vw; height: 86px; display: flex; justify-content: space-around; background-color: rgb(133, 133, 133); align-items: center; position: fixed; top: 0; } .text, .link{ text-decoration: none; color: white; font-size: 18px; transition: .3s; } .text:hover{ color: rgb(81, 151, 255); } .after{ margin-top: 86px; } .row{ display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; transition: .2s; cursor: pointer; } .row:nth-child(even){ background-color: whitesmoke; } .row span{ padding: 5px; } .row:hover { background-color: rgb(197, 197, 197) ; } .row:first-child{ font-weight: 900; background-color: transparent; cursor: default; } .row.active{ background-color: rgb(118, 118, 243); color: white; } .active__nav{ text-decoration: overline; } text.date{ writing-mode: vertical-lr; } line{ stroke: rgb(131, 131, 131); stroke-width: 1px; } .graph{ stroke: black; stroke-width: 3px; } .block{ width: 25%; margin: 20px auto; } CSS *{ padding: 0; margin: 0; } .nav__bar{ width: 100vw; height: 86px; display: flex; justify-content: space-around; background-color: rgb(133, 133, 133); align-items: center; position: fixed; top: 0; } .text, .link{ text-decoration: none; color: white; font-size: 18px; transition: .3s; } .text:hover{ color: rgb(81, 151, 255); } .after{ margin-top: 86px; } .row{ display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; transition: .2s; cursor: pointer; } .row:nth-child(even){ background-color: whitesmoke; } .row span{ padding: 5px; } .row:hover { background-color: rgb(197, 197, 197) ; } .row:first-child{ font-weight: 900; background-color: transparent; cursor: default; } .row.active{ background-color: rgb(118, 118, 243); color: white; } .active__nav{ text-decoration: overline; } text.date{ writing-mode: vertical-lr; } line{ stroke: rgb(131, 131, 131); stroke-width: 1px; } .graph{ stroke: black; stroke-width: 3px; } .block{ width: 25%; margin: 20px auto; } admin.css .main{ display: flex; align-items: center; width: auto; height: auto; margin: 0 auto; justify-content: center; padding: 30px; flex-direction: column; } input{ background-color: transparent; border: 1px solid black; border-radius: 4px; } .fro{ display: flex; justify-content: space-around; align-items: center; flex-direction: column; padding: 1rem; } .btn_sub{ padding: 8px; border-radius: 8px; background-color: rgb(187, 158, 214); border: 1px solid black; margin-bottom: 8px; } .btn_can{ padding: 8px; border-radius: 8px; background-color: rgb(214, 169, 158); border: 1px solid black; } dialog:modal{ border: 1px solid black; border-radius: 8px; top: 50%; left: 50%; transform: translate(-50%, -50%); } .tool__bar{ position: fixed; z-index: 2; top: 60px; left: 40px; } .tool__bar img{ width: 25px; margin-right: 10px; cursor: pointer; } #text{ display: none; } .ck-editor__editable{ height: 500px; } CSS .main{ display: flex; align-items: center; width: auto; height: auto; margin: 0 auto; justify-content: center; padding: 30px; flex-direction: column; } input{ background-color: transparent; border: 1px solid black; border-radius: 4px; } .fro{ display: flex; justify-content: space-around; align-items: center; flex-direction: column; padding: 1rem; } .btn_sub{ padding: 8px; border-radius: 8px; background-color: rgb(187, 158, 214); border: 1px solid black; margin-bottom: 8px; } .btn_can{ padding: 8px; border-radius: 8px; background-color: rgb(214, 169, 158); border: 1px solid black; } dialog:modal{ border: 1px solid black; border-radius: 8px; top: 50%; left: 50%; transform: translate(-50%, -50%); } .tool__bar{ position: fixed; z-index: 2; top: 60px; left: 40px; } .tool__bar img{ width: 25px; margin-right: 10px; cursor: pointer; } #text{ display: none; } .ck-editor__editable{ height: 500px; } index.css @import url('https://fonts.googleapis.com/css2?family=Poppins&family=Unbounded&display=swap'); *{ margin: 0; padding: 0; font-family: 'Poppins', sans-serif; } .navbar{ background-color: rgb(87 165 42); display: grid; grid-template-columns: 1fr 1fr 1fr; box-shadow: 2px 4px 11px 0px rgb(34 60 80 / 20%); padding: 20px; align-items: center; position: fixed; width: 100vw; top: 0; } .middle{ display: flex; justify-content: space-between; } .login{ text-align: right; text-decoration: none; color: black; padding-left: 20px; } .right{ display: flex; justify-content: center; } .main_sec{ background-color: gray; max-width: 1200px; margin: 0 auto; height: 200vh; margin-top: 75px; } .content_box{ width: 90%; height: auto; padding: 30px 15px; border-radius: 12px; margin: auto; border: 1px solid rgb(88, 88, 88); margin-top: 15px; display: flex; flex-wrap: wrap; justify-content: space-between; text-decoration: none; color: black; } .content_box > span{ flex-basis: 30%; } .content_box > a{ flex-basis: 100%; margin-bottom: 30px; font-size: larger; text-decoration: none; color: black; transition: .3s; } .content_box > a:hover{ color: rgb(255, 209, 59); } .back_arr{ text-decoration: none; color: black; display: block; transition: .3s; margin-top: 10px; margin-left: 44px; } .back_arr:hover{ color: rgb(255, 209, 59); } CSS @import url('https://fonts.googleapis.com/css2?family=Poppins&family=Unbounded&display=swap'); *{ margin: 0; padding: 0; font-family: 'Poppins', sans-serif; } .navbar{ background-color: rgb(87 165 42); display: grid; grid-template-columns: 1fr 1fr 1fr; box-shadow: 2px 4px 11px 0px rgb(34 60 80 / 20%); padding: 20px; align-items: center; position: fixed; width: 100vw; top: 0; } .middle{ display: flex; justify-content: space-between; } .login{ text-align: right; text-decoration: none; color: black; padding-left: 20px; } .right{ display: flex; justify-content: center; } .main_sec{ background-color: gray; max-width: 1200px; margin: 0 auto; height: 200vh; margin-top: 75px; } .content_box{ width: 90%; height: auto; padding: 30px 15px; border-radius: 12px; margin: auto; border: 1px solid rgb(88, 88, 88); margin-top: 15px; display: flex; flex-wrap: wrap; justify-content: space-between; text-decoration: none; color: black; } .content_box > span{ flex-basis: 30%; } .content_box > a{ flex-basis: 100%; margin-bottom: 30px; font-size: larger; text-decoration: none; color: black; transition: .3s; } .content_box > a:hover{ color: rgb(255, 209, 59); } .back_arr{ text-decoration: none; color: black; display: block; transition: .3s; margin-top: 10px; margin-left: 44px; } .back_arr:hover{ color: rgb(255, 209, 59); } body { font-family: Arial, Helvetica, sans-serif; background-color: black; } * { box-sizing: border-box; } /* Add padding to containers */ .container { padding: 16px; background-color: white; } /* Full-width input fields */ input[type=text], input[type=password] { width: 100%; padding: 15px; margin: 5px 0 22px 0; display: inline-block; border: none; background: #f1f1f1; } input[type=text]:focus, input[type=password]:focus { background-color: #ddd; outline: none; } /* Overwrite default styles of hr */ hr { border: 1px solid #f1f1f1; margin-bottom: 25px; } /* Set a style for the submit button */ .registerbtn { background-color: #4CAF50; color: white; padding: 16px 20px; margin: 8px 0; border: none; cursor: pointer; width: 100%; opacity: 0.9; } .registerbtn:hover { opacity: 1; } /* Add a blue text color to links */ a { color: dodgerblue; } /* Set a grey background color and center the text of the "sign in" section */ .signin { background-color: #f1f1f1; text-align: center; } .error{ background-color: rgb(93, 122, 252); width: 70vw; height: 100px; border-radius: 12px; margin: 0 auto; display: flex; justify-content: center; align-items: center; font-size: 28px; } CSS body { font-family: Arial, Helvetica, sans-serif; background-color: black; } * { box-sizing: border-box; } /* Add padding to containers */ .container { padding: 16px; background-color: white; } /* Full-width input fields */ input[type=text], input[type=password] { width: 100%; padding: 15px; margin: 5px 0 22px 0; display: inline-block; border: none; background: #f1f1f1; } input[type=text]:focus, input[type=password]:focus { background-color: #ddd; outline: none; } /* Overwrite default styles of hr */ hr { border: 1px solid #f1f1f1; margin-bottom: 25px; } /* Set a style for the submit button */ .registerbtn { background-color: #4CAF50; color: white; padding: 16px 20px; margin: 8px 0; border: none; cursor: pointer; width: 100%; opacity: 0.9; } .registerbtn:hover { opacity: 1; } /* Add a blue text color to links */ a { color: dodgerblue; } /* Set a grey background color and center the text of the "sign in" section */ .signin { background-color: #f1f1f1; text-align: center; } .error{ background-color: rgb(93, 122, 252); width: 70vw; height: 100px; border-radius: 12px; margin: 0 auto; display: flex; justify-content: center; align-items: center; font-size: 28px; } include - файл: admin- файл, index.php, dbconf.php. dbconf.php: <?php $dsn = 'mysql:dbname=bazadannih;host=localhost'; $user = 'asd'; $password = '1111'; function Debug($txt){ if($fp = fopen('tmp.log', 'a')){ fwrite($fp, date("Y-m-d H:i:s - "). $txt."\n"); fclose($fp); } } ?> PHP <?php $dsn = 'mysql:dbname=bazadannih;host=localhost'; $user = 'asd'; $password = '1111'; function Debug($txt){ if($fp = fopen('tmp.log', 'a')){ fwrite($fp, date("Y-m-d H:i:s - "). $txt."\n"); fclose($fp); } } ?> index.php: <?php include("include/dbconf.php"); $dbh = new PDO($dsn, $user, $password, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); $base = dirname($_SERVER["PHP_SELF"])."/"; $query = substr($_SERVER["REQUEST_URI"], strlen($base) - 1); $query = str_replace("index.php", "", $query); $content = ''; if($query == ''){ $prep = $dbh->prepare("select p.id, data, text, views, s.name from posts p inner join superuser s on s.id = p.admid order by data desc"); $prep->execute(); foreach($prep->fetchAll() as $row){ $txt = substr(strip_tags($row['text']), 0, 200); $date = new DateTimeImmutable($row['data']); $content.= '<div class="content_box"><a href="/post/'.$row["id"].'"> <span>'.$txt."</span></a><span>".$date->format('d.m.Y H:i'); $content.= "</span><span>".$row['name']."</span><span>".$row['views']."</span></div>\n"; } } elseif(strpos($query, '/')){ list($query, $id) = explode("/", $query); //Debug($query.".".$id); if($query == "post"){ $prep = $dbh->prepare("update posts set views = views + 1 where id = ?"); $prep->execute([$id]); $prep = $dbh->prepare("select p.id, data, text, views, s.name from posts p inner join superuser s on s.id = p.admid where p.id = ?"); $prep->execute([$id]); if($row = $prep->fetch()){ $date = new DateTimeImmutable($row['data']); $content.= '<div class="content_box"><div>'.$row['text']."</div><span>".$date->format('d.m.Y H:i'); $content.= "</span><span>".$row['name']."</span><span>".$row['views']."</span></div>\n"; $content.= '<a class="back_arr" href="/">← To post list</a>'; $prep = $dbh->prepare("insert into views (postid) values(:id)"); $prep->execute(['id'=>$id]); } else{ $content = "Not Found 404"; } } } ?> <!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="/css/index.css"> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <main> <div class="navbar"> <div class="logotype"> <h2>Logo</h2> </div> <div class="middle"> <p class="middle_sec_text"> nav1 </p> <p class="middle_sec_text"> nav2 </p> <p class="middle_sec_text"> nav3 </p> </div> <div class="right"> <a href="login.html" class="login">Login</a> <a href="#" class="login">Reg</a> </div> </div> <div class="main_sec"> <?=$content?> </div> </main> <footer> </footer> </body> </html> PHP <?php include("include/dbconf.php"); $dbh = new PDO($dsn, $user, $password, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); $base = dirname($_SERVER["PHP_SELF"])."/"; $query = substr($_SERVER["REQUEST_URI"], strlen($base) - 1); $query = str_replace("index.php", "", $query); $content = ''; if($query == ''){ $prep = $dbh->prepare("select p.id, data, text, views, s.name from posts p inner join superuser s on s.id = p.admid order by data desc"); $prep->execute(); foreach($prep->fetchAll() as $row){ $txt = substr(strip_tags($row['text']), 0, 200); $date = new DateTimeImmutable($row['data']); $content.= '<div class="content_box"><a href="/post/'.$row["id"].'"> <span>'.$txt."</span></a><span>".$date->format('d.m.Y H:i'); $content.= "</span><span>".$row['name']."</span><span>".$row['views']."</span></div>\n"; } } elseif(strpos($query, '/')){ list($query, $id) = explode("/", $query); //Debug($query.".".$id); if($query == "post"){ $prep = $dbh->prepare("update posts set views = views + 1 where id = ?"); $prep->execute([$id]); $prep = $dbh->prepare("select p.id, data, text, views, s.name from posts p inner join superuser s on s.id = p.admid where p.id = ?"); $prep->execute([$id]); if($row = $prep->fetch()){ $date = new DateTimeImmutable($row['data']); $content.= '<div class="content_box"><div>'.$row['text']."</div><span>".$date->format('d.m.Y H:i'); $content.= "</span><span>".$row['name']."</span><span>".$row['views']."</span></div>\n"; $content.= '<a class="back_arr" href="/">← To post list</a>'; $prep = $dbh->prepare("insert into views (postid) values(:id)"); $prep->execute(['id'=>$id]); } else{ $content = "Not Found 404"; } } } ?> <!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="/css/index.css"> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <main> <div class="navbar"> <div class="logotype"> <h2>Logo</h2> </div> <div class="middle"> <p class="middle_sec_text"> nav1 </p> <p class="middle_sec_text"> nav2 </p> <p class="middle_sec_text"> nav3 </p> </div> <div class="right"> <a href="login.html" class="login">Login</a> <a href="#" class="login">Reg</a> </div> </div> <div class="main_sec"> <?=$content?> </div> </main> <footer> </footer> </body> </html> admin- файл: index.php, js - file, linksIn - file, login.php, tmp.log: index.php: <?php session_start(); define('AC_STAT', 1); define('AC_POST', 2); define('AC_ADMIN', 4); define('AC_USERS', 8); $menu = [ ['acs'=>AC_STAT, 'path'=>"./", 'title'=>'Статистика'], ['acs'=>AC_POST, 'path'=>"./posts", 'title'=>'Создание постов'], ['acs'=>AC_USERS, 'path'=>"./users", 'title'=>'Юзеры'], ['acs'=>AC_ADMIN, 'path'=>"./admins", 'title'=>'Администраторы'] ]; include("../dbconf.php"); $dbh = new PDO($dsn, $user, $password, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); // $pwd = password_hash("asdasd", PASSWORD_DEFAULT); // $sql = "insert into superuser (login, password, name, access) values('seconduser', '$pwd', 'user', 10)"; // $dbh->query($sql); if (!isset($_SESSION["su_id"])){ include('login.php'); } $base = dirname($_SERVER["PHP_SELF"])."/"; $len = strpos($_SERVER["REQUEST_URI"], "?"); if(!$len) $len = strlen($_SERVER["REQUEST_URI"]); $query = substr($_SERVER["REQUEST_URI"], strlen($base) - 1, $len - strlen($base) + 1); $query = str_replace("index.php", "", $query); if($query == "/logout"){ include("linksIn/logout.php"); } //Debug($query.' - '.print_r($_GET, true)); // if($query == "/admin"){ // include("linksIn/admin.php"); // } $found = false; foreach($menu as $item){ if($item['path'] == ".".$query){ $found = true; break; } } if(!$found){ include("linksIn{$query}.php"); } ?> <!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="/css/admin_panel.css?20230330"> <link rel="stylesheet" href="/css/admin.css"> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <base href="<?=$base?>"> <script src="https://cdn.ckeditor.com/ckeditor5/36.0.1/classic/ckeditor.js"></script> </head> <body> <div class="nav__bar"> <?php foreach($menu as $item){ if($item['acs'] & $_SESSION['su_access']){ echo '<a class="text'.($item['path'] == '.'.$query?' active__nav':'').'" href="'.$item['path'].'">'.$item['title']."</a>\n"; } } ?> <a href="logout" class="text">Выйти</a> </div> <?php if($query != '/'): ?> <div class="tool__bar"> <img src="/img/add.png" alt="" id="add"> <img src="/img/edit.png" alt="" id="edit"> <img src="/img/delete.png" alt="" id="delete"> </div> <?php endif; ?> <div class="after"> <?php if($query == "/"){ $query .= 'stats'; } include("linksIn{$query}.php"); ?> </div> <?php if($query != '/stats'): ?> <script src="./JS/script.js"></script> <?php endif; echo $_SERVER['HTTP_USER_AGENT'] ?> </body> </html> PHP <?php session_start(); define('AC_STAT', 1); define('AC_POST', 2); define('AC_ADMIN', 4); define('AC_USERS', 8); $menu = [ ['acs'=>AC_STAT, 'path'=>"./", 'title'=>'Статистика'], ['acs'=>AC_POST, 'path'=>"./posts", 'title'=>'Создание постов'], ['acs'=>AC_USERS, 'path'=>"./users", 'title'=>'Юзеры'], ['acs'=>AC_ADMIN, 'path'=>"./admins", 'title'=>'Администраторы'] ]; include("../dbconf.php"); $dbh = new PDO($dsn, $user, $password, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); // $pwd = password_hash("asdasd", PASSWORD_DEFAULT); // $sql = "insert into superuser (login, password, name, access) values('seconduser', '$pwd', 'user', 10)"; // $dbh->query($sql); if (!isset($_SESSION["su_id"])){ include('login.php'); } $base = dirname($_SERVER["PHP_SELF"])."/"; $len = strpos($_SERVER["REQUEST_URI"], "?"); if(!$len) $len = strlen($_SERVER["REQUEST_URI"]); $query = substr($_SERVER["REQUEST_URI"], strlen($base) - 1, $len - strlen($base) + 1); $query = str_replace("index.php", "", $query); if($query == "/logout"){ include("linksIn/logout.php"); } //Debug($query.' - '.print_r($_GET, true)); // if($query == "/admin"){ // include("linksIn/admin.php"); // } $found = false; foreach($menu as $item){ if($item['path'] == ".".$query){ $found = true; break; } } if(!$found){ include("linksIn{$query}.php"); } ?> <!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="/css/admin_panel.css?20230330"> <link rel="stylesheet" href="/css/admin.css"> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <base href="<?=$base?>"> <script src="https://cdn.ckeditor.com/ckeditor5/36.0.1/classic/ckeditor.js"></script> </head> <body> <div class="nav__bar"> <?php foreach($menu as $item){ if($item['acs'] & $_SESSION['su_access']){ echo '<a class="text'.($item['path'] == '.'.$query?' active__nav':'').'" href="'.$item['path'].'">'.$item['title']."</a>\n"; } } ?> <a href="logout" class="text">Выйти</a> </div> <?php if($query != '/'): ?> <div class="tool__bar"> <img src="/img/add.png" alt="" id="add"> <img src="/img/edit.png" alt="" id="edit"> <img src="/img/delete.png" alt="" id="delete"> </div> <?php endif; ?> <div class="after"> <?php if($query == "/"){ $query .= 'stats'; } include("linksIn{$query}.php"); ?> </div> <?php if($query != '/stats'): ?> <script src="./JS/script.js"></script> <?php endif; echo $_SERVER['HTTP_USER_AGENT'] ?> </body> </html> login.php: <?php if (isset($_SESSION['su_attempts']) && $_SESSION['su_attempts'] > 5){ exit("Превышено количество попыток входа") ; } $login = filter_input(INPUT_POST, "login", FILTER_SANITIZE_STRING); $password = filter_input(INPUT_POST, "psw", FILTER_SANITIZE_STRING); if ($login && $password){ $prep = $dbh->prepare("select * from superuser where login = ? and not block"); $prep->execute([$login]); if($res = $prep->fetch()){ if(password_verify($password, $res['password'])){ $_SESSION['su_id'] = $res['id']; $_SESSION['su_name'] = $res['name']; $_SESSION['su_access'] = $res['access']; $p = ""; foreach($menu as $item){ if($item['acs'] & $res['access']){ $p = substr($item['path'], 2); break; } } header("Location: //".$_SERVER["HTTP_HOST"]."/include/admin/".$p, true); exit(); } } $error = "пароль или логин не верны"; if (isset($_SESSION['su_attempts'])){ $_SESSION['su_attempts']++; if ($_SESSION['su_attempts'] > 5){ $error = "Превышено количество попыток входа"; } } else { $_SESSION['su_attempts'] = 1; } } ?> <!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="/css/login.css"> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <form action="<?=$_SERVER['PHP_SELF']?>" method="post"> <div class="container"> <h1>Login</h1> <hr> <label><b>Login</b></label> <input type="text" placeholder="Enter Login" name="login" required> <label><b>Password</b></label> <input type="password" placeholder="Enter Password" name="psw" required> <hr> <button class="registerbtn">Submit</button> <?php if(isset($error) ): ?><div class="error"> <?=$error?> </div> <?php endif; ?> </div> </form> </body> </html> <?php exit(); ?> PHP <?php if (isset($_SESSION['su_attempts']) && $_SESSION['su_attempts'] > 5){ exit("Превышено количество попыток входа") ; } $login = filter_input(INPUT_POST, "login", FILTER_SANITIZE_STRING); $password = filter_input(INPUT_POST, "psw", FILTER_SANITIZE_STRING); if ($login && $password){ $prep = $dbh->prepare("select * from superuser where login = ? and not block"); $prep->execute([$login]); if($res = $prep->fetch()){ if(password_verify($password, $res['password'])){ $_SESSION['su_id'] = $res['id']; $_SESSION['su_name'] = $res['name']; $_SESSION['su_access'] = $res['access']; $p = ""; foreach($menu as $item){ if($item['acs'] & $res['access']){ $p = substr($item['path'], 2); break; } } header("Location: //".$_SERVER["HTTP_HOST"]."/include/admin/".$p, true); exit(); } } $error = "пароль или логин не верны"; if (isset($_SESSION['su_attempts'])){ $_SESSION['su_attempts']++; if ($_SESSION['su_attempts'] > 5){ $error = "Превышено количество попыток входа"; } } else { $_SESSION['su_attempts'] = 1; } } ?> <!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="/css/login.css"> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <form action="<?=$_SERVER['PHP_SELF']?>" method="post"> <div class="container"> <h1>Login</h1> <hr> <label><b>Login</b></label> <input type="text" placeholder="Enter Login" name="login" required> <label><b>Password</b></label> <input type="password" placeholder="Enter Password" name="psw" required> <hr> <button class="registerbtn">Submit</button> <?php if(isset($error) ): ?><div class="error"> <?=$error?> </div> <?php endif; ?> </div> </form> </body> </html> <?php exit(); ?> JS- file: script.js: [CODE=php] let itemUrl = window.location.href.replace(/s$/,""); document.querySelector(".all_list").onclick = function(e){ let div = e.target.parentElement; let list = this.querySelectorAll(".row"); let id = div.dataset.id; list.forEach((el) => { el.classList.remove("active"); }) if(id){ div.classList.add("active"); } } document.querySelector(".all_list").ondblclick = function(e){ let div = e.target.parentElement; let id = div.dataset.id; edit(id, "edit"); } function edit(id, action){ let y = new FormData(); y.append("id", id); y.append("action", action); postData(itemUrl, y) .then((data) => { let dialog = document.createElement("dialog"); dialog.innerHTML = data; document.body.append(dialog); if(itemUrl.indexOf('/post') != -1 ){ ClassicEditor .create( document.querySelector( '#text' ) ) .catch( error => { console.error( error ); } ); } dialog.querySelector(".btn_can").onclick = (e)=>{ e.preventDefault(); dialog.close(); } dialog.onclose = (e)=>{ dialog.remove(); } let frm = dialog.firstElementChild; frm.onsubmit = (e)=>{ e.preventDefault(); let z = new FormData(frm); postData(itemUrl, z).then((data)=>{ if(data.indexOf('SQLSTAT') == -1){ window.location.href = window.location.href } else{ dialog.innerHTML = data + '<br>\n Esc - Закрыть'; } }) } dialog.showModal(); }); } const postData = async (url = '', data = {}) => { // Формируем запрос const response = await fetch(url, { // Метод, если не указывать, будет использоваться GET method: 'POST', // Данные body: data }); let x = await response.text(); return x; } document.querySelector(".tool__bar").onclick = (e) =>{ let btn = e.target; let action = btn.getAttribute("id"); let id = 0; if(action){ if(action != "add"){ id = document.querySelector(".row.active").dataset.id; } edit(id, action); } } [/CODE]linksIn - file: admin.php, admins.php, logout.php, post.php, posts.php, stats.php, user.php, users.php: admin.php: [CODE=php]<?php $id = filter_input(INPUT_POST, "id", FILTER_SANITIZE_NUMBER_INT); $action = filter_input(INPUT_POST, "action", FILTER_SANITIZE_STRING); $login = filter_input(INPUT_POST, "login", FILTER_SANITIZE_STRING); $password = filter_input(INPUT_POST, "password", FILTER_SANITIZE_STRING); $passwordtwo = filter_input(INPUT_POST, "passwordtwo", FILTER_SANITIZE_STRING); $name = filter_input(INPUT_POST, "name", FILTER_SANITIZE_STRING); $acs = filter_input(INPUT_POST, "acs", FILTER_SANITIZE_NUMBER_INT, FILTER_REQUIRE_ARRAY); $block = filter_input(INPUT_POST, "ban", FILTER_VALIDATE_BOOLEAN)? 1:0; $access = 0; //Debug(print_r($_POST, true)); if(is_array($acs)){ foreach($acs as $val) $access |= $val; } //Debug("id:$id, action:$action, login:$login, name:$name"); if ($id){ if($login && $name){ if($action == "edit"){ $sql = "update superuser set login=:login, name=:name, block=:block, access=:access"; $data = ["login"=>$login, "name"=>$name, "block"=>$block, "access"=>$access]; if($password && $password == $passwordtwo){ $password = password_hash($password, PASSWORD_DEFAULT); $sql.=", password=:password"; $data["password"]=$password; } $sql.=" where id =:id"; $data["id"]=$id; // Debug($sql."\n".print_r($data, true)); $prep = $dbh->prepare($sql); $prep->execute($data); } elseif ($action == "delete"){ $prep = $dbh->prepare("delete from superuser where id = ?"); $prep->execute([$id]); } } $prep = $dbh->prepare("select * from superuser where id = ?"); $prep->execute([$id]); if($res = $prep->fetch()){ extract($res); } } elseif ($action == "add" && $login && $name && $password && $password == $passwordtwo) { $password = password_hash($password, PASSWORD_DEFAULT); $data = ["login"=>$login, "name"=>$name, "block"=>$block, "password"=>$password, "access"=>$access]; // Debug(print_r($data, true)); $prep = $dbh->prepare("insert into superuser (login, name, password, block, access) values(:login, :name, :password, :block, :access)"); try{ $prep->execute($data); } catch(PDOException $ex){ exit($ex->getMessage()); } exit(); } ?> <form action="" method="post" class="main"> <input type="hidden" name="id" value="<?=$id?>"> <input type="hidden" name="action" value="<?=$action?>"> <div class="fro"> <label for="">логин <input type="text" name="login" value="<?=$login?>"> </label> </div> <div class="fro2"> <label for="">пароль <input type="password" name="password"> </label> </div> <div class="fro3"> <label for="">повторите пароль <input type="password" name="passwordtwo"> </label> </div> <div class="fro4"> <label for=""> имя <input type="text" name="name" value="<?=$name?>"> </label> </div> <label for=""> Права доступа </label> <?php foreach($menu as $item){ echo '<div><input type="checkbox" name="acs[]" value="'.$item['acs'].'"'; if($item['acs'] & $access) echo ' checked'; if($id == $_SESSION['su_id']) echo ' disabled'; echo ' id="ac'.$item['acs'].'"> <label for="ac'.$item['acs'].'">'.$item['title']."</label></div>\n"; } ?> <div class="fro5"> <label for="" <?php if($id == $_SESSION['su_id']): ?> style="display:none"<?php endif; ?>> <input type="checkbox" name="ban" value="true" <?php if($block) echo " checked" ?>> Блокировать </label> </div> <div> <button class="btn_sub"<?php if($id == $_SESSION['su_id'] && ($action == 'delete') ) echo ' disabled'; ?>><?php echo($action == "delete")?"Удалить":"Сохранить" ?></button> <button class="btn_can">Отмена</button> </div> </form> <?php exit(); ?> [/CODE]admins.php: [CODE=php]<div class="all_list"> <div class="row"> <span>Login: </span> <span>Name: </span> </div> <?php $prep = $dbh->prepare("select * from superuser where access <=? order by name"); $prep->execute([$_SESSION['su_access']]); foreach($prep->fetchAll() as $row){ echo '<div class="row" data-id="'.$row["id"].'"> <span>'.$row["login"]."</span><span>".$row["name"]."</span></div>\n"; } ?> </div> [/CODE][CODE=php]<?php unset($_SESSION['su_id'], $_SESSION['su_name'], $_SESSION['su_access']); header("Location: //".$_SERVER["HTTP_HOST"]."/include/admin/", true); exit(); ?> [/CODE][CODE=php]<?php $id = filter_input(INPUT_POST, "id", FILTER_SANITIZE_NUMBER_INT); $action = filter_input(INPUT_POST, "action", FILTER_SANITIZE_STRING); $text = filter_input(INPUT_POST, "text", FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_FLAG_NO_ENCODE_QUOTES); $text = htmlspecialchars_decode($text, ENT_QUOTES | ENT_HTML5); //Debug(print_r($_POST, true)); //Debug("id:$id, action:$action, text:$text, name:$name"); if ($id){ if($text){ if($action == "edit"){ $sql = "update posts set text=:text"; $data = ["text"=>$text]; $sql.=" where id =:id"; $data["id"]=$id; // Debug($sql."\n".print_r($data, true)); $prep = $dbh->prepare($sql); $prep->execute($data); } elseif ($action == "delete"){ $prep = $dbh->prepare("delete from posts where id = ?"); $prep->execute([$id]); } } $prep = $dbh->prepare("select * from posts where id = ?"); $prep->execute([$id]); if($res = $prep->fetch()){ extract($res); } } elseif ($action == "add" && $text) { $password = password_hash($password, PASSWORD_DEFAULT); $data = ["text"=>$text,"admid"=>$_SESSION['su_id']]; //Debug(print_r($data, true)); $prep = $dbh->prepare("insert into posts (text, admid) values(:text, :admid)"); try{ $prep->execute($data); } catch(PDOException $ex){ exit($ex->getMessage()); } exit(); // Debug(print_r($dbh->errorInfo(), true)); } ?> <form action="" method="post" class="main"> <input type="hidden" name="id" value="<?=$id?>"> <input type="hidden" name="action" value="<?=$action?>"> <div class="fro"> <textarea name="text" id="text"><?=$text?></textarea> </div> <div> <button class="btn_sub"><?php echo($action == "delete")?"Удалить":"Опубликовать" ?></button> <button class="btn_can">Отмена</button> </div> </form> <?php exit(); ?> [/CODE][CODE=php]<div class="all_list"> <div class="row"> <span>Publish: </span> <span>Text: </span> <span>Author: </span> <span>Views: </span> </div> <?php $prep = $dbh->prepare("select p.id, data, text, views, s.name from posts p inner join superuser s on s.id = p.admid order by data desc"); $prep->execute(); foreach($prep->fetchAll() as $row){ $txt = substr(strip_tags($row['text']), 0, 50); echo '<div class="row" data-id="'.$row["id"].'"> <span>'.$row["data"]."</span><span>".$txt; echo "</span><span>".$row['name']."</span><span>".$row['views']."</span></div>\n"; } ?> </div> [/CODE][CODE=php]<?php $width = 560; $height = 310; $dateto = filter_input(INPUT_GET, "dateto", FILTER_SANITIZE_NUMBER_INT); $datefrom = filter_input(INPUT_GET, "datefrom", FILTER_SANITIZE_NUMBER_INT); if(!$dateto or !$datefrom){ $dateto = date("Y-m-d"); $datefrom = date("Y-m-d", mktime(0,0,0, date("n")-1, date("j"), date("Y"))); } ?> <form class="block"> <input type="date" name="datefrom" value="<?=$datefrom?>"> – <input type="date" name="dateto" value="<?=$dateto?>"> <button>Показать</button> </form> <?php draw("DATE(datetime)", 'd.m', "Dates"); draw("WEEKDAY(datetime)", "D", "Weekdays"); draw("HOUR(datetime)", "H", "By hours"); function draw($criteria, $format, $title){ global $width, $height, $datefrom, $dateto, $dbh; echo '<svg width="'.$width.'" height="'.$height.'">'; echo '<text class="header" x="50" y="20">'.$title.'</text>'; $data = [ "from"=>$datefrom, "to"=>"$dateto 23:59:59" ]; $prep = $dbh->prepare("SELECT COUNT(*) AS CNT, $criteria AS DAY, datetime FROM `views` WHERE datetime BETWEEN :from AND :to GROUP BY DAY ORDER BY DAY;"); $prep->execute($data); $min = $max = 0; $arr = []; foreach($prep->fetchAll() as $row){ $arr[$row["datetime"]] = $row["CNT"]; if($row["CNT"] > $max) $max = $row["CNT"]; if($min == 0 || $min > $row["CNT"]) $min = $row["CNT"]; } // ksort($arr); // Debug("$min - $max\n".print_r($arr, true)); $maxg = round($max * 1.1); $ming = round($min / 1.1); if($ming <= 0) $ming = $min; $x = 45; $ty = $height - 40; $ox = $oy = 0; echo '<line x1="'.$x.'" y1="'.$ty.'" x2="'.$x.'" y2="0"/>'; echo '<line x1="'.$x.'" y1="'.$ty.'" x2="'.$width.'" y2="'.$ty.'"/>'; $y = $ty - ($min / $maxg) * $ty; $str = sprintf("%d", $min); echo '<line x1="'.($x - 5).'" y1="'.$y.'" x2="'.$x.'" y2="'.$y.'"/>'; echo '<text x="'.((6-strlen($str))* 6).'" y="'.$y.'" class="grade">'.$min.'</text>'; $y = $ty - ($max / $maxg) * $ty; $str = sprintf("%d", $max); echo '<line x1="'.($x - 5).'" y1="'.$y.'" x2="'.$x.'" y2="'.$y.'"/>'; echo '<text x="'.((6-strlen($str))* 6).'" y="'.$y.'" class="grade">'.$max.'</text>'; foreach($arr as $date=>$cnt){ $date = new DateTimeImmutable($date); echo '<text x="'.$x.'" y="'.$ty.'" class="date">'.$date->format($format).'</text>'; $y = $ty - ($cnt / $maxg) * $ty; if($ox + $oy == 0){ $ox = $x; $oy = $y; } echo '<line class="graph" x1="'.$ox.'" y1="'.$oy.'" x2="'.$x.'" y2="'.$y.'"/>'; $ox = $x; $oy = $y; $x += 20; } echo '</svg>'; } ?> [/CODE][CODE=php]<?php $id = filter_input(INPUT_POST, "id", FILTER_SANITIZE_NUMBER_INT); $action = filter_input(INPUT_POST, "action", FILTER_SANITIZE_STRING); $login = filter_input(INPUT_POST, "login", FILTER_SANITIZE_STRING); $password = filter_input(INPUT_POST, "password", FILTER_SANITIZE_STRING); $passwordtwo = filter_input(INPUT_POST, "passwordtwo", FILTER_SANITIZE_STRING); $name = filter_input(INPUT_POST, "name", FILTER_SANITIZE_STRING); $tel = filter_input(INPUT_POST, "tel", FILTER_SANITIZE_STRING); $mail = filter_input(INPUT_POST, "mail", FILTER_SANITIZE_STRING); $block = filter_input(INPUT_POST, "ban", FILTER_VALIDATE_BOOLEAN)? 1:0; //Debug(print_r($_POST, true)); //Debug("id:$id, action:$action, login:$login, name:$name"); if ($id){ if($login && $name){ if($action == "edit"){ $sql = "update users set login=:login, name=:name, block=:block, tel=:tel, mail=:mail"; $data = ["login"=>$login, "name"=>$name, "block"=>$block, "tel"=>$tel, "mail"=>$mail]; if($password && $password == $passwordtwo){ $password = password_hash($password, PASSWORD_DEFAULT); $sql.=", password=:password"; $data["password"]=$password; } $sql.=" where id =:id"; $data["id"]=$id; // Debug($sql."\n".print_r($data, true)); $prep = $dbh->prepare($sql); $prep->execute($data); } elseif ($action == "delete"){ $prep = $dbh->prepare("delete from users where id = ?"); $prep->execute([$id]); } } $prep = $dbh->prepare("select * from users where id = ?"); $prep->execute([$id]); if($res = $prep->fetch()){ extract($res); } } elseif ($action == "add" && $login && $name && $password && $password == $passwordtwo) { $password = password_hash($password, PASSWORD_DEFAULT); $data = ["login"=>$login,"password"=>$password, "name"=>$name, "block"=>$block, "tel"=>$tel, "mail"=>$mail]; //Debug(print_r($data, true)); $prep = $dbh->prepare("insert into users (login, name, password, block, tel, mail) values(:login, :name, :password, :block, :tel, :mail)"); try{ $prep->execute($data); } catch(PDOException $ex){ exit($ex->getMessage()); } exit(); // Debug(print_r($dbh->errorInfo(), true)); } ?> <form action="" method="post" class="main"> <input type="hidden" name="id" value="<?=$id?>"> <input type="hidden" name="action" value="<?=$action?>"> <div class="fro"> <label for="">логин <input type="text" name="login" value="<?=$login?>"> </label> <label for="">пароль <input type="password" name="password"> </label> <label for="">повторите пароль <input type="password" name="passwordtwo"> </label> <label for="">Имя <input type="text" name="name" value="<?=$name?>"> </label> <label for="">Телефон <input type="text" name="tel" value="<?=$tel?>"> </label> <label for="">Почта <input type="text" name="mail" value="<?=$mail?>"> </label> <label for="" > <input type="checkbox" name="ban" value="true" <?php if($block) echo " checked" ?>> Блокировать </label> </div> <div> <button class="btn_sub"<?php if($id == $_SESSION['su_id'] && ($action == 'delete') ) echo ' disabled'; ?>><?php echo($action == "delete")?"Удалить":"Опубликовать" ?></button> <button class="btn_can">Отмена</button> </div> </form> <?php exit(); ?> [/CODE][CODE=php]<div class="all_list"> <div class="row"> <span>Login: </span> <span>Name: </span> <span>Telephone: </span> <span>Email: </span> </div> <?php $prep = $dbh->prepare("select * from users order by name"); $prep->execute(); foreach($prep->fetchAll() as $row){ echo '<div class="row" data-id="'.$row["id"].'"> <span>'.$row["login"]."</span><span>".$row["name"]; echo "</span><span>".$row['tel']."</span><span>".$row['mail']."</span></div>\n"; } ?> </div> [/CODE]Ну вот и все, поставьте себе виртуальную машину и сидите кайфуйте, правда я очень долго с ней возился и настраивал, если что, могу помочь настроить виртуалку, ну а на этом усе глиф
WiperInside, спасибо за предоставленную информацию и заготовку на PHP! Она выглядит очень полезной для создания сайтов. Если у тебя есть какие-либо вопросы или нужна помощь, не стесняйся обращаться. Я готов помочь!