• Acasă
  • Despre noi
  • Autori
  • Mărturii
  • Arhivă
  • Trimite Articol
  • Contact

WORLDIT

Lumea în 1 și 0.

  • Știri
    • Tehnologie
    • Tehnologie mobilă
    • Securitate
    • Developers
    • Știință
    • Benzi desenate
    • Jocuri
    • Intern
  • Tehnic
    • Browser
    • C#
    • C/C++
    • Challenge
    • HTML/CSS
    • Javascript, Ajax, jQuery
    • Open Source
    • PHP
    • Python
    • Securitate IT
    • Socializare
    • WordPress
    • Altele
  • Recenzii
  • Interviuri
  • Evenimente

Introducere in Design Patterns – MVC (partea I)

13
  • Publicat de Andrei Avădănei
  • în PHP · Tehnic
  • — 14 mai, 2010 at 5:39 pm

Introducere in Design Patterns

Problema?

Una dintre cele mai mari probleme ce sunt intalnite in proiectele de anvergura este organizarea eficienta pentru a putea lucra cu o echipa de programatori. De asemenea, cu totii realizam la un moment dat ca scriem cod prost. Eu definesc codul prost ca fiind nepregatit pentru reutilizare in alte aplicatii. Nu de multe ori suntem nevoiti sa facem sisteme de inregistrare, de autentificare, avem nevoie de numeroase modalitati de a accesa bazele de date etc. Dar, toate aceste probleme care pot fi scrise o data si folosite ulterior au ceva in comun : o data implimentate, modificarile ce trebuie aduse pentru a putea fi refolosite sunt minime. Insa ce ne facem daca incercam sa editam acel cod dupa un an?

Solutia?

Evident, solutia sta in mainile noastre. Trebuie sa gandim o modalitate de lucru ce se potriveste perfect pentru orice tip de proiect, spunem noi, trebuie sa stabilim arhitectura ce o au in comun toate proiectele. Practic, un punct de reper pentru a descoperi un programator bun, indiferent de limbajele in care lucreaza, este abilitatea acestuia de a aplica tehnici cunoscute in industrie pentru a arhitecturiza proiectele intr-un mod eficient. Design Patterns (sau proiectarea modulelor) sunt un set de solutii ce pot fi aplicate la diverse probleme ce se intalnesc frecvent in cadrul programarii orientate pe obiecte (POO). Cateva din cele mai populare design patternuri folosite la scara larga sunt Singleton, Factory, Registry si MVC. Acestea sunt prezentate foarte frumos in articolul Design Patterns de pe Tutorial Web sau pe WorldIT.

Primele trei modalitati de lucru sunt simple, in vreme ce MVC reprezinta o structura complexa si foarte eficienta, ce se potriveste cu aproape orice tip de proiect, fiind recomandat si folosit in cele de anvergura. In urmatoarele zile ma voi concentra pe explicarea intr-un mod cat mai clar pe utilitatea si modul de lucru a acestei arhitecturi – MVC.

Introducere in MVC

Ce este MVC?

MVC, sau Model-View-Controller este un sablon arhitectural folosit in industria de software development(inclusiv web development). Aceasta modalitate de lucru reuseste cu succes izolarea partii logice de interfata proiectului, rezultand in aplicatii extrem de usor de modificat. In organizarea MVC, modelul reprezinta informatia (datele) de care are nevoie aplicatia, viewerul corespunde cu elementele de interfata iar controller-ul reprezinta sistemul comunicativ si decizional ce proceseaza datele informationale, facand legatura intre model si view.

Despre Model, View si Controller

Modelul reprezinta partea de hard-programming, partea logica a aplicatiei. El are in responsabilitate actiunile si operatiile asupra datelor, autentificarea utilizatorilor, integrarea diverselor clase ce permit procesarea informatiilor din diverse baze de date.

View-ul se ocupa de afisarea datelor, practic aceasta parte a programului va avea grija de cum vede end-userul informatia procesata de controller. O data ce functiile sunt executate de model, viewului ii sunt oferite rezultatele, iar acesta le va trimite catre browser. In general viewul este o mini-aplicatie ce ajuta la randarea unor informatii, avand la baza diverse template-uri.

