Skocz do zawartości

Tworzenie własnego CMS - problemy i pytania początkującego


 Udostępnij

Rekomendowane odpowiedzi

  • Ekspert

Joł, postanowiłem założyć temat zbiorczy na wszelkie moje problemy związane z tworzeniem CMSa (systemu zarządzania treścią) by mięć całe FAQ w jednym wątku ☺️

Nie ukrywam, ale z PHP nie mam wiele wspólnego i dlatego (w tym przypadku) sięgam po gotowe rozwiązania modyfikując je pod swoje potrzeby, ale do rzeczy.

Mam problem z rejestracją użytkownika. Walidacja działa jak należy jednak w przypadku gdy kliknie się na przycisk rejestracji wyskakuje błąd:

SQLSTATE[HY093]: Invalid parameter number: parameter was not defined

Czytając na stackoverflow doszedłem do tego, że jest to zbyt ogólny komunikat i może dotyczyć dosłownie wszystkiego. Lecz postępując zgodnie z jego treścią przeszukałem każdą funkcję, która posiada jakieś argumenty i sprawdzałem czy wszystko się zgadza.

Nie byłem do końca pewnym kilku linijek dlatego też próbowałem różnych kombinacji i efekt był taki sam

Dołączam następujące pliki, może wy będziecie w stanie powiedzieć mi co jest źle. Osobiście mam pewne wątpliwości co do metody prepare().

Spoiler

init.php


<?php
    session_start();
    require_once '../inc/class.Dbconfig.php';

    global $pdo;
    $db = Database::getInstance();
    $pdo = $db->GetConnection();
?>

 

Spoiler

class.Dbconfig.php


<?php
    class Database {
        private $connection;
        private static $instance;
        private $dsn = 'mysql:host=xxxt;dbname=xxx';
        private $name = 'xxx';
        private $password = 'xxx';

        public static function getInstance() {
            if( !self::$instance )
                self::$instance = new self();
            return self::$instance;
        }

        public function __construct() {
            try {
                $this->connection = new PDO( $this->dsn, $this->name, $this->password );
                $this->connection->setAttribute( PDO::ATTR_PERSISTENT, TRUE );
                $this->connection->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
            }
            catch ( PDOException $e ) {
                echo $e->getMessage();
                die();
            }
        }

        private function __clone() { }

        public function getConnection() {
            return $this->connection;
        }
    }
?>

 

Spoiler

class.Register.php


<?php
    class Register {
        private $connection;

        public function __construct( $data ) {
            $this->connection = $data;
        }

        public function registerUser( $user_name, $user_password, $user_email ) {
            try {
                $new_password = password_hash( $user_password, PASSWORD_DEFAULT );
   
                $stmt = $this->connection->prepare("INSERT INTO users( login, password, email ) VALUES( :user_name, :user_password, :user_mail )");
              
                $stmt->bindparam( ":user_name", $user_name ); 
                $stmt->bindparam( ":user_mail", $user_email );
                $stmt->bindparam( ":user_password", $new_password );           
                $stmt->execute(); 
        
                return $stmt; 
            } catch( PDOException $e ) {
                echo $e->getMessage();
            }
        }

        public function redirect( $url ) {
            header( "Location: $url" );
        }
    }
?>

 

Spoiler

register.php


<?php
    require_once '../core/init.php';
    require_once '../inc/class.Register.php';

    $user = new Register( $pdo );
    
    if( isset( $_POST[ 'btn-submit' ] ) ) {
        $form_name = trim( $_POST[ 'username' ] );
        $form_password = trim( $_POST[ 'pass' ] );
        $form_passwordre = trim( $_POST[ 'pass-re' ] );
        $form_email = trim( $_POST[ 'email' ] );

        if( $form_name == "" )
            $error[] = 'Proszę wprowadzić nazwę użytkownika!';
        else if( $form_password  == "" )
            $error[] = "Proszę wprowadzić hasło użytkownika!";
        else if( strlen( $form_password ) < 6 )
            $error[] = "Hasło musi zawierać minimum 6 znaków";
        else if( $form_password != $form_passwordre )
            $error[] = "Podane hasła różnią się od siebie!";
        else if( $form_email == "" )
            $error[] = "Proszę wprowadzić adres email!";
        else if( !filter_var( $form_email, FILTER_VALIDATE_EMAIL ) )
            $error[] = "Proszę wprowadzić poprawny adres email";
        else {
            try {
                $stmt = $pdo->prepare( "SELECT login, email FROM users WHERE login = :user_name OR email = :user_email" );
                $stmt->execute( array( ':user_name' => $form_name, ':user_mail' => $form_email ) );
                $row = $stmt->fetch( PDO::FETCH_ASSOC );

                if( $row[ 'login' ] == $form_name )
                    $error[] = "Niestety, ale wybrany login jest już zajęty";
                else if( $row[ 'email'] == $form_email )
                    $error[] = "Niestety, ale wybrany email jest już zajęty";
                else {
                    if( $user->registerUser( $form_name, $form_password, $form_email ) )
                        $user->redirect( 'sign-up.php?joined' );
                }
            } catch( PDOException $e ) {
                echo $e->getMessage();
            }
        } 
    }
