уторак, 28. јануар 2014.

Validation helper (ispravnost formi), PHP (OOP), PDO API

Ovaj helper ima zadatak da ukaže na neispravno popunjene forme, odnosno nepopunjene forme. 

Helper ne koristi framework za razliku od ostalih projekata na blogu, ali svakako ima za cilj da demonstrira OO pristup, PDO API kroz prepare() statement i tzv. SQL Injection, sve to naravno kroz PHP. Sam helper nije veliki (koristi samo 3 klase), ali se uz veoma malu doradu uspešno može implementirati u svaki custom framework. Na isti (ili barem sličan) način funkcionišu validation_helper, odnosno validation_library u mnogim radnim okvirima kojima upravlja PHP.

Dakle, u našem slučaju ćemo koristiti  bazu sa jednom tabelom, čisto radi provere da li uneti podatak sa forme već postoji u bazi ili ne. Sve ostalo se izvršava direktno u skruptu, bez komunikacije sa bazom.

Napomena: syntax highlighting na blogu hoće po neki put da "pojede" po koji html tag, tako da će vam se možda index.php učiniti malo čudnim. Kompletan projekat se može videti na github.com/vlradovanovic

Baza se može preuzeti ovde, a izgleda ovako:



-- phpMyAdmin SQL Dump
-- version 4.0.4.1
-- http://www.phpmyadmin.net
--
-- Host: 127.0.0.1
-- Generation Time: Jan 28, 2014 at 01:36 PM
-- Server version: 5.5.32
-- PHP Version: 5.4.19

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;

--
-- Database: `validacija`
--
CREATE DATABASE IF NOT EXISTS `validacija` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;
USE `validacija`;

-- --------------------------------------------------------

--
-- Table structure for table `korisnici`
--