Controller-ul reprezinta creierul aplicatiei. Aceasta face legatura intre model si view, intre actiunile userului si partea decizionala a aplicatiei. In functie de nevoile utilizatorului, controllerul apeleaza diverse functii definite special pentru sectiunea de site in care se afla userul. Functia se va folosi de model pentru a prelucra (extrage, actualiza) datele, dupa care informatiile noi vor fi trimise catre view, ce le va afisa apoi prin template-uri.

Structura unei aplicatii folosind arhitectura MVC

Acest tutorial va prezenta structura ce o folosesc personal pentru a organiza in format MVC un nou framework. Aceasta serie de articole se va invarti in jurul acestei structuri.

• application
  aplicatie1
    controller
    model
    view
  aplicatie2
  aplicatie3
• config
• db
• library
  cache
  controller
  model
    dbs
  view
    templates
• public
  aplicatie1
    css
    img
    js
    swf
  aplicatie2
  aplicatie3
• tmp
  cache
  logs
  sessions

Tutorial MVC – crearea structurii de baza a framework-ului

Definirea unui singur punct accesibil din partea clientului

Prima problema ce o intalnim este stabilirea unui singur punct de intrare, un index.php care va avea grija de tot si toate. Pentru a usura acest proces ne vom folosi de URL redirecting si permalinks, care sunt evident configurate din .htaccess.

Mai intai adaugam un fisier .htaccess in root-ul arhitecturii cu urmatorul cod. Acesta va redirecta totul catre folderul /public al aceleiasi arhitecturi.

<IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteRule    ^$    public/    [L]
    RewriteRule    (.*) public/$1    [L]
 </IfModule>

;
Urmeaza sa cream un nou fisier .htaccess in directorul /public.

<IfModule mod_rewrite.c>
RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule ^(.*)$ index.php?url=$1 [PT,L]

 </IfModule>

Fisierul public/index.php

Aceasta pagina va avea declarate cateva constante si va incarca bootstrap-ul.

<?php
 
/**
 * Use the DS to separate the directories in other defines
 */
	if(!defined('DS')) 
		define('DS',DIRECTORY_SEPARATOR);
/**
 * The full path to the directory which holds "app", WITHOUT a trailing DS.
 *
 */
	if(!defined('ROOT')) 
		define('ROOT',dirname(dirname(__FILE__)));
/**
 * The actual directory name for the "app".
 *
 */
	if (!defined('APP_DIR')) 
		define('APP_DIR', ROOT . DS . 'application');
/**
 * The actual WWW_ROOT Directory. It has a trailing DS.
 *
 */
if (!defined('WWW_ROOT')) 
	define('WWW_ROOT', dirname(__FILE__) . DS);
	

if(!defined('CORE_PATH')) 
	define('CORE_PATH',ROOT . DS . 'library' . DS );


if(!defined('CONFIG_DIR')) 
	define('CONFIG_DIR',ROOT . DS . 'config'  );


if(file_exists(CORE_PATH . 'bootstrap.php')) 
	require_once(CORE_PATH . 'bootstrap.php');
else 
	trigger_error('Framework core could not be found.  Check the value of CORE_PATH. IT should point to '.DS.' library.'.DS.'bootstrap.php .');

?>

Fisierul library/basics.php

Acest fisier contine, dupa cum spune si numele, cateva functii de baza, de care ne vom izbi pe tot parcursul procesului de dezvoltare al arhitecturii. Functia setReporting() stabileste daca suntem in timpul dezvoltarii si trateaza variabile pe ecran, in vreme ce in afara starii de developer, erorile vor fi stocate pe disc. Functia killMagicQuotes() va cauta magic quotes si le va elimina, unregisterGlobals() va elimina variabilele globale, __autoload() este una din functiile magice ce se bazeaza pe overloading ce va face putina magie : va incarca toate fisierele necesare pentru clase. Functia clear este functia care se va apela recursiv curatand un vector de orice dimensiune/adancime prin htmlentities.

