CodeIgniter - Логин система
20-08-2010
Структурата на приложението е следната:
+application
-+controllers
--+home.php
--+users.php
-+views
--+home.php
--+login.php
--+register.php
--+output.php
-+models
--+Umodel.php

Ще започнем с контролера Home, който ще осигури нашата начална страница
Всеки контролер започва със създаването на клас с името на контролера, разширяващ класът Controller:
controllers/home.php
class Home Extends Controller {

Всеки контролер трябва да има функция-конструктор която изглежда така:
function Home {
parent::Controller();
}

След като сме създали контролера е време да създадем метод в него. По подразбиране CodeIgniter зарежда методът index ако е наличен.
Сега ще кажем на метода да извика изгледа "home", като изпрати данни за заглавието на страницата
function index() {
$data['title'] = "Начало";
$this->load->view("home", $data);
}

Целият файл изглежда така:
controllers/home.php
<?php
class Home extends Controller {

function Home() {
parent::Controller();
}

function index() {
$data['title'] = "Начало";
$this->load->view("home", $data);
}
}

Данните към изгледа се изпращат под формата на масив. Изгледът представлява статична HTML страница, в която можем да използваме данните подадени от контролера по следния начин:
Изпратихме следния масив до изгледа:
Array ( title => "Начало")
За да изведем информацията е достатъчно да напишем следното:
<?php echo $title ?>

А ето как ще изглежда цялата страница:
views/home.php
<html>
<head>
<title><?php echo $title ?></title>
</head>
<body>
Здравей!
</body>
</html>

И нашата първа връзка Контролер-Изглед е готова. За да видите резултата напишете в браузъра следното:
http://път.до/CodeIgniter/Home


Време е да направим още 2 изгледа - за регистрация и вход. Тук ще ви запозная с Form Helper - инструмент, който ви помага да създавате форми.
Създаваме файла views/register.php
Първата ни работа е да заредим Form Helper-а. Това става по следния начин:
<?php
$this->load->helper("form");

Повече за Form Helper: http://codeigniter.com/user_guide/helpers/form_helper.html
Сега ще направим нова форма, която ще води към контролера Users, метода Add, които ще създадем по-късно
echo form_open("users/add");

Започваме да добавяме полетата. Ще използваме 2 типа полета - стандартни и за парола + бутон за изпращане. За да придам вид на формата ще я сложа в таблица:
echo "<table><tr><td>Потребителско име</td><td>";
echo form_input("username")."</td></tr>";
echo "<tr><td>Парола</td><td>";
echo form_password("password")."</td></tr>";
echo "<tr><td>Потвърди парола</td><td>";
echo form_password("confirm")."</td></tr>";
echo "<tr><td>Е-майл адрес</td><td>";
echo form_input("email")."</td></tr>";
echo "<tr><td colspan='2'>";
echo form_submit("submit", "Регистрация")."</td></tr></table>";

Накрая затваряме формата така:
echo form_close();

По същия начин създаваме и изгледа за вход:
views/login.php
<?php
$this->load->helper("form");
echo form_open("users/log");
echo "<table><tr><td>Потребителско име</td><td>";
echo form_input("username")."</td></tr>";
echo "<tr><td>Парола</td><td>";
echo form_password("password")."</td></tr>";
echo "<tr><td colspan='2'>";
echo form_submit("submit", "Вход")."</td></tr></table>";
echo form_close();
?>


Създадохме още 2 изгледа и сега трябва да направим контролер за тях. Аз ще го кръстя Users:
controllers/users.php
<?php
class Users Extends Controller {

function Users {
parent:Controller();
}

Сега трябва да създадем методите. Ще ги кръстя register и login:

function register() {
$this->load->view("register");
}

function login() {
$this->load->view("login");
}


Сега след като имаме изгледи и контролер отговарящ за тях ни трябват хипервръзки между тях. Тук на помощ ни идва URL Helper-а. Тъй като най-вероятно ще го ползвате доста често, ви препоръчвам да го зареждате автоматично. Това става по следния начин:
Във файла config/autoload.php намирате $autoload['helper'] и добавяте 'url' към масива:
$autoload['helper'] = array('url');

Ако предпочитате да го правите ръчно, ще трябва да поставяте следния код във всеки изглед:
<?php $this->load->helper("url"); ?>

След като сте заредили helper-а хипервръзки се създават по следния начин:
<?php echo anchor("КОНТРОЛЕР/МЕТОД", "ТЕКСТ"); ?>

Сега ще добавим връзки от views/home.php към register и login:
views/home.php
<html>
<head>
<title><?php echo $title?></title>
</head>
<body>
Здравей!<br/>
<?php echo anchor("users/register", "Регистрация")?><br/>
<?php echo anchor("users/login", "Вход")?>
</body>
</html>

По същия начин можете да добавите връзки и в останалите изгледи
Още за URL Helper: http://codeigniter.com/user_guide/helpers/url_helper.html




Време е да минем към втората част. Ще започнем със създаването на таблица в базата данни:
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL auto_increment,
`username` varchar(16) NOT NULL,
`password` varchar(32) NOT NULL,
`email` varchar(128) NOT NULL,
`date` timestamp NOT NULL default CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
)

Ако все още не сте направили настройките за база данни можете да го направите от config/database.php
От тук нататък ще работим с библиотеките database и session, затова ви препоръчвам да ги настроите да се зареждат автоматично. Във файла config/autoload.php намерете $autoload['libraries'] и добавете 2те библиотеки към масива:
$autoload['libraries'] = array('database', 'session');


Сега ще направим модела, който ще отговаря за регистрацията, входа и изхода. Аз ще го кръстя Umodel:

models/Umodel.php
<?php
class Umodel extends Model {

function Umodel() {
parent::Model();
/**
$this->load->database();
$this->load->library('session');
Това няма да ви трябва ако сте настроили библиотеките да се зареждат автоматично
**/
}

До тук всичко е като при контролера. Сега започваме да добавяме методите, които ще обработват формите за регистрация/вход:
function Add() {
if($this->input->post("password") == $this->input->post("confirm")) {
$query = $this->db->get_where("users", array('username' => $this->input->post("username")));
if($query->num_rows() > 0) {
return "Потребител с това име вече съществува";
}
$data['username'] = $this->input->post("username");
$data['password'] = md5($this->input->post("password"));
$data['email'] = $this->input->post("email");
$this->db->insert("users", $data);
return "Регистрацията е успешна";
} else {
return "Паролите не съвпадат";
}
}

Тук виждате начина, по който се взима информация от POST и по който се добавя нов ред към базата данни. Създава се масив от този тип:
Array (pole1_v_database => "stoinost",
pole2_v_database => "stoinost 2")

И след това се ползва функцията
$this->db->insert("ТАБЛИЦА", $Array);


Ето го и метода за вход:
function Log() {
if($this->input->post("username") && $this->input->post("password")) {
$query = $this->db->get_where("users", array('username' => $this->input->post("username")));
if($query->num_rows() > 0) {
$row = $query->row();
if($row->password == md5($this->input->post("password"))) {
$this->session->set_userdata("username", $row->username);
return "Влезе успешно";
} else {
return "Грешна парола";
}
} else {
return "Няма потребител с това име";
}
} else {
return "Не са попълнени всички полета";
}
}

Тук виждате как се формулират SELECT заявки с WHERE клауза. Първия аргумент на функцията е таблицата, от която извличате данни, а вторият е масив. Масив от типа
Array(name = "Ivan")

връща следната WHERE клауза: WHERE name = "Ivan".
За Active Record Class и библиотеката Database може да прочетете тук: http://codeigniter.com/user_guide/database/index.html
Виждате и как се създава сесия:
$this->session->set_userdata("name", "value");

След малко ще ви покажа как се взима информация от сесията, но преди това да направим и метод за изход:
function Logout() {
$this->session->sess_destroy();
return "Излезе успешно";
}

Тук няма какво да се коментира. Повече за библиотеката session прочетете тук: http://codeigniter.com/user_guide/libraries/sessions.html

Остана само да добавим в контролера методи, които да се свързват с модела. Добаваме следния код в controllers/users.php
function Add() {
$result['output'] = $this->Umodel->Add();
$this->load->view("output", $result);
}

function Log() {
$result['output'] = $this->Umodel->Log();
$this->load->view("output", $result);
}

function Logout() {
$result['output'] = $this->Umodel->Logout();
$this->load->view("output", $result);
}

Но за да работи модела, трябва да го заредим в конструктора:
function Users() {
parent::Controller();
$this->load->model("Umodel");
}


Създаваме и един изглед в който да се извежда резултата:
views/output.php
<html>
<head>
<title>Междинна страница</title>
</head>
<body>
<?php echo $output?><br/>
<?php echo anchor("home", "Към началото")?>
</body>
</html>


Сега променяме и началната страница, като в controllers/home.php променим index-а така:
function index() {
$data['title'] = "Начало";
if($this->session->userdata("username")) {
$data['username'] = $this->session->userdata("username");
}
$this->load->view("home", $data);
}

Тук виждате как се взима информация от сесията:
$this->session->userdata("name")


После правим views/home.php да изглежда така:
<html>
<head>
<title><?php echo $title?></title>
</head>
<body>
<?php if(isset($username)):?>
<?php echo "Здравей, ".$username?>!<br/>
<?php echo anchor("users/logout", "Изход")?>
<?php else:?>
Здравей!<br/>
<?php echo anchor("users/register", "Регистрация")?><br/>
<?php echo anchor("users/login", "Вход")?>
<?php endif;?>
</body>
</html>

За синтаксиса във view файловете можете да прочетете тук: http://codeigniter.com/user_guide/general/alternative_php.html

Ако има нещо неясно питайте в коментарите, възможно е да съм допуснал грешка някъде. Всички файлове тествани и работещи може за изтеглите от тук






/ Трябва да сте регистриран за да напишете коментар /
От: bgmaniaka
21:16 23-08-2010
Не видях никъде папката config :|
От: raiden
21:33 23-08-2010
autoload.php:
От: raiden
21:35 23-08-2010
Предния коментар нещо се бъгна...
autoload.php:

$autoload['libraries'] = array('database', 'session');
$autoload['helper'] = array('url');
$autoload['plugin'] = array();
$autoload['config'] = array();
$autoload['language'] = array();
$autoload['model'] = array();

И вече всеки си настройва database.php
От: index
15:29 24-08-2010
system\application\config
От: raiden
16:47 24-08-2010
http://web-tourist.net/userfiles/2/2722.rar - config
От: rombeca
21:45 24-08-2010
Хубаво ама защо не използваш Form Validation Class за проверките? Пести една кофа код, слага защити и т.н.
От: raiden
23:27 24-08-2010
Ако тръгна да настройвам за всеки случай съобщенията за грешка дали ще ми спести код... така имам много по-голяма свобода над резултата, но виждам че имам някой пропуски - нямам проверка за наличие на потребителското име при регистрация например
От: Galli
13:26 26-08-2010
Съобщенията са настроени в system/language/en/form_validation_lang.php
Лично на мен в модела не ми харесва да се слага return 'лалала'; а само true/false
Също таблиците могат да се направят с HTML Table Class.
Но да не забравяме, че урокът е само един пример.
От: raiden
16:07 26-08-2010
От там мога да ги настроя глобално, ама не звучи много добре "Полето password не съвпада с полето confirm" нали :) И ще трябва да ги настройвам локално по време на изпълнението и кода пак ще си стане толкова
От: adrian
16:35 02-09-2010
Form_validation е един от най-полезните класове на CI и неизползването му е равносилно на "остави CI настрана и не се занимавай с MVC". Урокът в общи линии е хубав, но това с неизползването на form_validation просто не можех да го подмина.

set_rules ти дава да зададеш user friendly име на полето, което хвърля грешката и можеш да си сложиш каквото искаш, за да не се получава съобщение като това, което написа.

В кода ти си направил една единствена проверка и затова не се вижда недостатъкът, но ако трябва да сложиш required на всички input полета, ако трябва да направиш проверка за валиден email, ако имаш максимална и минимална дължина на дадени полета, тогава вече ще се загуби ефекта от ползването на MVC.

Също така проверката за съществуващо име може да стане също чрез form_validation. В момента се сещам за два начина. Единия е чрез разширяване на form_valiation класа (който ползвам аз в проектите си), a другият е със създаване на callback функция и слагането и като rules.

Написал си, че ако за всяка грешка трябва да си пишеш собствен текст ръчно в кода ще стане много код, така е, но поне е структуриран :)
От: Mapu0
15:00 15-09-2010
Много добър урок за начинаещите ;)
От: _PHP_
1:12 05-12-2010
Нищо лично към raiden или към който и да било, напротив - евала за труда, НО!
Има едно голямо НО!
Ето как стоят нещата при мен. Пишех процедурен код, но всички ни "огрява" рано или късно и реших, че ми трябва нещо по-мощно, по-гъвкаво. Започнах да чета за ООП при PHP. Не след дълго попаднах и на интересни четива за MVC, Frameworks и пр.
Тогава избрах и CodeIgniter за първия си framework. Веднага проверих тук и попаднах на този урок, прочетох го, като доста от нещата схванах, но също толкова и НЕ успях да проумея. Все пак реших, че съм прекалено тъп и продължих с образоването си в тази насока, като четях каквото ми падне(и продължавам да го правя) и разбира се е тематично.
След ден, два четене отново се върнах на статията и разбрах, че никак не е за начинаещи и най-малкото, оставя вредни навици, като НЕизползването на класа за валидация на формите, който е един от най-използваните в CI, както колегите вече споменаха.
Извод: Урока не е съвсем за начинаещи, а по-скоро за такива, които имат съвсем базови понятия за MVC модела и ООП.

Поздрави!
1