CREATE TABLE IF NOT EXISTS `korisnici` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `korisnicko_ime` varchar(25) NOT NULL,
  `lozinka` varchar(60) NOT NULL,
  `ime_prezime` varchar(35) NOT NULL,
  `email` varchar(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;

--
-- Dumping data for table `korisnici`
--

INSERT INTO `korisnici` (`id`, `korisnicko_ime`, `lozinka`, `ime_prezime`, `email`) VALUES
(1, 'admin', 'd033e22ae348aeb5660fc2140aec35850c4da997', 'Vladimir Radovanovic', 'vl.radovanovic@gmail');

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;



Input_class.php -- Proverava da li postoji unos i ako postoji deklariše metode ($_GET, odnosno $_POST):
<?php
class Input_class
{
    //Ukoliko postoji unos, prveri da li je GET ili POST, oba dolaze u obzir
    //Default je 'post'
    
    public static function exist($case = 'post') 
    {
        switch ($case) {
            case 'post':
                
                if (!empty($_POST))
                {
                    return TRUE;
                }
                else                    return FALSE;

                break;
                
                  case 'get':
                
                if (!empty($_GET))
                {
                    return TRUE;
                }
                else                    return FALSE;

                break;

            default:
                break;
        }
    }
    
    public static function input($value) 
    {
        if (isset($_POST[$value]))
        {
            return $_POST[$value];
        }
        
        elseif (isset ($_GET[$value])) {
        
            return $_GET[$value];
    }
    return '';
    }    
}

FormValidation_class.php izgleda ovako:
<?php

class FormValidation_class
{
    //Definisani property
    private $__database = null,
            $__error = array(),
            $__success = false;
    
    public function __construct() {
      $this->__database = DataBase_class::instance();

    }
    
    public function check($input, $fields = array())
    {
        foreach ($fields as $fields => $rules) {
            foreach ($rules as $key => $key_value) {
                $value = $input[$fields]; // Unos sa tastature, polje textbox
                
                if ($key === 'obavezno' && empty($value)) //U slucaju da je polje obavezno a da je unos prazan
                {
                   $this->addError("{$fields} je obavezno uneti."); //Npr: Korisnicko ime je obavezno
                }
                
                elseif (!empty ($value)) {
                    
                    switch ($key) {
                        case 'minimalno':

                           if (strlen($value) < $key_value)
                           {
                               $this->addError("Polje {$fields} mora imati najmanje {$key_value} karaktera.");
                           }
                            break;
                            
                        case 'maksimalno':
                        {
                            
                            if (strlen($value) > $key_value)
                            {
                                $this->addError("Polje {$fields} mora imati najviše {$key_value} karaktera.");
                            }
                        }
                            break;
                            
                        case 'jedinstven': //U slucaju da vec postoji taj username u bazi
                        {
                            
                            $query = $this->__database->query("korisnicko_ime");
                           
                            if ($query->count())
                            {
                               $this->addError("{$fields} postoji u bazi, pokušajte sa nekim drugim.");
                            }
                        }
                        break;
                            
                        case 'isto':
                        {
                            
                            if ($value != $input[$key_value])
                            {
                                $this->addError("Polje {$fields} mora biti isto kao polje lozinka");
                            }
                        }
                        break;
                            
                        case 'ispravno':
                        {
                            
                            if (!preg_match("/([\w\-]+\@[\w\-]+\.[\w\-]+)/", $value))
                                    {
                                        $this->addError("Pogrešan {$key_value} format");
                                    }
                        }
                        break;

                        default:
                            break;
                    }
                
            }
            }
        }
        
        if (empty($this->__error))
        {
            $this->__success = TRUE;
        }
        return $this; //Vraca current objekat
    }
    
    public function success()
    {
        return $this->__success;
    }
    
    public function error()
    {
        return $this->__error;
    }
    
    private function addError($error)
    {
       $this->__error[] = $error;
    }

}

DataBase_class.php treba da izgleda ovako:

<?php
class DataBase_class {
    
    //Definisani property
    
    private static $__instance = null;
    
    private  $__pdo,
            $__error = false,
            $__result,
            $__query,
            $__count = 0;
    
    private function __construct() {
        
    // Napraviti konekciju prema bazi
        
    $hostname = "localhost";
    $user = "root";
    $pass = "";
    $dbname = "validacija";
    
    try {
         $conn = "mysql:host=$hostname;dbname=$dbname";
        
        $this->__pdo = new PDO($conn, $user, $pass);
        
    } 
    
         catch (Exception $exc) {
            die($exc->getMessage());
        }
        }
    
        
        public static function instance()
        {
            //Pomocu instance() komuniciramo sa bazom iz razlicitih klasa
            
            if (!isset(self::$__instance))
            {
                self::$__instance = new DataBase_class();
            }
            
            return self::$__instance;
        }
        
        public function query($value)
        {
            $this->__error = FALSE;
            
  
                    if ($this->__query = $this->__pdo->prepare("SELECT * FROM korisnici WHERE korisnicko_ime = :name"))
                    {
                        
                        $this->__query->bindParam(":name", Input_class::input($value));
                        
                        if ($this->__query->execute())
                        {
                              $this->__result = $this->__query->fetchAll(PDO::FETCH_OBJ);
                              $this->__count = $this->__query->rowCount();
                        }
                    }
                
                else {
                    
                $this->__error = TRUE;

            }
          
            return $this;
}


        public function count()
        {
            return $this->__count;
        }
        
       
        
        public function result()
        {
            return $this->__result;
        }
        
        public function error()
        {
            return $this->__error;
        }
    
}

Na kraju index.php izgleda ovako
<?php
spl_autoload_register(function($class) //Biblioteka koja ucitava sve klase projekta
{
    require_once 'class/'.$class.'.php';
}
    );
    
  if (Input_class::exist())
  {
      $formvalidation = new FormValidation_class();
      
      $validate = $formvalidation->check($_POST, array(
          
          'korisnicko_ime' => array(
              'obavezno' => TRUE,
              'minimalno' => 4,
              'maksimalno' => 20,
              'jedinstven' => 'korisnici'
          ),
          
              'lozinka' => array(
              'obavezno' => TRUE,
              'minimalno' => 5,
              'maksimalno' => 25,
      ),
          'ponovo_lozinka' => array(
              
              'obavezno' => TRUE,
              'isto' => 'lozinka' 
          ),
          
          'email' => array(
              'obavezno' => TRUE,
              'ispravno' => 'email'
              
          )));
      
      if ($validate->success())
      {
          ?>


    
        
        Registracija korisnika
        
    
    
        
        
<?php echo 'Validacija uspešno prošla'; ?>
" Polja označena sa * su obavezna!!! "
<?php } else { ?> Registracija korisnika
<?php foreach ($validate->error() as $error) { echo $error, ' '; } ?>
" Polja označena sa * su obavezna!!! "
<?php } } else { ?> Registracija korisnika
" Polja označena sa * su obavezna!!! "
<?php } ?>
Kompletan projekat se može preuzeti ovde.

Srdačan pozdrav.
Vladimir