<?php
/** Check if environment is development and display errors **/
function setReporting()
{
	if(Configure::read('Dev.Enviroment') === TRUE)
	{		
		error_reporting(E_ALL);
		ini_set('display_errors','On');
	}
	else
	{
		error_reporting(E_ALL);
		ini_set('display_errors','Off');
		ini_set('log_errors','On');
		ini_set('error_log',ROOT.DS.'tmp'.DS.'logs'.DS.'error.log');
	}
}
/** Check for magic quotes and remove it **/
function stripSlashDeep($value)
{
	return (is_array($value) ? array_map('stripSlashDeep',$value) : stripslashes($value));
}
function killMagicQuotes()
{
	if(get_magic_quotes_gpc())
	{
		$_GET     = stripSlashesDeep($_GET);
		$_POST    = stripSlashesDeep($_POST);
		$_COOKIE  = stripSlashesDeep($_COOKIE);
		//$_SERVER  = stripSlashesDeep($_SERVER);
		//$_SESSION = stripSlashesDeep($_SESSION);
	}
}
/** Check register globals and remove them **/
function unregisterGlobals() 
{
    if (ini_get('register_globals')) 
	{
        $array = array('_SESSION', '_POST', '_GET', '_COOKIE', '_REQUEST', '_SERVER', '_ENV', '_FILES');
        foreach ($array as $value) 
            foreach ($GLOBALS[$value] as $key => $var) 
                if ($var === $GLOBALS[$key]) unset($GLOBALS[$key]);
    }
}
/** Autoload any classes that are required **/
function __autoload($className) 
{	
	if (file_exists(LIB_CONTROLLER . DS . strtolower($className) . '.php'))
		require_once(LIB_CONTROLLER . DS . strtolower($className) . '.php');
	else if (file_exists(LIB_MODEL . DS . strtolower($className) . '.php'))
		require_once(LIB_MODEL . DS . strtolower($className) . '.php');
	else if (file_exists(LIB_VIEW . DS . strtolower($className) . '.php'))
		require_once(LIB_VIEW . DS . strtolower($className) . '.php');
	else if (file_exists(APP_CONTROLLER  . DS . strtolower($className) . '.php')) 
		require_once(APP_CONTROLLER . DS . strtolower($className) . '.php');
	else if (file_exists(APP_MODEL . DS . strtolower($className) . '.php')) 
		require_once(APP_MODEL . DS . strtolower($className) . '.php');
	else if(file_exists(LIB_MODEL . DS . 'dbs' . DS . strtolower($className) . '.php'))
		require_once(LIB_MODEL . DS . 'dbs' . DS . strtolower($className) . '.php');
	else 
	{
		/* Error Generation Code Here **/
	//	trigger_error('We couldn`t find '.$className.' .');
	}
}

?>

Fisierul library/bootstrap.php

In acest fisier vom incarca cateva din cele mai importante fisiere. Vom apela functiile din basics.php prezentate anterior pentru a curata variabilele si a filtra putin informatiile. Acest fisier va incarca una din clasele cele mai importante : dispatcherul, sau cel care spune cine sa faca ce. Dispatcherul functioneaza in urmatorul mod : www.worldit.info/controller/actiune/query. Pentru a intelege mai exact cum functioneaza dispatcherul ne vom imagina ca avem urmatorul link :
• www.worldit.info/news/show/id/1

Controllerul e news
Modelul este new
Viewul este este show
Actiunea este show
Query-ul este un array (id,1)

<?php
if (!defined('PHP5')) {
	define('PHP5', (PHP_VERSION >= 5));
}

if(!defined('BOOTSTRAP')) {	
	require_once(ROOT . DS . 'library' . DS . 'paths.php');
	require_once(LIBRARY_DIR . DS . 'basics.php');
	require_once(LIBRARY_DIR . DS . 'dispatcher.php');
	require_once(LIBRARY_DIR . DS . 'cache.php');
	require_once(LIBRARY_DIR . DS . 'configure.php');
	require_once(CONFIG_DIR . DS . 'core.php');
	require_once(CONFIG_DIR . DS . 'config.php');
}

setReporting();
killMagicQuotes();
unregisterGlobals();
$Dispatcher = new Dispatcher($_GET['url'],array('render' => TRUE, 'layout' => TRUE));
?>