?>
<!DOCTYPE html>
<html land="pl">
    <head>

        <?php
            include( 'site_head.php' );
        ?>
        <link rel="stylesheet" href="assets/css/style.css">

        <title>Rejestracja</title>

    </head>
    <body>

        <form class="form" method="post" name="Rejestracja">
            <h1>Rejestracja</h1>
            <?php 
                if( isset( $error ) )  {
                    foreach( $error as $error ) {
                        ?>
                        <div class="form__error">
                            <p class="form__text"><?php echo $error ?></p>
                        </div>
                        <?php 
                    }
                } else if( isset( $_GET[ 'joined' ] ) ) {
                    ?>
                    <div class="form__enter">
                        <p class="form__text">Zarejestrowano pomyślnie!</p>
                    </div>
                    <?php
                }
            ?>
            <label for="name">Nazwa użytkownika</label>
            <div class="input-group">
                <input type="text" name="username" id="name" class="form__input" value="" placeholder="Wprowadź nazwę użytkownika">
                <span class="input__icon fa fa-user" aria-hidden="true"></span>
            </div>
            <label for="password">Hasło użytkownika</label>
            <div class="input-group">
                <input type="password" name="pass" id="password" class="form__input" value="" placeholder="Wprowadź hasło użytkownika">
                <span class="input__icon fa fa-lock" aria-hidden="true"></span>
            </div>
            <label for="password-re">Powtórz hasło</label>
            <div class="input-group">
                <input type="password" name="pass-re" id="password-re" class="form__input" value="" placeholder="Wprowadź ponownie hasło">
                <span class="input__icon fa fa-lock" aria-hidden="true"></span>
            </div>
            <label for="email">Adres email</label>
            <div class="input-group">
                <input type="email" name="email" id="email" class="form__input" value="" placeholder="Wprowadź adres email">
                <span class="input__icon fa fa-envelope" aria-hidden="true"></span>
            </div>
            <div class="input-group">
                <button type="submit" name="btn-submit" id="btn-submit" class="fom__button">
                    Utwórz konto<span class="fa fa-plus" aria-hidden="true"></span>
                </button>
                <button type="reset" name="btn-reset" id="btn-reset" class="form__buttin">
                    Resetuj pola<span class="fa fa-close" aria-hidden="true"></span>
                </button>
            </div>
        </form>
        
    </body>
</html>

 

1. SQLSTATE[HY093]: Invalid parameter number: parameter was not defined

    Tworzenie własnego CMS (systemu zarządzania treścią) - parameter was

Edytowane przez Lord Fenrir
Odnośnik do komentarza
Udostępnij na innych stronach

  • Ekspert

Moje uwagi:

  1. Nie korzystaj z $_* tylko zapoznaj się z filter_input()
  2. array() zamień na [] - chyba, że potrzebujesz wsparcie dla PHP < 5.4

A co do błędu, na pewno wyrzuca go przy wywołaniu metody registerUser() ?

Być może skrypt w ogóle nie wie co to $pdo przez literówkę:

<?php
$pdo = $db->GetConnection();

A metodę nazwałeś getConnection()

Edytowane przez BlackIce
Odnośnik do komentarza
Udostępnij na innych stronach

  • Ekspert

Naprawione, brakowało literki, a dokładnie tutaj przy execute, wyżej jest user_email, a ja wpisałem user_mail

$stmt = $pdo->prepare( "SELECT login, email FROM users WHERE login = :user_name OR email = :user_email" );
$stmt->execute( array( ':user_name' => $form_name, ':user_mail' => $form_email ) );

@SeNioR możesz przywrócić starą nazwę wątku, bo jak mówiłem chciałem z tego zrobić osobiste FAQ i odpowiednia nawigację do danego problemu by mieć wszystko w jednym miejscu

Edytowane przez Lord Fenrir
naprawione
Odnośnik do komentarza
Udostępnij na innych stronach

  • 3 tygodnie później...
  • Ekspert

Przychodzę z kolejnym problemem. Projekt się trochę rozrósł i w pewnym momencie postanowiłem zrobić tak aby sprawdzało czy jakaś tabela istnieje, a jeśli nie to żeby ją tworzyło. Aby nie trzeba było z palca wpisywać zapytań do mysqla. Więc w pliku init.php napisałem coś takiego:

$sql_users = "CREATE TABLE IF NOT EXISTS `users`(
        `id` INT AUTO_INCREMENT PRIMARY KEY,
        `login` VARCHAR(30) NOT NULL,
        `password` VARCHAR(30) NOT NULL,
        `email` VARCHAR(70) NOT NULL,
        `register_date` TIMESTAMP,
        `login_date` TIMESTAMP) ENGINE = MYISAM";
$pdo->exec( $sql_users);

Działa, tworzy się tabela jeżeli nie istnieje, ale teraz przestało mi działać logowanie. Wygląda tak jakby funkcja weryfikująca nie mogła dopasować haseł.

