Jetzt auch auf Github!
https://github.com/C3010/SA-MP-UCP
Tutorial
Ja ja, es gibt bereits sehr viele Tutorials, nur sind die meisten out of date. Da die Interesse an PHP momentan sehr steigt und viele daran interessiert sind langsam was eigenes anzufangen dachte ich mir, ich mache ein kleines Beispiel. Ich werde versuchen alles bestmöglich zu erklären, jedoch ist es etwas mehr Code als man es von anderen Basics gewohnt ist, deswegen sind einige PHP Grundlagen vorrausgesetzt.
Bevor wir anfangen solltest du dir diesen Beitrag durchlesen, um zu wissen was PDO ist und wieso ich in diesem Beispiel zu PDO greife und nicht zu der veralteten mysql() Methode.
Ich werde dir nicht erklären wie du ein richtiges UCP entwickelst, denn im endeffekt wird es nur ein Login und eine Seite um die Stats zu sehen.
Da aber die meisten sich die veraltete Tutorials durchlesen, mache ich dennoch ein kleines Update sodass du mit deinen Codes immer auf den neusten Stand bist.
Fangen wir an.
Zunächst legen wir uns 2 Verzeichnisse und 1 Unterverzeichnis an
pages |
web/css |
Und nun die nötigen Dateien
pages | web/css |
account.php | style.css |
index.php |
Im Hauptverzeichnisse benötigen wir ebenfalls 4 Dateien
Configuration.php |
Connection.php |
Page.php |
index.php |
Zu einigen Dateien benötige ich keine große Erklärung schreiben und spare mir das Tippen und dir zugleich deine Zeit.
Also fangen wir einfach mal mit etwas Copy&Paste an.
Folgendes fügst du in die style.css
@charset "UTF-8";
* {
margin: 0;
padding: 0;
border: 0;
font-size: 99%;
font-family: 'Open Sans', 'Arial';
outline: none !important;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
vertical-align: baseline;
}
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
a {
color: #ffffff;
text-decoration: none;
transition: ease all .4s;
-moz-transition: ease all .4s;
-webkit-transition: ease all .4s;
-o-transition: ease all .4s;
-ms-transition: ease all .4s;
}
a:hover {
text-decoration: underline;
}
body {
cursor: default;
margin: 0;
padding: 0;
color: #ffffff;
background: #171717;
font-weight: 400;
text-shadow: 1px 2px 0 rgba(0, 0, 0, .3);
}
h1, h2, h3, h4 {
font-weight: 400;
}
h1 {
font-size: 21pt;
margin-bottom: 15px;
}
input {
width: 100%;
padding: 5px;
margin-bottom: 15px;
color: white;
border: none;
transition: all .4s;
-webkit-transition: all .4s;
-moz-transition: all .4s;
-o-transition: all .4s;
}
input[type="text"],
input[type="mail"],
input[type="password"],
textarea {
border: 2px solid #df3e2d;
background: rgba(0, 0, 0, .3);
}
input[type="text"]:hover,
input[type="mail"]:hover,
input[type="password"]:hover,
textarea:hover {
border-color: #F24E3D;
}
input[type="submit"],
button {
background: #df3e2d;
text-decoration: none;
cursor: pointer;
text-align: center;
}
input[type="submit"]:hover,
button:hover {
background: #F24E3D;
}
.alert {
padding: 8px;
color: #ffffff;
font-size: 9pt;
font-weight: 600;
background: #4EB54A;
margin-bottom: 15px;
}
.alert-error {
background: #F24E3D;
}
.grid {
width: 500px;
margin: 0 auto;
}
#wrapper {
margin: 50px auto;
}
.menu {
margin: 30px auto;
text-align: center;
}
.menu li {
display: inline-block;
padding: 0 10px;
}
.left {
float: left;
}
.right {
float: right;
}
.clear {
clear: both;
}
@media only screen and (max-width: 800px) {
.grid {
width: 90%;
}
}
Alles anzeigen
Das kommt in die Configuration.php und nicht vergessen die Daten anzupassen.
<?php
if(!defined('ACCESS')) header('Location: index.php');
$_CFG = [
'MYSQL' => [
'HOST' => '127.0.0.1',
'USER' => 'root',
'PASS' => '123456',
'DATA' => 'samp_ucp'
],
'SITE' => [
'NAME' => 'SA:MP UCP'
]
];
Alles anzeigen
Dies kommt in die Connection.php (es ist nichts weiter als eine Klasse für die MySQL Verbindung, sollte sich von selbst erklären)
<?php
if(!defined('ACCESS')) header('Location: index.php');
class Connection {
private $connection = null;
public function createConnection($data) {
if(!$this->connection) {
try {
$this->connection = new PDO("mysql:host={$data[0]};dbname={$data[3]};charset=utf8", $data[1], $data[2]);
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->connection->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8' COLLATE 'utf8_unicode_ci'");
$this->connection->exec('set names utf8');
mb_internal_encoding('UTF-8');
} catch(PDOException $ex) {
die($ex->getMessage());
}
}
}
public function getConnection() {
return $this->connection;
}
}
Alles anzeigen
Nun sind wir mit dem Copy&Paste erstmal fertig.
Fangen wir mit der index.php an, also die Hauptdatei welche immer als erstes aufgerufen wird.
Wie schon erwähnt sollte man einige PHP Grundlagen beherschen.
Zunächst öffnen wir den PHP Tag und starten eine session, falls noch keine gestartet ist.
Im normalfall brauchen wie die Abfrage nicht, aber wir lassen es sicherheitshalber drinne:
Nun setzen wir einige Einstellungen fest, sind nicht sehr wichtig aber könnte im späteren nützlich werden.
Erklärungen
set_time_limit, ini_set, date_default_timezone_set, http://error_reporting,
@set_time_limit(0);
@ini_set('memory_limit', -1);
@ini_set('display_errors', true);
@date_default_timezone_set('Europe/Berlin');
error_reporting(E_ALL);
Nun definieren wir eine Variable, sodass fremde außer auf die index.php auf keine andere Dateien zugreifen können.
Deswegen haben wir auch folgende Abfrage in einigen Dateien
Es leitet den User zurück auf index.php, wenn ACCESS nicht definiert ist. Da in der index.php die Variable definiert ist, können wir nur über die index.php auf die anderen Dateien zugreifen.
So nun geht's aber weiter. Wir inkludieren nun die anderen 3 Dateien im Hauptverzeichnis.
Und nun stellen wir eine Verbindung zu unserer MySQL Datenbank her. Dazu benutzen wir die Connection Klasse, welche wir bereits oben erstellt haben.
$pdo = new Connection();
$pdo->createConnection(array(
$_CFG['MYSQL']['HOST'],
$_CFG['MYSQL']['USER'],
$_CFG['MYSQL']['PASS'],
$_CFG['MYSQL']['DATA']
));
Und kommen wir zum Ende der index.php.
Wir erstellen ein neues Objekt welche die Funktionen von der Page Klasse erbt und geben den Konstruktor zurück.
So müsste nun unsere index.php aussehen
<?php
if(session_status() == PHP_SESSION_NONE) session_start();
@set_time_limit(0);
@ini_set('memory_limit', -1);
@ini_set('display_errors', true);
@date_default_timezone_set('Europe/Berlin');
error_reporting(E_ALL);
define('ACCESS', true);
require_once('Configuration.php');
require_once('Connection.php');
require_once('Page.php');
$pdo = new Connection();
$pdo->createConnection(array(
$_CFG['MYSQL']['HOST'],
$_CFG['MYSQL']['USER'],
$_CFG['MYSQL']['PASS'],
$_CFG['MYSQL']['DATA']
));
return new Page($_REQUEST, $_CFG, $pdo->getConnection());
Alles anzeigen
So und nun kommen wir zu der Page Klasse. Wir fügen folgenden Code in der Page.php Klasse ein.
Auch hier werde ich keine Erklärung schreiben, da sich das alles eigentlich von selbst erklären sollte.
<?php
if(!defined('ACCESS')) header('Location: index.php');
class Page {
private $page = 'index',
$dir;
public $request, $cfg, $pdo;
public function __construct($request, $cfg, $pdo, $dir = 'pages') {
$this->request = $request;
$this->cfg = $cfg;
$this->pdo = $pdo;
$this->dir = $dir;
if(isset($request['p'])) {
if(strtolower($request['p']) == 'logout') {
session_destroy();
header('Location: index.php');
}
if($this->fileExists($request['p'])) {
$this->page = $request['p'];
}
}
$this->display();
}
private function fileExists($page) {
if(file_exists($this->dir . '/' . strtolower($page) . '.php')) {
return true;
}
}
private function getFile($page) {
return $this->dir . '/' . strtolower($page) . '.php';
}
private function display() {
require_once($this->getFile($this->page));
}
public function isLoggedIn() {
if(isset($_SESSION['USERNAME'], $_SESSION['PASSWORD'])) {
$stmt = $this->pdo->prepare('SELECT NULL FROM `Accounts` WHERE `Username` = :username AND `Password` = :password LIMIT 1');
$stmt->execute(array(
':username' => $_SESSION['USERNAME'],
':password' => $_SESSION['PASSWORD']
));
if($stmt->rowCount()) {
return true;
}
}
}
public function getData($row) {
if($this->isLoggedIn()) {
$stmt = $this->pdo->prepare('SELECT `' . $row . '` FROM `Accounts` WHERE `Username` = :username LIMIT 1');
$stmt->execute(array(
':username' => $_SESSION['USERNAME']
));
$obj = $stmt->fetch(PDO::FETCH_ASSOC);
return $obj[$row];
}
}
}
Alles anzeigen
Für dich werden die 2 Funktionen isLoggedIn() und getData() am wichtigsten sein.
Mit isLoggedIn() können wir abfragen, ob der User eingeloggt ist und mit getData() können wir Daten vom Spieler auslesen.
Nehmen wir an, wir wollen das Level auslesen, dann benutzen wir
Also weiter. Weiter gehts mit den pages Verzeichnis. Wir fügen in index.php und account.php den folgendem Inhalt ein.
<?php
if(!defined('ACCESS')) header('Location: index.php');
if($this->isLoggedIn()) {
header('Location: index.php?p=account');
}
if(isset($this->request['login'])) {
if(isset($this->request['username'], $this->request['password'])) {
$username = $this->request['username'];
// Ohne Verschlüsslung:
$password = $this->request['password'];
//MD5:
//$password = md5($this->request['password']);
$stmt = $this->pdo->prepare('SELECT `Username`, `Password` FROM `Accounts` WHERE `Username` = :username AND `Password` = :password LIMIT 1');
$stmt->execute(array(
':username' => $username,
':password' => $password
));
if($stmt->rowCount()) {
$obj = $stmt->fetch(PDO::FETCH_OBJ);
$_SESSION['USERNAME'] = $obj->Username;
$_SESSION['PASSWORD'] = $obj->Password;
header('Location: index.php?p=account');
} else {
$error = 'Falsche Zugangsdaten.';
}
}
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title><?php echo $this->cfg['SITE']['NAME']; ?></title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no" />
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,400italic,600,600italic">
<link rel="stylesheet" href="web/css/style.css" />
</head>
<body>
<div id="wrapper" class="grid">
<ul class="menu">
<li>
<a href="index.php">Startseite</a>
</li>
</ul>
<h1>Login</h1>
<?php if(isset($error)) { ?>
<div class="alert alert-error"><?php echo $error; ?></div>
<?php } ?>
<form method="post">
<input type="text" name="username" placeholder="Benutzername" />
<input type="password" name="password" placeholder="Passwort" />
<input type="submit" name="login" value="Einloggen" />
</form>
</div>
</body>
</html>
Alles anzeigen
<?php
if(!defined('ACCESS')) header('Location: index.php');
if(!$this->isLoggedIn()) {
header('Location: index.php');
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title><?php echo $this->cfg['SITE']['NAME']; ?></title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no" />
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,400italic,600,600italic">
<link rel="stylesheet" href="web/css/style.css" />
</head>
<body>
<div id="wrapper" class="grid">
<ul class="menu">
<li>
<a href="index.php">Startseite</a>
</li>
<li>
<a href="index.php?p=logout">Ausloggen</a>
</li>
</ul>
<h1>Account</h1>
<b>Name:</b> <?php echo $this->getData('Username'); ?><br />
<b>Level:</b> <?php echo $this->getData('Level'); ?>
</div>
</body>
</html>
Alles anzeigen
Es ist kein richtiges Tutorial sondern etwas für Anfänger welche bereits die Grundlagen von PHP beherschen und auch die Codes verstehen.
Zu den HTML und CSS Teil habe ich keine Erklärung gegeben, da es nicht wirklich zum Tutorial gehört und man HTML und CSS schon beherschen sollte, bevor man mit PHP beginnt.
In der index.php prüfen wir ob der User angemeldet ist und falls ja leiten wir ihn zu seiner Statistik. In der account.php das selbe nur umgekehrt.
Die Abfrage mit dem Login sollte bereits selbst erklärend sein.
Das Tutorial dient mehr oder weniger um up to date zu bleiben und die neuste PHP Version nutzen zu können.
Sollten Fragen offen stehen kannst du die gerne stellen.
04.05.2016
Mehrsprachig
Auf Anfrage von @Whice. erkläre ich dir heute wie du ein einfaches Sprachsystem erstellen kannst.
Dazu habe ich bereits eine Klasse erstellt welche du du in den Hauptverzeichnis legen und anschließend ein Ordner "lang" anlegen musst.
<?php
/*
* @author C3O
*/
class Language {
const DEFAULT_LANGUAGE = 'de';
const SESSION_NAME = 'LANGUAGE';
public $language,
$json;
/**
* @param $language
*/
public function setLanguage($language) {
$this->language = $language;
if(isset($_SESSION[self::SESSION_NAME])) {
if($this->exists($_SESSION[self::SESSION_NAME])) {
$this->language = $_SESSION[self::SESSION_NAME];
}
}
if(!$this->exists($this->language)) {
$this->language = self::DEFAULT_LANGUAGE;
}
$language = $this->language;
$content = file_get_contents("lang/{$language}.json");
$this->json = json_decode($content, true);
}
/**
* @return mixed
*/
public function json() {
return $this->json;
}
/**
* @return array
*/
public function getLanguages() {
$files = [];
$dir = scandir('lang/');
foreach($dir as $key => $value) {
if(strpos(strtolower($value), '.json') !== false) {
$value = str_replace('.json', '', strtolower($value));
$files[] = strtoupper($value);
}
}
return $files;
}
/**
* @param $language
* @return bool
*/
public function exists($language = '') {
if(file_exists('lang/' . $language . '.json')) {
return true;
}
return false;
}
/**
* @param $string
* @param array $placeholders
* @param array $replaces
* @return mixed
*/
public function getReplaced($string, $placeholders = array(), $replaces = array()) {
$text = str_replace($placeholders, $replaces, $string);
return $text;
}
}
Alles anzeigen
Die Sprachdatei inkludierst du nun in deiner index.php
Nun erstellen wir ein neues Objekt
Nun geben wir die $language Variable unserer Page Klasse weiter.
Den Konstruktor der Page Klasse müssen wir nun anpassen
public function __construct($request, $cfg, $pdo, $language, $dir = 'pages') {
$this->language = $language;
//...
}
Und folgendes in der Page Klasse definieren, nicht vergessen!
So nun sind wir fertig und können die Klasse benutzen. Wir erstellen uns im lang Verzeichnis eine neue Datei
Hier können wir nun alle Texte in einem JSON Array reinschreiben und nutzen können wir es dann wie folgt
Wenn du eine weitere Sprache hinzufügen möchtest bspw. englisch erstellst du im lang Ordner die Datei EN.json welche dann zum Beispiel so aussehen kann
Nun kannst du eine Seite erstellen wo der Nutzer seine Sprache für sich selbst ändern kann.
Das müsste dann ungefähr so aussehen
$lang = 'en';
if($this->language->exists($lang)) {
$_SESSION['LANGUAGE'] = strtoupper($lang);
$this->language->setLanguage($lang);
}
Es ist auch möglich Platzerhalter zu benutzen.
Ein kleines Beispiel