Fisierul library/paths.php

Acest fisier contine cateva constante ce ne vor ajuta pe parcurs la utilizarea eficienta a cailor relative si absolute ale fisierelor framework-ului.

<?php
	if(!defined('APP'))
		define('APP', 'apptest');
		
	if (!defined('APP_CONTROLLER')) 
		define('APP_CONTROLLER', APP_DIR . DS . APP . DS . 'controller');
	
	if (!defined('APP_MODEL')) 
		define('APP_MODEL', APP_DIR . DS  . APP . DS . 'model');
	
	if (!defined('APP_VIEW')) 
		define('APP_VIEW', APP_DIR . DS  . APP . DS . 'view');
	
	if (!defined('LIBRARY_DIR')) 
		define('LIBRARY_DIR', ROOT . DS . 'library');
	
	if (!defined('LIB_CONTROLLER')) 
		define('LIB_CONTROLLER', LIBRARY_DIR . DS . 'controller');
	
	if (!defined('LIB_MODEL')) 
		define('LIB_MODEL', LIBRARY_DIR . DS . 'model');
	
	if (!defined('LIB_VIEW')) 
		define('LIB_VIEW', LIBRARY_DIR . DS . 'view');
	
	if (!defined('LIB_TEMPLATES')) 
		define('LIB_TEMPLATES', LIB_VIEW . DS . 'templates');
	
	if (!defined('TMP')) 
		define('TMP', ROOT . DS . 'tmp');
	
	if (!defined('CACHE')) 
		define('CACHE', TMP . DS . 'cache');
	
?>

Clasa Object – baza controalelor (library/controller/object.php)

Aceasta clasa este putin mai dezvoltata decat o clasa abstracta, prezentand cateva din functiile de baza necesare in toate clasele noastre ulterioare. Prezinta functiile __construct(), __destruct(), __toString() si log(), create special doar pentru overloading ulterior in clasele copii. Functia _set() este utila pentru a seta variabile dinamic iar dispatchMethod() apeleaza o functie din interiorul obiectului, fiind o optimizare smechera pentru imbunatatirea performantelor.

<?php

class Object 
{
	/**
	 * Log object
	 *
	 * @var FrameworkLog
	 * @access protected
	 **/
	var $_log;
	
	/**
	 * Returns a singleton instance
	 *
	 * @return object
	 * @access public
	 * @static
	 **/
	public static function &getInstance() 
	{
		static $instance = array();
		$name = get_class($this);
		if (!$instance) 
			$instance[0] =& new $name();
		return $instance[0];
	}
	
   /**
	 * Class constructor, overridden in descendant classes.
	**/
	public function __construct()
	{
		//this will be overridden by other classes
	}
	
   /**
	 * Class destructor, overridden in descendant classes.
	**/
	public function __destruct()
	{
		//this will be overridden by other classes
	}
	
   /**
	 * Object-to-string conversion.
	 * Each class can override this method as necessary.
	 *
	 * @return string The name of this class
	 * @access public
	 **/
	public function __toString() 
	{
		$class = get_class($this);
		return $class;
	}
	
    /**
	 * Stop execution of the current script, with an error code
	 *
	 * @param $status - exit with an error code
	 * @return void
	 * @access public
	 **/
	public function _stop($status = 0) 
	{
		exit($status);
	}
	
   /**
	 * API for logging events.
	 *
	 * @param string $msg Log message
	 * @param integer $type Error type constant.  
	 * @return boolean Success of log write
	 * @access public
	 **/
	public function log($msg = '', $error = 0)
	{
		//this will be overriden soon
		return FALSE;
	}
	
   /**
	 * You can add multiple proprieties of the object in a single line of code.
	 *
	 * @param array $properties An associative array containing properties and corresponding values.
	 * @return void
	 * @access protected
	 **/
	function _set($prop = array()) 
	{
		if (is_array($prop) && !empty($prop))
		{
			$vars = get_object_vars($this);
			foreach ($prop as $key => $val) 
				if (array_key_exists($key, $vars))
					$this->{$key} = $val;
		}
	}
	