class.Register.php

public function registerUser( $user_name, $user_password, $user_email ) {
            try {
                $new_password = password_hash( $user_password, PASSWORD_DEFAULT );
   
                $stmt = $this->connection->prepare("INSERT INTO `users`( `login`, `password`, `email`, `register_date` ) VALUES( :user_name, :user_password, :user_mail, :register_date )");
              
                $stmt->bindparam( ":user_name", $user_name ); 
                $stmt->bindparam( ":user_mail", $user_email );
                $stmt->bindparam( ":user_password", $new_password ); 
                $stmt->bindparam( ":register_date", date( 'Y-m-d' ) );         
                $stmt->execute(); 
        
                return $stmt; 
            } catch( PDOException $e ) {
                echo $e->getMessage() . '3';
            }
}

class.Login.php

public function loginUser( $user_name, $user_password ) {
            try {
                $stmt = $this->connection->prepare( "SELECT * FROM `users` WHERE `login` = :user_name LIMIT 1" );
                $stmt->execute( array( ':user_name' => $user_name ) );
                $row = $stmt->fetch( PDO::FETCH_ASSOC );

                $stmt2 = $this->connection->prepare( "UPDATE `users` SET `login_date` = now() WHERE `login` = :user_name" );
                $stmt2->execute( array( ':user_name' => $user_name ) );

                if( $stmt->rowCount() > 0 ) {
                    if( password_verify( $user_password, $row[ 'password' ] ) ) {
                        $_SESSION[ 'user_session' ] = $row[ 'id' ];
                        return true;
                    } else {
                        return false;
                    }
                }

            } catch( PDOException $e ) {
                echo $e->getMessage();
            }
}

Komunikat zwrotny przy próbie zalogowania: "Wprowadzono błędna nazwę uzytkownika lub hasło."

if( $user->loginUser( $form_name, $form_password ) )
	$user->redirect( 'admin/index.php' );
else
	$error = "Wprowadzono błędna nazwę uzytkownika lub hasło.";

@BlackIce liczę na Ciebie

Edytowane przez Lord Fenrir
Odnośnik do komentarza
Udostępnij na innych stronach

  • Ekspert

Żeby po wgraniu na zewnętrzny serwer nie trzeba było tworzyć tego od ręki. Projekt nie ma żadnego instalatora ani nic co by służyło do konfiguracji. W przypadku gdy pierwszy raz zostanie włączona jakaś podstrona skrypt sprawdzi czy istnieje tabela z użytkownikami (wyjdzie, że nie ma takiej) i ją utworzy. Następnie podczas rejestracji pierwsze założone konto jest tym głównym, które może zarządzać pozostałymi ☺️

Odnośnik do komentarza
Udostępnij na innych stronach

  • Ekspert

Tworzysz tabelę i ograniczasz pole hasła do 30 znaków:

`password` VARCHAR(30) NOT NULL,

Natomiast do tworzenia hasła uzywasz:

password_hash( $user_password, PASSWORD_DEFAULT );

Z dokumentacji - PHP: password_hash - Manual  - wyczytać można:

Cytuj

(...) recommended to store the result in a database column that can expand beyond 60 characters (255 characters would be a good choice).

Odnośnik do komentarza
Udostępnij na innych stronach

  • Ekspert

Hehs, w sumie myślałem, że będzie to szło dużo gorzej biorąc pod uwagę, że średnio lubię bawić się bebechami. Mam jednak teraz trochę inne pytanie.

Do wyświetlania danych (użytkowników, kategorii) używam tabelki, w której mam pole o nazwie ID, które pobiera z bazy danych id i tym samym wyświetla kolejność. Jako, że id jest kluczem głównym ma włączoną auto inkrementacje, jednak mam problem w przypadku usunięcia jakiejś pozycji. Wyświetlane ID się nie zmniejsza a z tego co udało mi się wyczytać to automatyczna dekrementacja klucza głównego jest niewskazana, więc jak do tego podejść?

Odnośnik do komentarza
Udostępnij na innych stronach

  • Ekspert

No jak? Przecież nie mogę zostawić tabelki w taki sposób:

ID: |    Nazwa    |    Data Rejestracji    |    Data ostatniego logowania    |
1        admin            01-01-2000                    01-01-2000
3    testowe-konto        01-01-2000                    01-01-2000
7       admin1            01-01-2000                    01-01-2000
...

Tego samego używam na stronie głównej do wyświetlania kategorii, w które gość klika

Odnośnik do komentarza
Udostępnij na innych stronach

  • Ekspert

Dobrze, prawdopodobnie ostatnie moje pytanie, ale jak przefiltrować zawartość textarea ($zmienna = $_POST[ 'textarea' ]) tak aby wprowadzony tekst do bazy danych mógł zawierać kod dowolnego języka programowania ale nie był wykonywany? Korzystam z edytora markdown (SimpleMDE)?

Odnośnik do komentarza
Udostępnij na innych stronach

Problem wciąż nierozwiązany? Dodaj swoją odpowiedź

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto. Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się
 Udostępnij

×