Académique Documents
Professionnel Documents
Culture Documents
EjemploPHP+POO+MVCVictorRobles|VictorRobles
Inicio
Desarrollo web
Sistemas
Sobre mi
Portafolio
Contacto
Desarrollo web
Like
Buscador
Buscar
Seguro que algunos que hayan ledo o visto algunos de los tutoriales o ejemplos que pongo sobre programacin
en PHP con y sin frameworks, pueden no estar de acuerdo conmigo en ciertos detalles, o incluso estar
Quizs te interese
pensando este chico no est programando verdaderamente orientado a objetos o no sigue el paradigma a
rajatabla (todo lo que explico lo hago desde mi punto de vista actual, nunca digo que sea la verdad absoluta o
lo ms correcto siempre).
Pues bien hoy voy a poner un ejemplo muy bueno de como programar realmente orientado a objetos en PHP
puro con MVC. Lo que voy a mostrar hoy perfectamente podra ser la base para construirnos un pequeo
framework propio, veremos incluso como hacer un controlador frontal, como crear objetos que representen
entidades de la base de datos, etc, por lo tanto lo que voy a ensear hoy es un ejemplo muy didctico y muy
completo.
Estructura de directorios
En nuestro framework tendremos varios directorios:
config: aqu irn los ficheros de configuracin de la base de datos, globales,
Nuevo
Popular
Aleatorio
etc.
controller: como sabemos en la arquitectura MVC los controladores se
encargarn de recibir y filtrar datos que le llegan de las vistas, llamar a los
modelos y pasar los datos de estos a las vistas. Pues en este directorio
colocaremos los controladores
core: aqu colocaremos las clases base de las que heredarn por ejemplo
controladores y modelos, y tambin podramos colocar ms libreras hechas
por nosotros o por terceros, esto sera el ncleo del framework.
model: aqu irn los modelos, para ser fieles al paradigma orientado objetos
tenemos que tener una clase por cada tabla o entidad de la base de
datos(excepto para las tablas pivote) y estas clases servirn para crear objetos
de ese tipo de entidad(por ejemplo crear un objeto usuario para crear un
usuario en la BD). Tambin tendremos modelos de consulta a la BD que contendrn consultas ms complejas
que estn relacionadas con una o varias entidades.
view: aqu iran las vistas, es decir, donde se imprimirn los datos y lo que ver el usuario.
index.php ser el controlador frontal por el que pasar absolutamente todo en la aplicacin.
Patrones y
bsquedas en
Linux
feb 17, 2015
Comandos para
filtrar en Linux
feb 10, 2015
Dispositivos de
almacenamiento
en Linux
feb 3, 2015
Cdigo del
ejemplo de
creacin de un
blog con
Symfony2
ene 29, 2015
<?php
returnarray(
"driver"=>"mysql",
"host"=>"localhost",
"user"=>"root",
"pass"=>"",
"database"=>"pruebas",
"charset"=>"utf8"
);
?>
Tambin podemos crearnos un fichero gobal.php en el que irn constantes que luego nos servirn por ejemplo
para establecer controladores y acciones por defecto (y todo lo que queramos meterle).
1
2
3
4
5
<?php
define("CONTROLADOR_DEFECTO","Usuarios");
define("ACCION_DEFECTO","index");
//Msconstantesdeconfiguracin
?>
http://victorroblesweb.es/2014/07/15/ejemplophppoomvc/
1/9
19/2/2015
EjemploPHP+POO+MVCVictorRobles|VictorRobles
<?php
classConectar{
private$driver;
private$host,$user,$pass,$database,$charset;
publicfunction__construct(){
$db_cfg=require_once'config/database.php';
$this>driver=$db_cfg["driver"];
$this>host=$db_cfg["host"];
$this>user=$db_cfg["user"];
$this>pass=$db_cfg["pass"];
$this>database=$db_cfg["database"];
$this>charset=$db_cfg["charset"];
}
publicfunctionconexion(){
if($this>driver=="mysql"||$this>driver==null){
$con=newmysqli($this>host,$this>user,$this>pass,$this>database);
$con>query("SETNAMES'".$this>charset."'");
}
return$con;
}
publicfunctionstartFluent(){
require_once"FluentPDO/FluentPDO.php";
if($this>driver=="mysql"||$this>driver==null){
$pdo=newPDO($this>driver.":dbname=".$this>database,$this>user,
$this>pass);
$fpdo=newFluentPDO($pdo);
}
return$fpdo;
}
}
?>
Seguimos creando el fichero EntidadBase.php de esta clase heredarn los modelos que representen entidades,
en el constructor le pasaremos el nombre de la tabla y tendremos tantos mtodos como queramos para
ayudarnos con las peticiones a la BD a travs de los objetos que iremos creando. Lo bueno que tiene es que
Categoras
estos mtodos pueden ser reutilizados en otras clases ya que le indicamos la tabla en el constructor.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
classEntidadBase{
private$table;
private$db;
private$conectar;
publicfunction__construct($table){
$this>table=(string)$table;
require_once'Conectar.php';
$this>conectar=newConectar();
$this>db=$this>conectar>conexion();
}
publicfunctiongetConetar(){
return$this>conectar;
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
publicfunctiondb(){
return$this>db;
}
publicfunctiongetAll(){
$query=$this>db>query("SELECT*FROM$this>tableORDERBYidDESC");
//Devolvemoselresultsetenformadearraydeobjetos
while($row=$query>fetch_object()){
$resultSet[]=$row;
}
return$resultSet;
}
publicfunctiongetById($id){
$query=$this>db>query("SELECT*FROM$this>tableWHEREid=$id");
if($row=$query>fetch_object()){
$resultSet=$row;
}
return$resultSet;
}
publicfunctiongetBy($column,$value){
$query=$this>db>query("SELECT*FROM$this>tableWHERE$column='$value'");
while($row=$query>fetch_object()){
$resultSet[]=$row;
}
return$resultSet;
http://victorroblesweb.es/2014/07/15/ejemplophppoomvc/
Esto mola
2/9
19/2/2015
EjemploPHP+POO+MVCVictorRobles|VictorRobles
51
52
53
54
55
56
57
58
59
60
61
return$resultSet;
}
publicfunctiondeleteById($id){
$query=$this>db>query("DELETEFROM$this>tableWHEREid=$id");
return$query;
}
publicfunctiondeleteBy($column,$value){
$query=$this>db>query("DELETEFROM$this>tableWHERE$column='$value'");
return$query;
62
63
64
65
66
67
68
69
70
71
/*
*Aqupodemosmontarnosunmontndemtodosquenosayuden
*ahaceroperacionesconlabasededatosdelaentidad
*/
}
?>
Ahora crearemos la clase ModeloBase que heredar de la clase EntidadBase y a su vez ser heredada por los
modelos de consultas. La clase ModeloBase permitir utilizar el constructor de consultas que hemos incluido y
tambin los mtodos de EntidadBase, as como otros mtodos que programemos dentro de la clase, por
ejemplo yo tengo un mtodo para ejecutar consultas sql que directamente me devuelve el resultset en un array
de objetos preparado para pasrselo a una vista, podramos tener cientos para diferentes cosas.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?php
classModeloBaseextendsEntidadBase{
private$table;
private$fluent;
publicfunction__construct($table){
$this>table=(string)$table;
parent::__construct($table);
$this>fluent=$this>getConetar()>startFluent();
}
publicfunctionfluent(){
return$this>fluent;
}
publicfunctionejecutarSql($query){
$query=$this>db()>query($query);
if($query==true){
if($query>num_rows>1){
while($row=$query>fetch_object()){
$resultSet[]=$row;
}
}elseif($query>num_rows==1){
if($row=$query>fetch_object()){
$resultSet=$row;
}
}else{
$resultSet=true;
}
}else{
$resultSet=false;
}
return$resultSet;
}
38
39
40
41
//Aquipodemosmontarnosmtodosparalosmodelosdeconsulta
}
?>
La siguiente clase que crearemos es ControladoresBase de la cual heredarn los controladores, esta clase carga
EntidadesBase, ModelosBase, y todos los modelos creados dentro del directorio model.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php
classControladorBase{
publicfunction__construct(){
require_once'EntidadBase.php';
require_once'ModeloBase.php';
//Incluirtodoslosmodelos
foreach(glob("model/*.php")as$file){
require_once$file;
}
}
//Pluginsyfuncionalidades
/*
*Estemtodoloquehaceesrecibirlosdatosdelcontroladorenformadearray
*losrecorreycreaunavariabledinmicaconelindiceasociativoyledael
*valorquecontienedichaposicindelarray,luegocargaloshelpersparalas
*vistasycargalavistaquelellegacomoparmetro.Enresumenunmtodopara
*renderizarvistas.
*/
publicfunctionview($vista,$datos){
foreach($datosas$id_assoc=>$valor){
${$id_assoc}=$valor;
}
require_once'core/AyudaVistas.php';
$helper=newAyudaVistas();
require_once'view/'.$vista.'View.php';
}
http://victorroblesweb.es/2014/07/15/ejemplophppoomvc/
3/9
19/2/2015
EjemploPHP+POO+MVCVictorRobles|VictorRobles
32
33
34
35
36
37
38
39
40
41
publicfunctionredirect($controlador=CONTROLADOR_DEFECTO,$accion=ACCION_DEFECTO){
header("Location:index.php?controller=".$controlador."&action=".$accion);
}
//Mtodosparaloscontroladores
}
?>
Ahora crearemos la clase AyudaVistas que puede contener diversos helpers (pequeos mtodos que nos
ayuden en pequeas tareas dentro de las vistas).
1
2
3
4
5
6
7
8
9
10
11
<?php
classAyudaVistas{
publicfunctionurl($controlador=CONTROLADOR_DEFECTO,$accion=ACCION_DEFECTO){
$urlString="index.php?controller=".$controlador."&action=".$accion;
return$urlString;
}
//Helpersparalasvistas
}
?>
Ahora crearemos el fichero ControladorFrontal.func.php que tiene las funciones que se encargan de cargar un
controlador u otro y una accin u otra en funcin de lo que se le diga por la url.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
//FUNCIONESPARAELCONTROLADORFRONTAL
functioncargarControlador($controller){
$controlador=ucwords($controller).'Controller';
$strFileController='controller/'.$controlador.'.php';
if(!is_file($strFileController)){
$strFileController='controller/'.ucwords(CONTROLADOR_DEFECTO).'Controller.php';
}
require_once$strFileController;
$controllerObj=new$controlador();
return$controllerObj;
}
functioncargarAccion($controllerObj,$action){
$accion=$action;
$controllerObj>$accion();
}
functionlanzarAccion($controllerObj){
if(isset($_GET["action"])&&method_exists($controllerObj,$_GET["action"])){
cargarAccion($controllerObj,$_GET["action"]);
}else{
cargarAccion($controllerObj,ACCION_DEFECTO);
}
}
?>
//Baseparaloscontroladores
require_once'core/ControladorBase.php';
//Funcionesparaelcontroladorfrontal
require_once'core/ControladorFrontal.func.php';
//Cargamoscontroladoresyacciones
if(isset($_GET["controller"])){
$controllerObj=cargarControlador($_GET["controller"]);
lanzarAccion($controllerObj);
}else{
$controllerObj=cargarControlador(CONTROLADOR_DEFECTO);
lanzarAccion($controllerObj);
}
?>
Modelos y objetos
Si queremos seguir el paradigma de la programacin orientada a objetos tericamente deberamos tener una
clase por cada tabla de la base de datos(excepto tablas pivote) que haga referencia a un objeto de la vida real,
en este caso el objeto que crearamos seria Usuario y el usuario tendra un nombre, un apellido, un email, etc,
pues bien eso serian los atributos del objeto y tendramos un mtodo get y set por cada atributo que servirn
para establecer el valor de las propiedades y para conseguir el valor de cada atributo. Esta clase hereda de
EntidadesBase y tiene un mtodo save para guardar el usuario en la base de datos, podramos tener otro
mtodo update que seria similar, etc.
Y te preguntars por que no lo haces as siempre? la respuesta es simple, en algunos proyectos en los que hay
muchas tablas puede ser engorroso estar creando una clase por cada tabla solamente para tener un insert y un
update(aunque tiene sus ventajas) aunque segn este paradigma no sea del todo correcto omito esto y
http://victorroblesweb.es/2014/07/15/ejemplophppoomvc/
4/9
19/2/2015
EjemploPHP+POO+MVCVictorRobles|VictorRobles
update(aunque tiene sus ventajas) aunque segn este paradigma no sea del todo correcto omito esto y
directamente creo modelos de consultas en los que tengo mtodos que interaccionan con una tabla
mayoritariamente o varias segn las relaciones que tengan, por otra parte algunos frameworks cuentan con
ORMs que nos ayudan con todo esto pero de igual forma cuando tienes muchas tablas relacionadas quiz el
uso del ORM sin controlarlo muy bien puede dificultar la tarea, en cualquier caso lo ms correcto es tener una
clase por entidad aunque a veces no sea lo ms practico o cmodo.
Truco: si usas NetBeans puedes generar los getters y setters desde el men Source -> Insert Code
1
2
3
4
5
6
7
8
9
10
<?php
classUsuarioextendsEntidadBase{
private$id;
private$nombre;
private$apellido;
private$email;
private$password;
publicfunction__construct(){
$table="usuarios";
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
parent::__construct($table);
}
publicfunctiongetId(){
return$this>id;
}
publicfunctionsetId($id){
$this>id=$id;
}
publicfunctiongetNombre(){
return$this>nombre;
}
publicfunctionsetNombre($nombre){
$this>nombre=$nombre;
}
publicfunctiongetApellido(){
return$this>apellido;
}
publicfunctionsetApellido($apellido){
$this>apellido=$apellido;
}
publicfunctiongetEmail(){
return$this>email;
}
publicfunctionsetEmail($email){
$this>email=$email;
}
publicfunctiongetPassword(){
return$this>password;
}
publicfunctionsetPassword($password){
$this>password=$password;
}
publicfunctionsave(){
$query="INSERTINTOusuarios(id,nombre,apellido,email,password)
VALUES(NULL,
'".$this>nombre."',
'".$this>apellido."',
'".$this>email."',
'".$this>password."');";
$save=$this>db()>query($query);
//$this>db()>error;
return$save;
}
}
?>
Aqu pondramos las consultas completas, en lugar de utilizar los mtodos que tenemos en el modelo de
entidad, aunque tambin estaran accesibles desde este modelo.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
classUsuariosModelextendsModeloBase{
private$table;
publicfunction__construct(){
$this>table="usuarios";
parent::__construct($this>table);
}
//Metodosdeconsulta
publicfunctiongetUnUsuario(){
$query="SELECT*FROMusuariosWHEREemail='victor@victor.com'";
$usuario=$this>ejecutarSql($query);
return$usuario;
}
}
?>
Los controladores
Los crearemos en el directorio controller, en este caso tengo creado UsuariosController.
http://victorroblesweb.es/2014/07/15/ejemplophppoomvc/
5/9
19/2/2015
EjemploPHP+POO+MVCVictorRobles|VictorRobles
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?php
classUsuariosControllerextendsControladorBase{
publicfunction__construct(){
parent::__construct();
}
publicfunctionindex(){
//Creamoselobjetousuario
$usuario=newUsuario();
//Conseguimostodoslosusuarios
$allusers=$usuario>getAll();
//Cargamoslavistaindexylepasamosvalores
$this>view("index",array(
"allusers"=>$allusers,
"Hola"=>"SoyVctorRobles"
));
}
publicfunctioncrear(){
if(isset($_POST["nombre"])){
//Creamosunusuario
$usuario=newUsuario();
$usuario>setNombre($_POST["nombre"]);
$usuario>setApellido($_POST["apellido"]);
$usuario>setEmail($_POST["email"]);
$usuario>setPassword(sha1($_POST["password"]));
$save=$usuario>save();
}
$this>redirect("Usuarios","index");
}
publicfunctionborrar(){
if(isset($_GET["id"])){
$id=(int)$_GET["id"];
$usuario=newUsuario();
$usuario>deleteById($id);
}
$this>redirect();
}
publicfunctionhola(){
$usuarios=newUsuariosModel();
$usu=$usuarios>getUnUsuario();
var_dump($usu);
}
}
?>
Las vistas
En este caso tengo la vista indexView.php creada.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<!DOCTYPEHTML>
<htmllang="es">
<head>
<metacharset="utf8"/>
<title>EjemploPHPMySQLiPOOMVC</title>
<linkhref="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"
rel="stylesheet"type="text/css"/>
<scripttype="text/javascript"
src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<scripttype="text/javascript"
src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<style>
input{
margintop:5px;
marginbottom:5px;
}
.right{
float:right;
}
</style>
</head>
<body>
<formaction="<?phpecho$helper>url("usuarios","crear");?>"method="post"
class="collg5">
<h3>Aadirusuario</h3>
<hr/>
Nombre:<inputtype="text"name="nombre"class="formcontrol"/>
Apellido:<inputtype="text"name="apellido"class="formcontrol"/>
Email:<inputtype="text"name="email"class="formcontrol"/>
Contrasea:<inputtype="password"name="password"class="formcontrol"/>
<inputtype="submit"value="enviar"class="btnbtnsuccess"/>
</form>
<divclass="collg7">
<h3>Usuarios</h3>
<hr/>
</div>
<sectionclass="collg7usuario"style="height:400px;overflowy:scroll;">
<?phpforeach($allusersas$user){//recorremoselarraydeobjetosy
obtenemoselvalordelaspropiedades?>
<?phpecho$user>id;?>
<?phpecho$user>nombre;?>
<?phpecho$user>apellido;?>
<?phpecho$user>email;?>
<divclass="right">
<ahref="<?phpecho$helper>url("usuarios","borrar");?>&id=<?php
http://victorroblesweb.es/2014/07/15/ejemplophppoomvc/
6/9
19/2/2015
EjemploPHP+POO+MVCVictorRobles|VictorRobles
41 <ahref="<?phpecho$helper>url("usuarios","borrar");?>&id=<?php
echo$user>id;?>"class="btnbtndanger">Borrar</a>
42 </div>
43 <hr/>
44 <?php}?>
45 </section>
46 <footerclass="collg12">
47 <hr/>
48 EjemploPHPMySQLiPOOMVCVctorRobles<a
href="http://victorroblesweb.es">victorroblesweb.es</a>Copyright©<?phpecho
date("Y");?>
49 </footer>
50 </body>
51 </html>
Este ejemplo est hecho en unas tres horas, podra trabajarse mucho ms y construirnos un marco de trabajo
muy bonito para nosotros y hecho por nosotros con lo cual tendramos un control y conocimiento absoluto de
lo que pasa por debajo. El siguiente paso seria limpiar la URL mediante un .htaccess, y seguir dndole
funcionalidades, aadiendo nuestras propias libreras para toda clase de tareas o de terceros como por ejemplo
PHPThumb, HTML2PDF, SwiftMailer, Twig si queremos un motor de plantillas poderoso o incluso Active Record
ORM para darle ms potencia.
Por que cuento todo esto? En primer lugar para disipar las dudas del que pueda creer que no entiendo la
programacin orientada a objetos, en segundo lugar para demostrar que un ex alumno de un ciclo formativo de
administracin de sistemas sabe programar igual que cualquier otro de ciclos especficos de programacin, en
tercer lugar para ensear como se hace un programa en PHP utilizando POO y MVC con un controlador frontal,
y para demostrar que aunque programemos en PHP puro no tenemos porque hacer las cosas mal y no cuesta
trabajo hacerlas bien, he visto varios proyectos hechos actualmente que son un verdadero caos y un
despropsito, con esto podemos empezar a hacer buenos programas aunque no usemos un framework de
terceros.
Cdigo fuente de este ejemplo
Artculos relacionados
La extensin
CRUD con
Crear modelo de
Controladores y
Rutas y pasar
Subir ficheros en
MySQLi en PHP
Codeigniter
formulario en Yii
vistas en Yii
Codeigniter
en Zend
Framework 2
Me gusta
http://victorroblesweb.es/2014/07/15/ejemplophppoomvc/
7/9
19/2/2015
EjemploPHP+POO+MVCVictorRobles|VictorRobles
Me gusta
Autor: Victor
Desarrollador web...
6 Comentarios
Bea
4 SEPTIEMBRE, 2014
Responder
David
12 SEPTIEMBRE, 2014
Responder
Vctor Robles
18 DICIEMBRE, 2014
Responder
Sergio Castillo
6 OCTUBRE, 2014
Gracias!! execelente turorial, muchas gracias por el tiempo tomado en publicarlo y ensearnos el
modo correcto de trabajar.
Responder
Armin Vera
29 OCTUBRE, 2014
Estimado Victor, estoy totalmente de acuerdo con cada uno de los motivos por los cuales
desarrollaste este ejemplo. Quiero compartir un punto que me pareci importante que lo
nombraras, y es que el lenguaje no hace al programador, ni el programador al lenguaje, si no que el
programador puede programar bien o mal dependiendo de su buena o mala decisin. Digo esto
porque me ha tocado compartir, sobre todo con programadores de Python, que sacan en cara de
PHP que se presta para muchos caos y despropsitos como dices t en tu publicacin. Pero as
tambin Basic, C, Pascal, Python, C# y etc etc etc, pueden prestarse para caos y despropsitos en la
medida que el programador no pueda ordenar una lgica.
Si bien es cierto, hoy el mercado busca que los desarrollos sean orientados a objetos, esto no quiere
decir que toda solucin deba obedecer al paradigma orientado a objetos. Por lo tanto, estoy en total
http://victorroblesweb.es/2014/07/15/ejemplophppoomvc/
8/9
19/2/2015
EjemploPHP+POO+MVCVictorRobles|VictorRobles
decir que toda solucin deba obedecer al paradigma orientado a objetos. Por lo tanto, estoy en total
desacuerdo con aquellos que reclaman en contra de PHP por ser ocupado muchas veces en forma
estructurada dentro de pginas html/php. Es decisin del programador el seguir un patrn MVC o
n y no es cosa del lenguaje pedirle al programador, por tema de buenas prcticas o lo que se
quiera, seguir tal o cual modelo de desarrollo.
Por ltimo, si PHP fuera un lenguaje malo, no creo que proyectos como MySQL quisieran adoptarlo
como futuro lenguaje para sus scripts (esto segn una noticia que alcanc a leer su ttulo pero no su
contenido) ni tampoco creo que Facebook se haya desarrollado en PHP durante tanto tiempo (an
se desarrolla en PHP?).
Espero haber sido defensor durante algunos instantes de un excelente lenguaje de programacin
que se ha robado la pelcula durante tantos aos.
Responder
Maracile
6 FEBRERO, 2015
Hola Victor,
agradecerte el esfuerzo e inters en compartir un articulo tan bueno, muy buena ayuda de verdad.
Un saludo
Responder
Poner un comentario
Tu direccin de correo electrnico no ser publicada. Los campos necesarios estn marcados *
Nombre *
Correo electrnico *
Web
Comentario
http://victorroblesweb.es/2014/07/15/ejemplophppoomvc/
9/9