   /**
	 * Calls a method on this object with the given parameters. Provides an OO wrapper
	 * for call_user_func_array, and improves performance by using straight method calls
	 * in most cases.
	 *
	 * @param string $method  Name of the method to call
	 * @param array $params  Parameter list to use when calling $method
	 * @return mixed  Returns the result of the method call
	 * @access public
	 **/
	public function dispatchMethod($method, $params = array()) 
	{
		switch (sizeof($params)) 
		{
			case 0:return $this->{$method}();
			case 1:return $this->{$method}($params[0]);
			case 2:return $this->{$method}($params[0], $params[1]);
			case 3:return $this->{$method}($params[0], $params[1], $params[2]);
			case 4:return $this->{$method}($params[0], $params[1], $params[2], $params[3]);
			default:return call_user_func_array(array(&$this, $method), $params); break;
		}		 
	}
}
?>

Clasa Dispatcher – managerul MVC (library/dispatcher.php)

Aceasta clasa, dupa cum spuneam si mai sus, reprezinta unul din creierii principali, o parte foarte importanta ce dirijeaza toate creierasele mai mici (controllerele). Functia dispatch() proceseaza prin intermediul unor functii auxiliare (_extractParams(),_parseUrl(),_restructureParams(),_getController()) parametri oferiti de utilizator prin intermediul URI si incarca controllerul de care avem nevoie, la actiunea ceruta cu parametrii (query) oferiti. De aceasta parte a procesului se ocupa functia _invoke().

<?php

class Dispatcher extends Object
{
	/** 
	 * the params for this request
	 *
	 * @var array
	 * @access public
	 **/
	var $params = NULL;
	/**
	 * Constructor.
	 **/
	function __construct($url = NULL, $additionalParams = array())
	{
		return $this->dispatch($url, $additionalParams);	
	}

	/**
	 * Dispatches and invokes given URL, handing over control to the involved controllers, and then renders the results. (if autorender)
	 * @param string $url URL information to work on
	 * @param array $additionalParams Settings array which is melded with the GET params
	 * @return boolean Success
	 * @access public
	**/
	function dispatch($url = NULL, $additionalParams = array())
	{
		if(is_array($url)) {
			$url = $this->_extractParams($url);
		}
		
		$url = $this->_parseUrl($url);
		
		$this->_restructureParams($url,$additionalParams); 
		$controller =& $this->_getController();
	 
		if(is_object($controller))
		{			
			if(isset($this->params['render'])) 
				$controller->autoRender = $this->params['render'];
			else $controller->autoRender = FALSE;
			
			if(isset($this->params['layout'])) 
				$controller->autoLayout = $this->params['layout'];
			else $controller->autoLayout = FALSE;
			
			$controller->here = APP_CONTROLLER; //TODO : Sure?
			$controller->_set($this->params);
			
			return $this->_invoke($controller);
		}
		else
		{
			$this->params = NULL;
			trigger_error('Invalid controller',E_USER_NOTICE);
		}
		return FALSE;
	}
	
	public function _invoke(&$controller)
	{
		$controller->startProc();	 
		
		$output = $controller->dispatchMethod($this->params['action'], $this->params['params']);
		 
		if ($controller->autoRender) 
			$controller->output = $controller->render(APP_VIEW . DS . $controller->action . DS . $controller->action .$controller->ext);
		elseif (empty($controller->output)) 
			$controller->output = $output;
				
		if(isset($this->params['return']) && $this->params['return'])
			return $controller->output;
		echo $controller->output;
	}
	
	
	/**
	 * Sets the params when $url is passed as an array to string Action
	 * @param array $url information array to work on
	 * @access public
	**/
	function _extractParams($url)
	{
		return implode('/', $url);
	}

	/**
	 * Sets the params when $url is passed as an array to string Action
	 * @param string $url information array to work on
	 * @access public
	**/
	function _parseUrl($url) 
	{
		return explode('/',$url);
	}

