01 Practica Anexo Gastos PHP
01 Practica Anexo Gastos PHP
01 Practica Anexo Gastos PHP
El objetivo de esta prctica es crear una aplicacin web MVC con el lenguaje PHP para el manejo de gastos
personales (registro de facturas de gastos vlidas en Ecuador). Se requiere tener instalado el stack de aplicaciones
XAMPP.
El siguiente diseo muestra la arquitectura de la aplicacin:
ARQUITECTURA DEL SISTEMA PHP-MVC-CRUD
VIEW
CONTROLLER
MODEL
BDD
index.html
index.php
controller.php
GastosModel.php
Proveedor.php,
Factura.php
Database.php
MySQL
el
ingreso
3. Mediante el administrador de la base de datos MySQL (phpMyAdmin) crear una nueva base de datos de nombre
anexogastos y dos nuevas tablas proveedor y factura (utilizar el script indicado):
CREATETABLEproveedor(
rucVARCHAR(13)PRIMARYKEYCOMMENT'Registrounicodecontribuyentes',
razon_socialVARCHAR(300)notnulluniqueKEYCOMMENT'Elnombredelproveedor'
)COMMENT'Tabladeproveedores.';
CREATETABLEfactura(
id_facturaintegerNOTNULLPRIMARYKEYAUTO_INCREMENTCOMMENT'Identificadorinternounicodelafactura.',
rucVARCHAR(13)NOTNULLCOMMENT'RUCdelproveedor.',
numero_facturaVARCHAR(17)NOTNULLCOMMENT'NumerodefacturaenformatoNNNNNNNNNNNNNNN.',
fecha_emisionDATENOTNULLCOMMENT'Fechadeemisiondelafactura.',
valor_baseFLOATNOTNULLCOMMENT'Valorendolaresdelabasedelafactura.'
)COMMENT='Tabladeregistrodefacturasdegasto.';
ALTERTABLEfacturaADDCONSTRAINTfact_prov_fkFOREIGNKEY(ruc)
REFERENCESanexogastos.proveedor(ruc)ONDELETERESTRICTONUPDATERESTRICT;
INSERTINTOproveedor(ruc,razon_social)VALUES('1006598457001','SupermercadoLaVecina');
INSERTINTOproveedor(ruc,razon_social)VALUES('1008574854001','FarmaciaElSano');
INSERTINTOproveedor(ruc,razon_social)VALUES('1007845124001','ModasRosita');
INSERTINTOfactura(ruc,numero_factura,fecha_emision,valor_base)VALUES('1006598457001','001001000004566'
,'2015/02/17',103.45);
INSERTINTOfactura(ruc,numero_factura,fecha_emision,valor_base)VALUES('1006598457001','001001000004567'
,'2015/02/18',215.23);
INSERTINTOfactura(ruc,numero_factura,fecha_emision,valor_base)VALUES('1008574854001','006003000012745'
,'2015/01/10',45.03);
5. Para organizar los componentes de la aplicacin, creamos las carpetas model, view y controller y tambin movemos
la pgina index.php que fue creada por el asistente hacia la carpeta view. Tenemos el proyecto as:
6. Creamos una nueva pgina index.html en la raz del proyecto, nos servir nicamente para redireccionar la
navegacin hacia la pgina view/index.php:
index.html:
<!DOCTYPEhtml>
<html>
<head>
<title>anexogastos</title>
<metacharset="UTF8">
<metahttpequiv="refresh"content="0;url=view/index.php"/>
</head>
<body>
</body>
</html>
7.
8. Iniciamos la implementacin de la capa modelo. Creamos una nueva clase PHP llamada Database. Esta clase
mantendr los mtodos necesarios para manejar la conexin a la base de datos. Para optimizar este recurso, utiliza el
patrn de diseo singleton, que asegura que se mantenga una sola conexin en las transacciones. Crear una nueva
clase PHP en el archivo Database.php y que deber almacenarse en la carpeta model:
model/Database.php:
<?php
/**
*Claseutilitariaquemanejalaconexion/desconexionalabasededatos
*mediantelasfuncionesPDO(PHPDataObjects).
*Utilizaelpatrondedisenosingletonparaelmanejodelaconexion.
*@authormrea
*/
classDatabase{
//Propiedadesestaticasconlainformaciondelaconexion(DSN):
privatestatic$dbName='productos';
privatestatic$dbHost='localhost';
privatestatic$dbUsername='root';
privatestatic$dbUserPassword='';
//Propiedadparacontroldelaconexion:
privatestatic$conexion=null;
/**
*Nosepermiteinstanciarestaclase,seutilizansuselementos
*detipoestatico.
*/
publicfunction__construct(){
exit('Nosepermiteinstanciarestaclase.');
}
/**
*Metodoestaticoquecreaunaconexionalabasededatos.
*@returntype
*/
publicstaticfunctionconnect(){
//Unasolaconexionparatodalaaplicacion(singleton):
if(null==self::$conexion){
try{
self::$conexion=newPDO("mysql:host=".self::$dbHost.";"."dbname=".self::
$dbName,self::$dbUsername,self::$dbUserPassword);
}catch(PDOException$e){
die($e>getMessage());
}
}
returnself::$conexion;
}
/**
*Metodoestaticoparadesconexiondelabdd.
*/
publicstaticfunctiondisconnect(){
self::$conexion=null;
}
}
?>
9. Dentro del mismo model creamos las clases Proveedor y Factura (objetos de dominio) que representan a las tablas
proveedor y factura . Estas clases tendrn tantas propiedades como campos tenga las tablas:
model/Proveedor.php:
<?php
/**
*ClaseProveedor
*@authormrea
*/
classProveedor{
private$ruc;
private$razonSocial;
function__construct($ruc,$razonSocial){
$this>ruc=$ruc;
$this>razonSocial=$razonSocial;
}
publicfunctiongetRuc(){
return$this>ruc;
}
publicfunctiongetRazonSocial(){
return$this>razonSocial;
}
publicfunctionsetRuc($ruc){
$this>ruc=$ruc;
}
publicfunctionsetRazonSocial($razonSocial){
$this>razonSocial=$razonSocial;
}
}
model/Factura.php:
<?php
/**
*ClaseFactura
*@authormrea
*/
classFactura{
private$idFactura;
private$ruc;
private$numeroFactura;
private$fechaEmision;
private$valorBase;
function__construct($idFactura,$ruc,$numeroFactura,$fechaEmision,$valorBase){
$this>idFactura=$idFactura;
$this>ruc=$ruc;
$this>numeroFactura=$numeroFactura;
$this>fechaEmision=$fechaEmision;
$this>valorBase=$valorBase;
}
publicfunctiongetIdFactura(){
return$this>idFactura;
}
publicfunctiongetRuc(){
return$this>ruc;
}
publicfunctiongetNumeroFactura(){
return$this>numeroFactura;
}
publicfunctiongetFechaEmision(){
return$this>fechaEmision;
}
publicfunctiongetValorBase(){
return$this>valorBase;
}
publicfunctionsetIdFactura($idFactura){
$this>idFactura=$idFactura;
}
publicfunctionsetRuc($ruc){
$this>ruc=$ruc;
}
publicfunctionsetNumeroFactura($numeroFactura){
$this>numeroFactura=$numeroFactura;
}
publicfunctionsetFechaEmision($fechaEmision){
$this>fechaEmision=$fechaEmision;
}
publicfunctionsetValorBase($valorBase){
$this>valorBase=$valorBase;
}
}
10. La lgica de la aplicacin la implementamos en la clase GastosModel. Esta clase se encarga de las funciones CRUD
del sistema (Create,Read,Update,Delete) con la base de datos. Adicionalmente, se encarga de transformar los registros
de la bdd a objetos (Proveedor y Factura) y viceversa. Esto permite que luego en la capa de la vista, se mantenga un
modelo uniforme de informacin. Inicialmente la clase GastosModel implementa una funcin de consulta de facturas
para posteriormente poder visualizar la informacin en la vista:
model/GastosModel.php:
<?php
include'Database.php';
include'Proveedor.php';
include'Factura.php';
/**
*ObjetodenegocioGastosModel.ImplementafuncionesCRUD
*yvariasfuncionesdenegociodelaaplicacionAnexode
*gastospersonales.
*
*@authormrea
*/
classGastosModel{
/**
*Retornalalistadefacturasdelabdd.
*@returnarray
*/
publicfunctiongetFacturas(){
//obtenemoslainformaciondelabdd:
$pdo=Database::connect();
$sql="select*fromfacturaorderbyid_facturadesc";
$resultado=$pdo>query($sql);
//transformamoslosregistrosenobjetosdetipoFactura:
$listado=array();
foreach($resultadoas$res){
$factura=newFactura($res['id_factura'],$res['ruc'],$res['numero_factura'],$res['fecha_emision'],
$res['valor_base']);
array_push($listado,$factura);
}
Database::disconnect();
//retornamosellistadoresultante:
return$listado;
}
}
11. La siguiente es la capa de controladores. El controlador tiene la funcin de administrar la navegacin entre pginas, al
mismo tiempo que invoca a la capa de lgica (modelo). Mantiene la informacin disponible para la capa de la vista
mediante el uso de sesiones (session). Implementamos el componente controller.php en la carpeta controller:
controller/controller.php:
<?php
///////////////////////////////////////////////////////////////////////
//Componentecontrollerqueverificalaopcionseleccionada
//porelusuario,ejecutaelmodeloyenrutalanavegaciondepaginas.
///////////////////////////////////////////////////////////////////////
require_once'../model/GastosModel.php';
session_start();
$gastosModel=newGastosModel();
//recibimoslaopciondesdelavista:
$opcion=$_REQUEST['opcion'];
switch($opcion){
case"listar":
//obtenemoslalistadefacturas:
$listado=$gastosModel>getFacturas();
//ylosguardamosensesion:
$_SESSION['listado']=serialize($listado);
//redireccionamosalapaginaindexparavisualizar:
header('Location:../view/index.php');
break;
default:
//sinoexistelaopcionrecibidaporelcontrolador,siempre
//redirigimoslanavegacionalapaginaindex:
header('Location:../view/index.php');
}
12. Finalmente en la capa de la vista creamos la pgina view/index.php. Esta pgina se encargar de implementar la
visualizacin de datos, botones y enlaces (links) de opciones y el formulario donde el usuario pueda ingresar
informacin de nuevas facturas. La manera en que estas pginas interactan con el controlador es mediante controles
de tipo hidden que indican la opcin seleccionada por el usuario (en los formularios) o mediante enlaces generados
dinmicamente (<a href>) que permiten que un usuario seleccione una factura determinada para eliminarla por
ejemplo. A continuacin el cdigo de la pgina:
view/index.php:
<!DOCTYPEhtml>
<?php
session_start();
include'../model/Factura.php';
?>
<html>
<head>
<metacharset="UTF8">
<title>Anexodegastospersonales</title>
</head>
<body>
<table>
<tr><td><formaction="../controller/controller.php">
<inputtype="hidden"name="opcion"value="listar">
<inputtype="submit"value="Consultarlistado">
</form></td></tr>
</table>
<tableborder="1">
<tr>
<th>ID_FACT</th>
<th>RUC</th>
<th>NUM_FACTURA</th>
<th>FECHAEMISION</th>
<th>VALORBASE</th>
</tr>
<?php
//verificamossiexisteensesionellistadodefacturas:
if(isset($_SESSION['listado'])){
$listado=unserialize($_SESSION['listado']);
foreach($listadoas$fact){
echo"<tr>";
echo"<td>".$fact>getIdFactura()."</td>";
echo"<td>".$fact>getRuc()."</td>";
echo"<td>".$fact>getNumeroFactura()."</td>";
echo"<td>".$fact>getFechaEmision()."</td>";
echo"<td>".$fact>getValorBase()."</td>";
echo"</tr>";
}
}else{
echo"Nosehancargadodatos.";
}
?>
</table>
</body>
</html>
14. Requerimiento: ajustar la fecha de emisin al centro y el valor base hacia la derecha.
15. Ahora adicionamos la funcionalidad para ingresar nuevas facturas. Primero incrementamos el mtodo necesario en
GastosModel:
model/GastosModel.php:
<?php
include'Database.php';
include'Proveedor.php';
include'Factura.php';
/**
*ObjetodenegocioGastosModel.ImplementafuncionesCRUD
*yvariasfuncionesdenegociodelaaplicacionAnexode
*gastospersonales.
*
*@authormrea
*/
classGastosModel{
/**
*Retornalalistadefacturasdelabdd.
*@returnarray
*/
publicfunctiongetFacturas(){
...
}
/**
*Insertaunanuevafacturaenlabdd.
*@paramtype$rucRUCdelproveedor.
*@paramtype$numeroFacturaNumerodefactura.
*@paramtype$fechaEmisionLafechadeemision.
*@paramtype$valorBaseElvalorbasedelafactura.
*@throwsException
*/
publicfunctioninsertarFactura($ruc,$numeroFactura,$fechaEmision,$valorBase){
$pdo=Database::connect();
$sql="insertintofactura(ruc,numero_factura,fecha_emision,valor_base)values(?,?,?,?)";
$consulta=$pdo>prepare($sql);
//Ejecutamosypasamoslosparametros:
try{
$consulta>execute(array($ruc,$numeroFactura,$fechaEmision,$valorBase));
}catch(PDOException$e){
Database::disconnect();
thrownewException($e>getMessage());
}
Database::disconnect();
}
}
18. Ejecutamos e ingresamos varias facturas nuevas, se debe tener precaucin y utilizar nicamente nmeros de RUC que
existan en la base de datos:
19. Requerimiento: Establecer los cuatro campos como obligatorios mediante HTML5.
20. Creacin de una lista de opciones. En lugar de solicitar al usuario en un cuadro de texto abierto el RUC del proveedor,
podemos crear una lista dinmica de opciones con la informacin de la tabla proveedores. Para ello creamos el
respectivo mtodo en el GastosModel para obtener el listado de proveedores:
model/GastosModel.php:
/**
*Obtieneunalistadetodoslosproveedores.
*@returnarray
*/
publicfunctiongetProveedores(){
//obtenemoslainformaciondelabdd:
$pdo=Database::connect();
$sql="select*fromproveedororderbyrazon_social";
$resultado=$pdo>query($sql);
//transformamoslosregistrosenobjetosdetipoProveedor:
$listado=array();
foreach($resultadoas$res){
$proveedor=newProveedor($res['ruc'],$res['razon_social']);
array_push($listado,$proveedor);
}
Database::disconnect();
//retornamosellistadoresultante:
return$listado;
}
21. En este caso, vamos a prescindir del controller, y directamente desde la vista accedemos a GastosModel para obtener
la lista de proveedores y crear la lista (ntese que ahora los archivos de clases son incluidos con include_once para
evitar problemas de compilacin duplicada):
view/index.php:
<!DOCTYPEhtml>
<?php
session_start();
include_once'../model/Factura.php';
include_once'../model/Proveedor.php';
include_once'../model/GastosModel.php';
?>
<html>
<head>
<metacharset="UTF8">
<title>Anexodegastospersonales</title>
</head>
<body>
<formaction="../controller/controller.php">
<inputtype="hidden"name="opcion"value="insertar">
<table>
<tr>
<td>RUC</td>
<td>
<selectname="ruc">
<?php
$gastosModel=newGastosModel();
$listado=$gastosModel>getProveedores();
foreach($listadoas$prov){
echo"<optionvalue='".$prov>getRuc()."'>".$prov>getRazonSocial()."</option>";
}
?>
</select>
</td>
</tr>
<tr>
<td>NUM.FACTURA</td>
<td>
<inputtype="text"name="numeroFactura"size="17"maxlength="17"required="true">
(NNNNNNNNNNNNNNN)
</td>
</tr>
......
23. Requerimiento: Adicionar la opcin de eliminar una factura especfica (mediante enlaces dinmicos).
24. Requerimiento: Implementar la funcionalidad necesaria para que el sistema no permita ingresar dos veces la misma
factura de un proveedor.