	/**
	 * Restructure Params if we deal with a plugin
	 * @param string $url information array to work on
	 * @param array $additionalParams Settings array which is melded with the GET params
	 * @access protected
	**/
	private function _restructureParams($url, $additionalParams) 
	{
		$this->params = array();
		$this->params['name']       = ($ctrl = ucwords(trim(array_shift($url)))) != '' ? $ctrl : 'Index';
		$this->params['controller'] = $this->params['name'].'Controller';
		$this->params['model']      = rtrim($this->params['name'],'s');
		$this->params['action']     = ($act = array_shift($url)) != '' ? $act : 'index';		
		
		$this->params['return']     = isset($additionalParams['return'])?$additionalParams['return']:TRUE;
		$this->params['layout']     = isset($additionalParams['layout'])?$additionalParams['layout']:TRUE;
		$this->params['render']     = isset($additionalParams['render'])?$additionalParams['render']:TRUE;
		
		unset($additionalParams['return'],$additionalParams['layout'],$additionalParams['render']);
		$this->params['params']     = array_merge($url, $additionalParams);
	}
	/**
	 * Get controller to use, either plugin controller or application controller
	 * @return mixed name of controller if not loaded, or object if loaded
	 * @access private
	 **/
	function _getController()
	{  
		if(class_exists($this->params['controller']))
		{
			$controller =& new $this->params['controller']();
			return $controller;
		} 
		else
		{
			return $this->params['controller'];
		}
	}
}


?>

Cam atat pentru prima parte care deja s-a intins foarte mult. Pana in acest moment am reusit sa introducem o parte din partile componente principale ale unui framework ce foloseste o structura de lucru MVC. In cea de-a doua parte a articolului voi introduce partile componente principale : Model View Controller. Daca ati digerat acest articol si nu aveti rabdare pana voi termina urmatoarea parte, puteti arunca o privire pe intregul framework, care poate fi inteles daca urmariti documentatia scrisa de mine pentru aproape toate functiile. Framework-ul din aceasta arhiva prezinta toate caracteristicile de baza de care are nevoie unul cu exceptia debuggerului. 🙂

Etichete: ce este mvcclasedesign patternsdespre factorydespre mvcdespre rgistrydespre singletonintroducere in mvcmodel view controllermvcoopPHPpootutorial design patternstutorial mvc

— Andrei Avădănei a scris 1246 articole

Andrei scrie pe worldit.info din vara lui 2011. Este fondatorul Asociatiei Centrul de Cercetare in Securitate Informatica din Romania - CCSIR si coordoneaza DefCamp, cea mai importanta conferinta de securitate informatica & hacking din Europa Centrala si de Est. Andrei ofera in cadrul Bit Sentinel servicii de securitate informatica, penetration testing, security management, recuperarea de pe urma unui atac cibernetic, training-uri si workshop-uri.

  • Articolul anterior Skype lanseaza Group Video Calling
  • Articolul următor Google Voice ofera invitatii studentilor

13 Comentarii

  1. Cornescu Andrey spune:
    mai 16, 2010 la 1:48 pm

    Imi place implementarea clasei Object dar de ce static $instance este de tip array 😕

  2. Avadanei Andrei spune:
    mai 16, 2010 la 1:55 pm

    E o poveste mai lunga. La inceput aveam o intentie de a face un array mai „special” de obiecte statice, dar mi-am dat seama ca pana la urma va fi inutil. 🙂

  3. Creeps spune:
    mai 22, 2010 la 10:52 pm

    E cumva derivat de-aici? http://anantgarg.com/2009/03/13/write-your-own-php-mvc-framework-part-1/ Cam asa arata, doar ca minified.

  4. Avadanei Andrei spune:
    mai 23, 2010 la 12:02 am

    Hmm, imi amintesc acum de tutorialul asta. E unul cu care am inceput studiul MVC in urma cu ceva vreme, din el am pastrat doar ce m-a interesat. Prima parte(adica aceasta) a articolului include ceva asemanator cu respectivul articol, restul partilor vei vedea si tu ca nu mai au nici o legatura cu el. 🙂

  5. Creeps spune:
    mai 23, 2010 la 10:43 am

    Mea culpa, si eu am primele 3 pagini de „PHP MVC Tutorials” de pe Google accesate, si mi-a sarit in ochi stripSlashesDeep-ul, de-aia am vrut sa stiu 😀

  6. Artur spune:
    septembrie 9, 2010 la 5:38 pm

    Salut, imi place articolul tau dar am incercat sa il execut pe calculatorul meu si am intilnit urmatoarele probleme:

    Notice: Undefined offset: 0 in C:\xampp\htdocs\MVC\library\shared.php on line 57

    Deprecated: Assigning the return value of new by reference is deprecated in C:\xampp\htdocs\MVC\library\controller.class.php on line 15

    Deprecated: Assigning the return value of new by reference is deprecated in C:\xampp\htdocs\MVC\library\controller.class.php on line 16

    Fatal error: Class ” not found in C:\xampp\htdocs\MVC\library\controller.class.php on line 15

    poti sa ma ajuti?

  7. Andrei Avadanei spune:
    septembrie 9, 2010 la 5:50 pm

    Asta e prima parte a tutorialului. Incearca sa descarci partea a treia, ea contine toate dependetele frameworkului. 🙂

  8. Artur spune:
    septembrie 10, 2010 la 8:29 am

    Eu nu gasesc linku de unde pot sa descarc partea a 3, poate ma ajuti tu?

  9. Andrei Avadanei spune:
    septembrie 10, 2010 la 10:58 am

    A doua parte si ultima. Enjoy.

  10. Andrei Misarca spune:
    ianuarie 18, 2011 la 12:59 pm

    Poti explica putin fisierele .htaccess, te rog 😀 In rest foarte tare articolul

  11. Condurache Bogdan spune:
    ianuarie 18, 2011 la 3:00 pm

    Vezi aici 🙂

  12. ohana spune:
    iunie 13, 2011 la 4:35 pm

    foarte util, pacat ca de abia acum am aflat de MVC

  13. Robert1995 spune:
    iulie 24, 2011 la 4:38 pm

    Foarte fain . Super articolul doar am citit pana acum . Looks nice


  • Facebook

    WorldIT.info
  • Ultimele Atacuri Cibernetice din Romania – RO Hacked

    [wp_rss_retriever url="https://rohacked.bit-sentinel.com/feed/" excerpt="none" items="5" read_more="false" new_window="true" thumbnail="false" cache="0"] RO Hacked este registrul atacurilor cibernetice din România.
  • Caută

  • Articole Recomandate

    • Recent Posts
    • Tags
    • Număr record de participanți la DefCamp 2015, cel mai important eveniment dedicat securității cibernetice din Europe Centrala si de Estdecembrie 2, 2015
    • La DefCamp 2015 vei afla prin ce tehnici pot fi evitate măsurile de securitate ale sistemelor informatice criticeoctombrie 16, 2015
    • Ultima sansa sa rezervi bilete de tip Early Bird la DefCamp 2015septembrie 1, 2015
    • 15 sfaturi despre cum poti deveni un programator bun venite de la specialisti romaniaugust 4, 2015
    • algoritmica Android antivirus Apple Avadanei Andrei benzi desenate BitDefender blog browser C++ Chrome concurs eveniment Facebook Firefox Google google chrome hacking html5 infografic informatica internet Internet Explorer IT javascript linux Microsoft Mozilla Firefox online PHP programare retea sociala review Romania securitate Tehnologie Twitter web Windows Windows 7 Wordpress WorldIT worldit.info Yahoo! YouTube
  • aprilie 2021
    L Ma Mi J V S D
     1234
    567891011
    12131415161718
    19202122232425
    2627282930  
    « dec.    
  • Link-uri Sponsorizate

    • laptop second hand

    • Calculatoare Second Hand

    • cod voucher pc garage

  • Home
  • Tehnic
  • PHP
  • Introducere in Design Patterns – MVC (partea I)
  • Important

    • Bit Sentinel
    • Centrul de Cercetare în Securitate Informatică din România
    • DefCamp
  • Prieteni

    • BetiT.ro
    • bijuterii handmade
    • Computerica | Resurse gratuite PC
    • Descopera.org
    • Gadgeturi si IT – Giz.ro
  • Prieteni

    • PC – Config
    • RO Hacked
    • Stiri IT

Copyright © 2009-2014 WORLDIT. Toate drepturile Rezervate.
Termeni și condiții | Contact | Licența Creative Commons