Vous êtes sur la page 1sur 124

CarreraLinux2008ProgramacionPHP1

Clase1IntroduccinaPHP
EscritoporDemianP.Alonso(demian@linuxadistancia.com)

Programaanalticodelamateria
1. IntroduccinaPHPylosscripts.Variables.TiposDeDatos.Entrada/SalidaBsica.
2. Controldeflujo:if,for,while,foreach
3. Archivos.DescriptoresdeArchivos.Entrada/SalidaenArchivos.Tuberas.
4. ExpresionesRegulares
5. FuncionesyMdulos
6. Manejodearchivosydirectorios.
7. Bibliotecadefunciones:manejodecadenas;manejodearreglos;manejodefechas
8. ServiciosdeInternet:SMTP,POPyFTP
9. Referencias
10.Introduccinalmanejodeobjetos.Conceptosbsicosherencia,polimorfismo,redefinicin
11.Excepciones:teorayaplicacin
12.Introduccinalaprogramacionweb.IntroduccinaHTML:HTML,HEAD,BODY.Formato
bsicodeltexto.Creacindelinksytablas.
13.CreacindeFormulariosenHTML.UtilizacindeFramesylistasenHTML
14.Creacindepginaswebdinmicas.Utilizacindevalorespasadosporformulariosyporlinks
15.ManejodeCookiesysesiones.
16.Introduccinalasbasededatosrelacionales.ElservidorMySQL.LenguajedeDefinicinde
Datos
17.LenguajedeManipulacindeDatos
18.LenguajedeAdministracindeSeguridad.UtilidadesRelacionadas.
19.ndiceseIntegridadReferencial.
20.Conectividadabasededatos:PHPyMySQL

ConceptosTericosGeneralessobreProgramacin
Programa:Esunconjuntodeaccionesquerealizanunatareaespecifica.Paraellounprogramatoma
datosylosconvierteeninformacin(porejemplo,listadodeclientes,modificarunarchivo,enviarun
datoaotracomputadora,etc).
Esquematicamente:
Datos *----------* Informacin
------->| Programa |------------->
*----------*

CarreraLinux2008ProgramacionPHP2
Lenguajedeprogramacin:Esunconjuntodereglassintcticasquenosotorganunaformade
escribirnuestrosprogramas.
Cdigofuente:Esunprogramaescritoenunlenguajedeprogramacindado.
Compilador:Esunprogramaquetraduceunprogramaescritoenunlenguajedeprogramacinaun
archivoejecutable.EstosignificaqueconvierteeltextoescritoenunlenguajedeprogramacinX,en
cdigodemquinaparaserejecutadocuandoseanecesario.Aesteprocesoselodenominacomo
compilacin.Sisellegaseamodificarelcdigofuentesernecesariopasardenuevoporelprocesode
compilacinparaqueseveanreflejadosdichoscambios.Ejemplosdelenguajesquesoncompilados
son:C,C++,Pascal,Clipper,etc.
Intrprete:Esunprogramaqueseencargadeejecutaruncdigofuenteenunlenguajedado.Un
interpreteleereltextoyloiraejecutandoamedidaquelovaleyendo,sinnecesidaddegenerarun
ejecutable.Enconsecuencia,cuandosealteraelcdigofuentedelprogramaseverautomaticamente
reflejadolaproximavezqueseejecute.Ejemplosdelenguajesquesoninterpretadosson:Perl,Python,
LISP,PHP,Bash,etc.
Variable:Esunespacioenlamemoriadelacomputadoraendondesepuedealmacenardatos.Toda
variabletieneunnombreparapoderusarladesdeelprograma.

IntroduccinalusodePHP
ParacrearunprogramaenPHPdeberemosprimerocrearunarchivoconsueditorpreferido(emacs,vi,
mcedit,kedit,etc).
Estearchivocontendrelcdelprograma.Sinembargo,laprimerlneadelmismotendrlasiguiente
forma(DEBESERLAPRIMERADETODAS):
#!/usr/bin/php

EstalnealeindicaalshellendondeseencuentraelintrpretedePHPparaejecutarnuestroprograma.
SiensusistemaPHPnoseencuentrainstaladoenesedirectorio,debercambiardicharutaporla
ubicacincorrecta.
ParasabersiPHPestainstaladopuedeejecutardesdeelshellelsiguientecomando:
$ which php

SiPHPestainstalado,entoncessemostrarlarutaalmismo(lacualeslacorrectaparautilizar).
Unavezescritoelprograma,sedeberrealizarunpasoprevioantesdepoderejecutarlo.Primeroes
necesarioasignarlepermisosdeejecucin.Paraelloutilizaremoselcomandochmod:
$ chmod 755 nombre_archivo.php

CarreraLinux2008ProgramacionPHP3
Dondenombre_archivo.phpeselnombredelarchivoqueacabasendecrearconsuprograma.
Luegoserposibleejecutarelprogramasimplementeingresandodesdeelshell:
$ ./nombre_archivo.php

Sielprogramaestabienescritoseejecutar,encasocontrarioPHPnosinformardeloserroresque
existiesen.
NOTA:Durantetodaslasclasesseadoptarcomoreglaquetodosloscomandosquesedebanejecutar
desdeelshellestarnantepuestosporunsmbolodepesos($)sisedebeejecutardichocomandocomo
unusuarionormalounnumeral(#)sisedebeejecutarcomoroot.DichosmboloNOsedebeescribir
yaquesimplementerepresentaalpromptdelshell(quedebernconcordarconloqueveenpantalla)

EllenguajedeprogramacinPHP
PHP(PHP:HypertextPreprocessor)esunlenguajequenacienelmundodelaspginasweb.Surgi
comounamaneraprcticadepodermezclarunlenguajedeprogramacinconHTML(ellenguajepara
escribirpginasweb).
UnprogramaenPHP,dentrodeunapginaweb,sepuedepensarcomounconjuntodeseccionesde
cdigoPHPintroducidasdentrodeunarchivoHTML.Enelcasodeunprogramaqueinteractue
completamentesobreelshell,podremosimaginarlocomounsologranbloquedecdigoPHP
embebidoennadadeHTML.
Entonces,definiremosunbloquedePHPdelasiguienteforma:
<?php
# Codigo en PHP
?>

Endonde<?phpabreelbloquedecdigoy?>cierradichobloque.

VariablesenPHP
EnPHPtodaslasvariablescomienzanconunsignodepesos($).Elinterpretecuandoencuentraun$
leerlossiguientescarcterescomoelnombredelavariable.LosnombresdelasvariablesenPHP
puedencontenercualquiercaracteralfanumrico(letrasynmeros)yelguinbajo(_).Detodosellos
quedarestringidoempezarelnombredelavariableconunnmero.
Sisehacereferenciaaunavariablequenoexiste,estapasaraaexistir(enelcasodeunaasignacin)o
simplementeserareemplazadaenlaexpresinporunvalorvaco(quegeneralmentenoafectaenla
operacinencuestin).
Ejemplosdedefinicindevariables:
$numero = 3;
$decimal = 8.3;

CarreraLinux2008ProgramacionPHP4
$cadena = "Hola Mundo!";

Ejemplodeoperacionesconvariables
$suma = $numero + $decimal;
$texto = "$cadena\nHello World";
echo "La suma es $suma";

Existenotrostiposdevariablesqueseutilizandeformadistinta.Entreellospodemosencontrarlos
arreglos.Unarreglo(tambinconocidocomoarregloasociativo,diccionarioohash)essimplementeun
conjuntodeelementos.Estoselementospuedensertantovariablescomunescomootroarreglo.Asu
vez,cadaelementoestaasociadoaunaclave(quepuedesertantonumricacomoalfabtica).En
consecuencia,estosarreglospuedenserutilizadoscomovectoresendondelasclavesseutilizarancomo
ndicesnumricos.Paradefinirunarreglousaremoslafuncinarraydealgunadelassiguientes
formas:
$vector = array(1, 3, 4, "Hola Mun", 3.4);
$arreglo = array("Jose" => 2, "Pepe" => 35, 23 => 42);

Laprimerformacreaunarregloenformade"vector"endondeelelemento1tieneelndice0,el
elemento3tieneelndice1,elelemento4tieneelndice2,elelemento"Hola"tieneelndice3yel
elemento3.4tieneelndice5.
Lasegundaformacreaunarreglodeformatalquelaclave"Jose"tieneasociadoelvalor2,laclave
"Pepe"el35ylaclave23el42.
Paraaccederluegoaunodelosvaloresdelvector,solohacefaltaconocerlaclavequesequiere
accederyescribirlaentrecorchetesluegodelnombredelavariable.Porejemplo:
echo "$vector[3] $arreglo[Jose]";

mostrarporpantalla"HolaMun2".Tambinsepuedemodificar(oagregarsinoexiste)unaclave,
asignndoleunvaloraella.Porejemplo:
$arreglo["Yo"] = 24;

agregarunaclavealarreglomientrasque
$arreglo["Pepe"] = 22;

modificarelcontenidodelayaexistenteclave"Pepe".

CarreraLinux2008ProgramacionPHP5

Operadores
Operadordeasignacin
Eloperadordeasignacineseligual(=).Sumisinesladedarleunvaloraunavariable.Porejemplo:
$mi_nombre = "Pepe";
$mi_lista = array(1, 2, 3);
$un_numero = (3 + 5) * 4;

Esimportantedestacarqueprimeroseevaluatodoloqueseencuentrealaderechadeligualyluegose
losescribeenlavariableespecificada.Notendrasentidotratardeasignarloalrevez.

Operadoresmatemticos
Estosoperadoressirvenpararealizaroperacionesmatemticasbsicas.Porejemploparasumardos
nmerosseusaelms(+):3 + 4
Losoperadoresbsicosson:
Operacin

Operador

suma

resta

multiplicacin *
divisin

mdulo

Operadoresdecadenas
Existeunoperadorparamanejarcadenas.Eseldeconcatenacin(.).Estesirveparajuntardos
cadenas(quepuedenestarenunavariable)enunasola.
Porejemplo,sisetieneunavariable$nombreconelvalor"Pepe",entonces"Hola " .
$nombreeslomismoque"Hola Pepe".

Operadoresdecomparacin
Estosoperadoressirvenparadeterminarsidosexpresionesrespondenonoauncriterio(verdaderoo
falso).Porejemplo,parasabersiunacadena(onmero)esigualaotraseutilizaeloperador==yeste
dirsiambassonigualesono.Todosestosoperadoressonbinarios,porlotanto,seescribendela
siguienteforma:expresion1 operador expresion2ytodoestodevolververdaderoofalso.
Sisetieneunavariable$sueldoconelvalor500entonces$sueldo > 1000serfalso,mientras
que$sueldo <= 500serverdadero.Estosoperadoresson:

CarreraLinux2008ProgramacionPHP6
Operacin

Operador

Igualdad

==

Mayorque

>

Menorque

<

Mayorigualque >=
Menorigualque <=
Distinto

!=

Operadoreslgicos
Estosoperadoressonsimilaresalosdecomparacinyaquedeterminanlaveracidadofalsedaddeuna
omscondiciones.Losoperadoresmencionadosanteriormentegenerabancondiciones(que$sueldo
> 500porejemplo)lascualespuedenserconcatendasparahacercondicionesmascomplejas.Para
elloexisten3operadores.
Elprimeroeseloperadorand(y)elcualtomadoscondiciones.Paraqueseaverdaderaestanueva
condicin,lasdoscondicionestomadasdebenserverdaderas.Elsiguientecuadroresumetodaslas
posibilidadesdevaloresquepuedentenerdoscondiciones:
condicin1 and condicin2
V
V
F
V
V
F
F
F

Valor
V
F
F
F

Elsegundooperandoeselor(o),elcualessimilaralandsoloquealcanzaconqueunasolasea
verdaderaparaquetodalacondicinseaverdadera.Deformaanloga:
condicin1 or
V
F
V
F

condicin2
V
V
F
F

Valor
V
V
V
F

Elltimooperandoeselnot(no)queeslanegacin.Simplementecambiaelvalordeverdadque
tengaunacondicin.
condicin = Valor
V
F
F
V

CarreraLinux2008ProgramacionPHP7

Entradaysalidabsica
Salida

Paramostrarcosasporlapantallaseutilizalafuncinecho.Estarecibeunalistacontodaslascosas
quedebemostrar.Porejemplo:
print "Hola ", $nombre, " la suma es ", 2 + 2, "\n";

Nota:Cuandoenunacadenaseponeunabarrainvertida(\),PHPinterpretaelprximocaracteren
formaespecial.Enelejemploanterior,elprximocaracteresla"n"yseinterpretael\ncomosifuera
unanuevalnea,porloquelosproximosechoimprimirnenlalneasiguienteenvezdeimprimiral
lado.
Losmscomunesson:
Caracter

Descripcin

\n

Nuevalnea

\t

Tabulacin

\\

Labarrainvertidaliteralmente(semuestraUNASOLAbarra)

Entrada
Paraleerdatosdeltecladoseutilizalaentradaestndar.Paraellodebemosleerdesdeelarchivodel
teclado,elcualsellamaSTDIN.Paraleerunalneadesdeeltecladollamaremosalafuncin
fgets(STDIN);lacualnosdevolverlaprximalneadisponibleobloquearelprogramahasta
queseencuentreunadisponible.
ParaquitarelENTERhayqueutilizareloperadorchopsobreloledo.Porejemplo:
$mi_entrada = fgets(STDIN);
$mi_entrada = chop($mi_entrada);

Entonces,sielusuarioingreso"Hola Mundo\n"(el\nseagregasiempreporqueeselcaracterque
ingresaelusuarioparaterminar)luegodelasdossentenciasescritas,quedarenlavariable
$mi_entradaelvalor"Hola Mundo"

Ejercicios
1.
2.
3.
4.
5.

Queesunavariable?
QuetiposdedatoshayenPHP?
Paraquesirvencadatipodeoperador?
Cualesladiferenciaentrelafuncionfgetsylafuncionecho?
Queventajastienelaprogramaciondescriptsaprogramarsobreunlenguajequesecompile?

CarreraLinux2008ProgramacionPHP8

Clase2Controldelflujodeejecucin
Estructurasdecontroldeflujo
Hastaestepuntosolosepodanejecutarunasentenciadebajodelaotrahastaquesecompletarel
programa.Sinembargo,existenalgunasestructurasquepermitenalterarestecomportamientoyobtener
resultadosmsinteresantes.

Estructuradebifurcacin
Laprimeradelasestructuras,elif,eslaquemepermitetomarunadecisinsobresiejecutaronoun
bloquedecdigodependiendodeunacondicin:
if(condicin) {
sentencia1;
sentencia2;
sentencia3;
...
sentenciaN;
}

Sisecumplecondicinentoncesseejecutarntodaslassentenciasqueseencuentrenentrelasllaves
(quesonobligatorias).Encasodequenosecumpla,entoncesseseguiranejecutandolassentenciasque
seencuentrenpordebajodelaltimallavedelif.
UnacondicinpuedesolamenteserVerdadera,secumple,oFalsa,nosecumple(Veroperadoresde
comparacin).
Sinembargo,tambinsepuedeobligaraejecutarunbloquedecdigosinosecumplelacondicin:
if(condicin) {
sentencia1;
sentencia2;
...
sentenciaN;
} else {
sentenciaN+1;
sentenciaN+2;
...
sentenciaM;
}

Enestecaso,sisecumplelacondicinseejecutanlassentenciasquevandesdeel1hastaN,ysino
secumple,lasquevandesdeN+1hastaM.Paraelloseutilizlapalabraelse(sino)quenospermite
ejecutaralgosilacondicinesfalsa.Siempreseejecutarunbloqueuotroperonuncaambos.

CarreraLinux2008ProgramacionPHP9
Cuandoseanidanunif,osea,ponermuchosifunodentrodeotro,elcdigosehacebastanteilegible.
Paraelloexisteotrapalabrareservada(oconjuncin),elseif,quepermitejuntarunelseconunify
asdejarelcdigomsordenado:
if(condicin) {
sentencia1;
sentencia2;
...
sentenciaN;
} elseif(condicion2) {
sentenciaN+1;
sentenciaN+2;
...
sentenciaM;
} else {
sentenciaM+1;
sentenciaM+2;
...
sentenciaJ;
}

Enestecaso,soloseejecutarunodelostresbloquesdecdigo(1aN,N+1aMoM+1aJ).

Ejemplos
Ejemplo1:Leerunatemperaturadesdeelusuarioydecir"HaceCalor"silatemperaturaesmayorque
30o"HaceFrio"enotrocaso.
echo "Ingrese la temperatura actual: ";
$temperatura = fgets(STDIN);
if($temperatura > 30) {
echo "Hace calor\n";
} else {
echo "Hace frio\n";
}

Ejemplo2:Leerunatemperaturadesdeelusuarioydecir"HaceCalor"silatemperaturaesmayorque
30,siestaentre20y30mostrar"Estaperfecto"o"HaceFrio"enotrocaso.
echo "Ingrese la temperatura actual: ";
$temperatura = fgets(STDIN);
if($temperatura > 30) {
echo "Hace calor\n";
} elseif ($temperatura > 20) {
echo "Esta perfecto\n";
} else {

CarreraLinux2008ProgramacionPHP10
}

echo "Hace frio\n";

Estructurawhile
Estaestructurasirveparaiterarsobreunaporcindecdigomientrassecumplaunacondicindada:
while(condicin) {
sentencia1;
sentencia2;
...
sentenciaN;
}

Lassentencias1alaNseejecutarnmientrascondicintengaunvalorverdadero.Lacondicinse
controlacadavezqueseterminedeejecutarlasentenciaNyalldeterminarsidebeiterardenuevoo
no.Porlotantounciclowhilepuedeejecutarsedesde0(lacondicinnuncafueverdadera)hasta
infinito.

Ejemplos
Ejemplo1:Mostrarlatablademultiplicardel7.
$x = 1;
while ($x <= 10) {
echo "$x por 7 = ", $x * 7, "\n";
$x = $x + 1;
}

Ejemplo2:Leervariaslneasportecladohastaqueseingreseunalneaquecontengasolamenteun
punto(.).Cadalnealedasedeberepetirenpantalla,peroenumerandolasdesde1enadelante.
$ingreso = fgets(STDIN);
$ingreso = chop($ingreso);
$x = 1;
while($ingreso != '.') {
echo "$x. $ingreso\n";
$x = $x + 1;
$ingreso = fgets(STDIN);
$ingreso = chop($ingreso);
}

Estructuraforeach
Estaestructuraseutilizapararecorrerunarreglo.
Existendosestilosdeforeach.Enelprimero,seirntomandodeaunoloselementosdelarreglo

CarreraLinux2008ProgramacionPHP11
indicado,yseirncolocandoenlavariableindicadaluegodelas.
Lasintaxissera:
foreach($arreglo as $valor) {
sentencia1;
sentencia2;
...
sentenciaN;
}

Aquseejecutarnlassentencias1alaNtantasvecescomoelementoshayaenelarreglo.Paracada
iteracinexistirunavariablellamada$valorquetendrunvalordelalista.
Lasegundaformanospermitenosoloobtenerelvalor,sinotambinlaclaveasociadacondichovalor.
Paraelloutilizaremoslasintaxis:
foreach($arreglo as $clave => $valor) {
sentencia1;
sentencia2;
...
sentenciaN;
}

Deestaformaparacadaciclosedispondrdeunavariable$clavequetienelaclavedelelementoque
seesteprocesando.Adems,en$valorestarelcontenidodelelementoactual.Porlotanto,alsaber
laclave,esposiblemodificarelarreglooriginal.

Ejemplos
Ejemplo1:Mostrartodosloselementosdeunalista.
$lista = array("Hola", 3, 5, "Mundo");
foreach($lista as $valor) {
echo "$valor\n";
}

Ejemplo2:Desdeunalistaconnmeroscalcularlasumadetodosellos.
$lista = array(2000, 700, 900, 1500);
$total = 0;
foreach($lista as $valor) {
$total = $total + $valor;
}
echo "La suma es $total\n";

CarreraLinux2008ProgramacionPHP12

Ejercicios
1. Cualesladiferenciaentreunifyunwhile?
2. Queesmsprcticopararecorrerunalista?unwhileounforeach?
3. Hacerunprogramaquedadaunalistaconnumeros,losmuestreydigasicadanmeroesPARo
IMPAR.
NOTA:unnmeroesPARsialdividirlopor2elmoduloda0($numero % 2 == 0)
4. Hacerunprogramaquedadaunalistaconnumeros,calcularlasumatoriayelpromediode
todosellos.
5. Hacerunprogramaquemuestrelastablasdemultiplicardel1al10(usandosolamentedos
cicloswhile)

Clase3Archivosdedatos
Introduccin
Unarchivoessimplementeunconjuntodebytes(ocaracteres).Losarchivossedividenendos
categoras:detextoybinarios.Sibienestadivisinesarbitrariayaquenohaydiferenciarealentre
ellos,diremosquelosarchivosdetextosonaquellosquepodemosleery"entender"concualquier
editordetexto(emacs,vi,mcedit,etc)ylosarchivosbinariossonaquellosquepresentancaracteres
"raros"cuandoselostratadeleer.
Veremosaquelusodelosarchivosdetexto.
Porlogeneral,cuandoseleeunarchivosevenvariaslneasdetexto.Porejemplo
Querido Mundo:
Hola Mundo, como has estado?

Esrazonablepensarqueexistealgunaformadeexpresarque"Hola Mundo"noseescribaalladode
"Querido Mundo:".Apesardequenosepuedever,hayuncaracterentreestasdoscadenas.Este
caractereseldenuevalnea(el'\n').PordefectoesteeselcaracterqueleindicaaPHPhastadonde
leercuandoserequiereunalectura.

UsodeArchivos
Apertura
Cuandosequiereutilizarunarchivo(leeroescribir)primeroesnecesariodecirlealSistemaOperativo
quenoslo"preste"parahacerloquedeseemos.
Paraelloexisteunafuncinllamadafopen,quetienelasiguienteforma:
$archivo = fopen("nombre_del_archivo", "modo");

Donde$archivoeselnombredelavariableconlacualseharreferencia,dentrodelscriptenPHP,
alarchivoquehayasidoabiertoexitosamente."nombre_del_archivo"esunacadenaquetienela

CarreraLinux2008ProgramacionPHP13
rutayelnombredelarchivo.
NOTA:Unavezabiertoelarchivosedebeusarlavariable$archivoparahacerreferenciaalarchivo
dentrodelscript.nombre_del_archivoessolounacadenaynosepuedenileerniescribirdesde
ohaciaella.
Comosemencionantes,elarchivopuedeserabiertoparaleer,escribirotambienparaagregar.Estose
especificadentrodelacadena"modo".Estacadenapodrser"r"paraabrirloparalectura,"w"para
escrituray"a"paraagregar.Porejemplo,paraescribirenelarchivopepe.datosdeldirectorio
actual,lacadenanombre_del_archivoes"./pepe.datos"yelmodo"w".Cuandoseabreun
archivoparaescribirsinoexisteelarchivo,entoncesesteescreado,ysiexistetodoslosdatosson
eliminados.Luegodeabiertosecomienzaaescribirdesdeeliniciodelarchivo.
Silaintencinnoesladeborrarlosdatos,entoncessedebeabrirparaagregar.Cuandoestoocurresiel
archivonoexistesecrea,ysiexisteentoncessecomienzaaescribirdesdeelfindedatosdelarchivosin
borrarsucontenido.
Algunosejemplosdeopenson:
$datos = fopen("./datos.txt", "r"); # Abre el archivo datos.txt para leer
$estadisticas = fopen("./stats.dat", "w"); # Abre el archivo stats.dat para
escribir
# y le asigna el descriptor ESTADISTICAS
$log = fopen("mensajes.log", "a"); # Abre para agregar el archivo mensajes.log

Puedeocurrirquenosepuedaabrirelarchivopordiversosmotivos.Porejemplo,siseabreelarchivo
paralecturayelarchivonoexisteonosetienenlospermisosadecuadosesunerror.Paraellola
funcinopendevuelveverdaderosisepudoabriryfalsoencasocontrario.
Paracontrolarestopodramoshacer:
$archivo = fopen("mi_archivo.txt", "r");
if(! $archivo) {
echo "ERROR al intentar abrir el archivo";
}

Estocontrolaraenelifsinosepudoabrirelarchivo.Encuyocasomostraraunmensajeinformando
elmotivo.

Clausura
Cuandosehaterminadodeusarelarchivoesnecesariocerrarloparaasegurarsequetodohayaquedado
guardado.Paraelloexistelafuncinclosealacualsolodebeespecificarseleeldescriptordel
archivo.Porejemplo:
close($archivo);

CarreraLinux2008ProgramacionPHP14
Lectura
Paraleerdeunarchivosepuedehacerdelamismaformaenqueseleadesdeelteclado(enrealidadel
tecladoesunarchivo).Estosehaceutilizandolamismafuncinfgets.Porejemplo,
$linea = fgets($archivo);

leerunalnea(hastaeincluyendoel'\n')hastaeldelimitador(quepordefectoesel'\n'queseparalas
lneas).Concadalecturaseavanzaralaprximalneaycuandonohayamslneascadalectura
devolverfalso.
Paradetectarquesehayllegadoalfinaldelarchivoexistelafuncinfeof.Estafuncindevolver
verdaderounavezquesehayaleidoelfindearchivo(unalecturadespuesdelfinaldelarchivo)yfalso
enotrocaso.Parahacerunprogramaquemuestreelcontenidodelarchivo"mi_archivo.txt"una
solucinsera:
$arch = fopen("1.html", "r");
while(!feof($arch)) {
$linea = fgets($arch);
echo $linea;
}
fclose($arch);

Sabiendoquelafuncinfgetsdevolverfalsounavezquetratemosdeleermsalladelfinal,otra
solucinsera:
$arch = fopen("mi_archivo.txt", "r");
while($linea = fgets($arch)) {
print $linea;
}
fclose($arch);

Escritura
Paraescribirenunarchivoseutilizalafuncinfputs.Paraellosedebeespecificarcomoprimer
parmetroelarchivoautilizaryluegoloquesequieramostrar.Porejemploparaguardarlosnmeros
del1al10enunarchivo(numeros.txt):
$arch_numeros = fopen("./numeros.txt", "w");
foreach (range(1, 10) as $numero) {
fputs($arch_numeros, "$numero\n");
}
fclose($arch_numeros);

NOTA:Lafuncinrangenosdevuelveunaarreglocuyosvaloressonlosnmerosquecomprendenel
intervaloespecificadoconsusdosparmetros.

CarreraLinux2008ProgramacionPHP15

Tuberas
Unatuberaesnimsnimenosqueunarchivo.Ladiferenciaestaqueenvezdeleerdesdeunarchivo
dedatosseleerdesdelasalidadeuncomando,oenvezdedescribirenunarchivodedatos,se
escribiralaentradadeuncomando.
Paracrearunatuberautilizamoslafuncinpopen,queesanlogaaopenperoenvezdeabrirun
archivo,ejecutarelprogramaespecificado.Comodiferenciatendremossolodosmodos"r"y"w"ya
quelastuberassonunidireccionales,solopodemosleeroescribirdeellas,peronoambascosassobre
lamismatubera.
Paracerrarunatuberaposeemoslafuncinpclosequeesigualacloseperocierraunatuberaen
vezdeunarchivo.
Veamosunejemplo:
$tub = popen("ps -o user ax | grep mi_usuario", "r");
$cant = 0;
while($l = fgets($tub)) {
$cant ++;
}
echo "Cantidad de procesos para mi_usuario: $cant\n";

Argumentosdesdelalneadecomandos
Esmuycomnqueunscriptnecesiteelusuarioleespecifiquesobrequearchivostrabajaroque
modifiquealgunaconductaespecfica.Paraelloseutilizanlosparmetrosqueselepasanalos
programasdesdelalneadecomandos.Porejemploelprogramalsmuestratodoslosarchivosdeun
directorio.Perosisequiereverlainformacindetalladadeestosseleagregaunargumento("-l")
paraquelohaga.
EnPHPtodosestosargumentossonaccedidosatravsdelarregloargv.Estearregloescreado
automaticamenteporPHPyesautomticamentellenadoconlosargumentos.Paraverificarestose
muestraelprogramaargs.php:
echo "Los argumentos son:\n";
foreach($argv as $indice => $argumento) {
echo "Argumento $indice: $argumento";
# notar que $argumento es lo mismo que $argv[$indice]
}

Siseejecutaahora:
$ args.php Hola Mundo "Hello World" 4 5 6

Mostrarporpantalla:

CarreraLinux2008ProgramacionPHP16
Los argumentos son:
Argumento 0: args.php
Argumento 1: Hola
Argumento 2: Mundo
Argumento 3: Hello World
Argumento 4: 4
Argumento 5: 5
Argumento 6: 6

Ejercicios
1. Quetienedesimilarelteclado(STDIN),unarchivoyunatuberia?
2. HacerunprogramaquegenereNnumerosaleatoriosylosguardeenunarchivounoporlinea.
TantoNcomoelnombredelarchivosedeberanpasardesdelalineadecomandos.Paralos
numerosaleatoriosmirarlaayudaparalafuncionrand(buscarlafuncionenelsitiodephp:
www.php.net).
3. Hacerunprogramaqueleaunarchivoingresadocomounargumentodesdelalineade
comandos(generadoporelprogramaanterior)yquemuestresoloaquellosnumerosquesean
PAR.
4. Hacerunprogramaqueleatodaslaslineasdeunarchivoylasimprimanuevamentepero
anteponiendolescuantasvecesserepitierondentrodelmismo.
5. Hacerunprogramaquerecibatresnombresdearchivosdesdelosargumentos.Elprograma
debegenerareltercerarchivosenbasealosdosprimeros,intercalandolaslineasdeambos.

Clase4ExpresionesRegulares
Introduccinalasexpresionesregulares
UnaexpresinregularesunaformaquenosproveePHP(entreotroslenguajes)deverificar,validary
extraerdatos.Estaherramientasebasaenquelaentradatieneunpatrn.Estosignificaquesibienno
sonigualestodaslasentradas,todastienenlamismaforma.Porejemplo,unarchivodelog
(/var/log/messages),unarchivodeconfiguracin(como/etc/inittab),ounarchivodedatos(como/etc/
passwd)entreotros.

Patrones
Lospatronesseespecificarcomounacadenadecaracterescomn.Estospatronescontarancon
caracteresliterales(debenestarliteralmenteenlacadenaquesebusca)yotroscaracteresespeciales
queledanflexibilidadygeneralidad(porejemplo,decirquedebehaberunoomsdgitos).
Paraaplicarestepatrnsobreunacadenaseutilizalafuncinereg,endondeelprimerparmetroser
elpatrnylasegundalacadenaconlacualsequierecomparar.Ademas,eregdevolververdaderosila
cadenacorrespondealpatrndadoofalsoencasocontrarior.

CarreraLinux2008ProgramacionPHP17
Ejemplo:
$cadena = "El conejo esta sobre la mesa";
if(ereg("conejo", $cadena)) {
print "La palabra conejo esta en la cadena\n";
} else {
print "La palabra conejo NO esta en la cadena\n";
}

Enesteejemplo,aparecerporpantallalaprimeraopcin.Cuandoseespecificaunpatrnqueconsta
solodeliterales(ninguncaracterespecial),sefijarsiesepatrnestaenalgunapartedelacadenasin
importardondeeste.
Elpatrntambienpuedeserespecificadoocontener,variablescomunesdetipocadenas.Paraponerel
patrnanteriorenunavariableelprogramaquedara:
$cadena = "El conejo esta sobre la mesa";
$patron = "conejo";
if(ereg($patron, $cadena)) {
print "La palabra conejo esta en la cadena\n";
} else {
print "La palabra conejo NO esta en la cadena\n";
}

Caracteresespeciales
Loscaracteresespecialesson:. * ? + [ ] ( ) { } ^ $ \
Sisequierequealgunodeestoscaracteresdebaaparecerenlacadenaqueseestavalidando,entonces
selesdebeanteponerunabarrainvertida(\)paraqueselosinterpretecomotal.

Lmites
Laprimerrestriccinquepondremossobreunaexpresinregularserloslmitesprincipioyfin.Para
elloexisteelcaracter^(principio)yelcaracter$(fin).El^,siaparece,aparecercomoprimer
caracterdelaexpresin,yaqueelprincipiodelacadenasolopuedeocurriralprincipio.Deforma
anlogaserel$.Parasabersiunaoracinterminaenpuntosepodrapregunar:
if(ereg("\.$", $cadena)) {
print "Bien terminada\n";
} else {
print "Mal terminada\n";
}

Estaexpresinconstadedoscaracteres:el\.querepresentaunpuntoliteral(estecaracterdebeestar
en$cadenaydebeserelltimodetodos)yelcaracter$queindicaelfindelacadena(dentrodecad
nopuedehabermscaracteresdespuesdel.).

CarreraLinux2008ProgramacionPHP18
Conjuntos
Hastaahorasoloseusaroncaracteresliterales,perotambinpuedengeneralizarse.Estosignificaquese
puededecirqueenciertopuntopuedeocurrir,porejemplo,unaletramayuscula.Paraelloseutilizan
loscorchetes([ ]).Dentrodeloscorchetessepondrantodosloscaracteresquesepermiten.Sise
buscansolodgitosseusar[0123456789].Sisequiereverificarqueunvaloringresadoseun
nmerode3dgitossepodrahacer:
$entrada = chop(fgets(STDIN));
if(ereg("^[0123456789][0123456789][0123456789]$", $entrada)) {
print "Tiene 3 digitos\n";
}

Comosepuedeapreciarestoeslargo,confuso,ypocoestetico.Paraellosepermitelaposibilidadde
definirunrango.Estosignifica,queenvezdeenumerartodaslasposibilidadessepuededecirdesdeun
caracter(0porejemplo)hastaciertootro(9porejemplo).Elrangoseespecificaponiendoentreestos
dosvalores,unguin(-).
Considerandoesto,elejemploanteriorquedara:
$entrada = chop(fgets(STDIN));
if(ereg("^[0-9][0-9][0-9]$", $entrada)) {
print "Tiene 3 digitos\n";
}

Sibienestoesmuchomsclaro,aunnoeslomsptimo.Paraellosedefinieronalgunosrangosquese
usanmuycomunmente.Estosrangosposeenunnombre,yseespecificaelmismoentrelossmbolos
[:y:].Porejemplo,elrango[0-9]estarepresentadopor[:digit:](equivalentea0-9).
Considerandoesto,sepuedemodificarloanteriora:
$entrada = chop(fgets(STDIN));
if(ereg("^[[:digit:]][[:digit:]][[:digit:]]$", $entrada)) {
print "Tiene 3 digitos\n";
}

Ascomoseespecificoenunconjuntocualessonloscaracteresqueseadmiten,tambienpuedeser
expresadodesuformacontraria.Estoes,decirsolamentecualescaracteresnosepermiten,dejanque
calificanenesterangoatodoslosdemascaracteres.Paraello,luegodelprimercorchete,sedebeponer
elacentocircunflejo(^),queeseloperadorqueme"niega"losdemascaracteres.Porejemplosinose
quiereaceptarningunnmerosepondra:
if(ereg("[^0-9]", $entrada) {
print "La cadena no tiene ningun numero\n";
}

Sibienestoesposible,esrecomendablequesiemprequeseutiliceunconjuntoqueseespecifiquenlos
caracteresquesipuedenir,envezdeespecificarlopornegacin.Estonosdalaseguridadquesila

CarreraLinux2008ProgramacionPHP19
entradaesvlida,entonceslasolucinestaentreloqueunoplaneo.Siencambiosenegoloscaracteres
quenosequerian,siseolvidodeponeralgunoosiaparecieronotroscaracteresqueenelmomentode
escribirelprogramanoexistieran,podriancausarefectosrarosennuestroprograma.
Entrelosconjuntosyadefinidosseencuentran:
[:alnum:]
[:alpha:]
[:digit:]
[:blank:]

[0-9A-Za-z]
[A-Za-z]
[0-9]
[ \t\n\r]

Repeticiones
Cuandoseutilizaexpresionesregulares,porlogeneral,ciertoscaracteresserepitenvariasveces.Por
ejemplo,siseestaleyendounarchivoquetienenombresdeusuarios,seguidosporunespacioy
seguidoporsudirectorioactual,ocurrirquelosnombrestienenmsqueunsolocaracter(muchos
[:alnum:]).Enesteejemplo,tampocosesabehastacuantoscaracterespuedatenerelnombreoel
directorio,porloquenosepodraexpresartodaslasposibilidades.Aquesdondeentranlas
repeticiones.

Ceroounarepeticin
Sisequiereponeralgocomoopcional,querradecirqueciertocaracterpuedeonoestar.Paraelloexiste
elcaracterespecial?.Esteoperadorpermitequeelcaracteranterioresteono.Porejemplo,siseesta
leyendolneascomolasdescriptasanteriormente,entradasposiblesseran:
root /root
usuario /home/usuario/

Comosepuedeapreciar,losdirectoriosnotienenlamismaforma,yaqueunoterminacon/yelotro
no.Entoncesestabarra(/)esopcional.Ennuestraexpresinregularaparecerun/?.El?permitir
queesecaracteresteonoeste.Graciasaestoambasentradassonvlidas.

unaomsrepeticiones
Siconsideramoselejemploanterior,paravalidarelnombredelusuariohariafaltapoderexpresarque
debehaberporlomenosuncaracter,yqueluegopuedensucederlovariasmas.Paraelloexisteel
operadorms(+).Esteoperadorpermitequeelcaracteroexpresinqueloprecedeserepita1oms
veces.Dentrodelaexpresinregular,paravalidaralnombre,apareceralprincipio^[[:alnum:]]+
dondeel^representaeliniciodelacadena,[[:alnum:]]escualquiercaracteralfanumricoyel+
hacequesepuedarepetirel[[:alnum:]]unaomsveces.

CarreraLinux2008ProgramacionPHP20
ceroomsrepeticiones
Siexistelaposibilidaddequetodouncampopuedaestarvaco,entoncesenvezdenecesitarquealgo
serepitaunaomsveces,senecesitarqueserepitaningunaomsveces.El"ninguna"eselqueleda
lacategoriadeopcional.Porejemplo,elarchivodeusuarios(/etc/passwd)tienealgunoscamposque
sonopcionales(comoelcampoGECOScontieneinformacinsuperflua,comoelnombrerealdel
usuario).Eloperadorquemepermitehacerestoeselasterisco(*).Deestaforma,enlaexpresin
regularaparecerun[[:alnum:]]*donde[[:alnum:]]esuncaracterque,porelasterisco,se
podrrepetirceroomsveces.

Rangoderepeticiones
Lasrepeticionesanterioreseranindefenidas,estoes,notenanunlimiteestablecido.Puedeocurrirque
senecesitequeuncaracteresteunnmeroespecficodevecesoqueestedentrodeunrango.Sise
quierevalidarunnmerode3dgitos,harafaltaqueelset[[:digit:]]serepitatresveces
([[:digit:]][[:digit:]][[:digit:]]).Tambinpuedeespecificarseunasolavezque
caractersequierequeserepitaydecircuantasvecessedeberepetir.Paraindicarlasrepeticionesestas
sedebenespecificarentrellaves({}).Paraelcasoanteriorsera[[:digit:]]{3}.Quepasarasi
elnmerode3dgitospuedetenervaloresquesoloseandedosdgitos(yaqueel099seralomismo
queponer99).Paraellosepuededecirquehayaentre1y3dgitos.Deestaformaestarian
contempladastodaslasposibilidades.Paraespecificarunrangotambinseusanlasllavesyentreellas
sepondraellimiteinferiorseguidodeunacomayseguidodellimitesuperior.Ennuestroejemplosera
[[:digit:]]{1,3}.
Larepeticinpuedeimitarseponiendotantasvecescomosenecesiteelcaracter,peroelrangode
repeticionesnopuedeserimitadodeestaforma,porloquelohacenecesarioconocerlo.
Tambinesposiblenoespecificarunodeloslimites.PHPinterpretarquellendoparaellimitequeno
seespecifico,puedetomarcualquiervalor.Entonces,siseescribe[[:digit:]]{,3}(nose
especificoellimiteinferior),podrhaberentre0y3dgitos.Y[[:digit:]]{2,}(noseespecifico
ellimitesuperior)significaquepuedehaber2omsdgitos.

Recuperarpartesdelacadena
Cuandoseaplicaunaexpresinregularaunacadenasefijasiestacadenaconcuerdaconelpatrn
especificado.Sihayunpatrn,entoncesdebehaberinformacintilmezcladaconalgunaformade
expresartodaestainformacinparaqueseentendibleporalgooalguien.Lasexpresionesregularesen
PHPnospermitenrecuperarestainformacintildesdelacadena.Paralograrestecomportamientolas
partesdelaexpresinregularquesequieranobtenercomovariablessedebenespecificarentre
parntesis.
DesdePHPseranecesarioagregarunparmetromsalallamadaaereg.Esteserelnombredeun
arregloquepodemosusar.Luegodelallamada,quedarapartirdelaposicin1elprimerjuegode
parntesis,enlaposicin2elsegundoyasisucesivamente.
Veamosunejemploprctico:Elarchivo/var/log/messagesesunarchivodelogqueregistratodaslas

CarreraLinux2008ProgramacionPHP21
accionesrealizadasporlosprogramas.Unaentradadeestearchivoenmimquinaes:
Dec 26 14:45:23 darkstar login[1077]: ROOT LOGIN on `tty2'

Elformatodeunaentradaes(enesteorden):
El comienzo de la cadena
3 letras que identifican el mes
1 o mas espacios
El dia en que se registro la operacion (pueden ser 1 o dos digitos)
La hora en que se registro la operacion separando las horas,
minutos y segundos con un :
El nombre del host
Una cantidad de caracteres hasta el un (puede haber espacios) : que
representan el programa (o proceso) que genero ese registro
1 :
Una cantidad indefinida de caracteres que muestran un mensaje que
informa el problema o exito detectado (incluido el \n).
Fin de la cadena.

Elobjetivodeesteprogramasermostrarporpantallasoloaquellasentradasquepertenezcanaunmes
ydaespecifico.Lasalidadeberindicarlahorayelmensajedecadaentrada.
Elprograma:
echo
$mes
echo
$dia

"Ingrese el mes a buscar: ";


= chop(fgets(STDIN));
"Ingrese el dia a buscar: ";
= chop(fgets(STDIN));

echo "Los mensajes de $dia de $mes:\n";


$log = fopen("/var/log/messages", "r");
if(!$log) {
echo "No se puede abrir el archivo: $!\n";
exit(1);
}
$patron = "^$mes".
"[[:blank:]]+".
"$dia".
"[[:blank:]]+".
"([[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2})".
"[[:blank:]]+".
"[[:alnum:]]+".
"[[:blank:]]+".
"[][[:alnum:].]+".
":".
"(.+)$";
while($linea = chop(fgets($log))) {
if(ereg($patron", $linea, $reg) {

CarreraLinux2008ProgramacionPHP22
cho "$reg[1]: $reg[2]\n";

}
}
fclose($log);

Lonicocomplejodeesteprogramaeselpatrnutilizadoenelif.Veamoslaporpartes.
Alprincipioestael^queindicaqueloquesiguedebeestaralprincipiodelacadena.Enestecasose
utilizalavariablesmesqueposeeelmes,queelusuarioingresoporteclado,quesequierebuscar(el
messeescribeeningleslasprimeras3letras).
Seguidodelmesseespecificaquepuedehaber1omsespacios([[:blank:]]+).Luegoapareceel
daquesequierebuscar,queseencuentraenlavariableda(queingresoelusuario).
Hastaaquihacequelaexpresinconcuerdeconlafechaqueelusuarioquierebuscar.Estaeslaunica
partequecambiaentredistintasejecucionesdelprograma.
Luegoaparecenuevamentelosespacios([[:blank:]]+).Segnelformatodelarchivodelog,lo
siguienteeslahoraconelformatodosdgitosdospuntosdosdgitosdospuntosdosdgitos
([[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2}).Comoestoespartedeloquenos
interesamostrarloescribimosdentrodeparntesis.Deestaformasilacadenaconcuerdaconla
expresinregular,quedarguardadoenlavariable$reg[1](porserelprimergrupodeparntesis)la
hora.
Despuesdelahorahayespacios([[:blank:]]+),elnombredelhost([[:alnum:]]+)yms
espacios([[:blank:]]+).
Luegovieneelnombredelprograma.Aqupuedenaparecercaracterescomoloscorchetes([]),el
punto,elespacioocualquiercaracteralfanumrico.Parasehaceunconjuntoquecontengaatodos
ellos(loscorchetesporserlosquedelimitanlosconjuntossedebenescribiralcomienzo),esteconjunto
seescribecomo[][[:alnum:].].Ycomotodoesosepuederepetir1omsvecesseleponeluego
unms(+).
Luegovieneeldospuntos(:)literal,yluegopuedehabercualquiercosahastaelfindelacadena.
Existeuncaracterespecialqueconcuerdaconcualquiercaracter.Estecaractereselpunto(.).
Especialmentetilenestaocasin,elpuntoseguidodelmsconcuerdaconcualquiercosaquehaya
luegodelpunto.Comotodoestorepresentaalmensajequeseestabuscandoyespartedeloquenos
interesaobtenerel.+seencierraentreparntesis.Deestaformaquedarenlavariable$reg[2]la
cadenaconelmensajedelog.
Finalmenteseencuentraelfindecadenaqueesdondeterminalaexpresinregular.
Dentrodelifsoloseimprimelafecha(queestabaen$reg[1])yluegoelmensaje(queestabaen
$reg[2]).
Unejemplodelasalidareducidaes(siseingresocomomesMayycomoda6):
00:01:43:
00:01:43:
00:01:43:
00:01:43:
00:01:43:
1, 5
00:01:43:

lp0: using parport0 (polling).


PPP Deflate Compression module registered
Soundblaster audio driver Copyright (C) by Hannu Savolainen
sb: CMI8330/C3D Audio Adapter detected
sb: ISAPnP reports 'CMI8330/C3D Audio Adapter' at i/o 0x220, irq 5, dma
SB 4.13 detected OK (220)

CarreraLinux2008ProgramacionPHP23
00:01:43:
00:01:43:
00:01:43:
00:01:43:

sb: 1 Soundblaster PnP card(s) found.


ne2k-pci.c:v1.02 10/19/2000 D. Becker/P. Gortmaker
http://www.scyld.com/network/ne2k-pci.html
PCI: Found IRQ 9 for device 00:10.0

Partiendoyjuntandocadenas
Siseposeeunacadena,comounaentradadelarchivo/etc/passwd,quetienecamposseparadospor
delimitadores(eneseejemploel:),sepuedesepararestacadenaporcamposparapoderutilizar
aquellosquenosseandeinteres.Paraelloexisteunafuncinquedespedazaunacadenaenunalista,
dondecadaelementodelalistaesuncampo.Estafuncinsellamaexplodeyllevadosparmetros.
Elprimeroesunacadenaqueespecficaeldelimitadorquesequiereusaryelsegundoparmetroesla
cadenaquesequiereromper.explodedevolverluegounalistacontodosloscampos.
Paraelejemplodel/etc/passwd:
$entrada = "root:x:0:0::/root:/bin/bash";
$campos = explode(":", $entrada);

Dejaren$camposelarreglo("root", "x", 0, 0, ,"/root,/bin/bash").Luegose


podrutilizarfacilmentecualquiercampo.
Parahacerelprocesoinversoexistelafuncinimplode.Estacomoprimerparmetroeldelimitador
conelquesequierajuntarloscamposdeunalista,ycomosegundoparmetrolalistaconloscamposa
juntar.implodedevolverunacadenacontodosloscamposunidosporeldelimitador.
Paracambiareldelimitadorenunaentradadelarchivodeconfiguracin(considerandoelcdigoquese
ejecutoantes):
$nueva_salida = implode("#", $campos);

Estodejaren$nueva_salidalacadena"root#x#0#0##/root#/bin/bash".

Ejercicios
1. Queesunpatronyparaquepuedeserusado?
2. Hacerunprogramaquepermitaingresarnumeros(positivosynegativos)portecladoylos
valide.Paraellosedeberausarunaexpresionregular.Seconsideraraunnumerosoloaquellas
entradasqueposeandigitosunicamente(sinespacios).Aquellasentradasquenoseannumericas
deberanserimpresasenlasalidadeerrorestandar(STDERR).
3. Seposeeunarchivoconpalabras(unaporlinea)querepresentatodaslaspalabrasquehayenun
diccionariodeespaol(dict.txt).Sepidehaceunprogramaquelepidaalusuariouna
terminacionyquebusqueendichodiccionariotodasaquellaspalabrasquetenganesa
terminacion.Tantolaterminacioncomoelarchivodepalabrassedeberapoderpasarcomoun
argumentodesdelalineadecomandos
4. Elcomandowho -umuestraalosusuariosqueestanconectados,enqueterminal,enque

CarreraLinux2008ProgramacionPHP24
fechayhora,ycuantotiempoestuvieroninactivos.Considerandoquelaultimacolumna
muestracuantotiempoestuvieroninactivos(losqueestanactivostieneun.),sepidehacerun
programaquemuestrecualeselusuarioquemastiemposinhacernada.
5. Elarchivo/proc/meminfoposeeinformacionsobrelamemoria.Deestearchivosepideextraer
elvalorasociadoaMemFreeyaMemTotal(MemorialibreyMemoriatotal
respectivamente).Luegoelprogramadeberainformarqueporcentajedememoriaestalibreen
esemomento.

5Funcionesymdulos
Funciones
Unafuncinesunaagrupaciondesentencias,decisiones,yciclosquerealizanunatareacomn.Estos
nostraevariosbeneficios:
1. Reutilizacin:Unafuncinpuedeserusadavariasvecessinnecesidaddereescribirlacadavez
quehayaqueusarla.
2. Abstraccin:Cuandounafuncinestahecha,yanoimportacomoesquelohacesinoqueeslo
quehace.Deestaformanospermiteconcentrarnosenelproblemamsgrande,dejandodelado
losdetallesdelaimplementacin.
3. Menoserrores:Alsepararelprogramaenpartesmspequeasesmsfcilubicarycorregir
loserrores.Adems,unafuncinbienhechayanoposeeerrores,ycuandosereutilizehabra
menoserroresenelcampogeneral.
Unafuncinpuededependerdealgunosparmetrosdeentrada.Siporejemplotenemosunafuncin
quecalculaelfactorialdeunnmero,sernecesariopasarlealafuncinsobrequenmerosequiere
trabajar.Lacantidaddeargumentospuedeirdesdecerohastalosquesequiera.
Tambienunafuncinpuededevolverunvalor.Enelejemploanterior,sernecesarioquelafuncin
devuelvaelfactorialcalculado.
EnPHPparadefinirunafuncinutilizaremoslapalabrareservafunctionseguidadelnombredela
funcin,suargumentosyelbloquedecdigocorrespondiente.
Engeneralsera:
function nombre_de_la_funcion($arg1, $arg2, $arg3) {
# Bloque de codigo
}

Losargumentossedefinencomovariablesnormales,ypuedentomarcualquiervalor,desdeunacadena
hastaunarray.
Paradevolverunvalorsellamaalafuncionreturnseguidadelvaloradevolver.
Cuandosedefineunafuncin,elcdigoquedelamismanoseejecuta.Soloseejecutarsisellamaa
lafuncin(comocuandosehaciaconrand).Parallamaraunafuncinpondremoselnombredeellay
seguidoyentreparntesissusargumentos(sinohayargumentosseescribirasolamentelosparntesis).

CarreraLinux2008ProgramacionPHP25
Veamosunejemplo:Ladefinicindelafuncinser:
function factorial($numero) {
$fact = 1;
while($numero > 0) {
$fact = $fact * $numero;
$numero = $numero - 1;
}
return $fact;
}

Luegoenalgunapartedelcdigoveremosunllamadadelestilo:
$x = factorial(4);

Enestecaso,$xtendrelvalor24(4!).
Aclaracin:Lasvariablesquesedefinendentrodeunafuncin,existensolamentedentrodelamisma
ynoafectaravariablesquetenganelmismonombreyseencuentrenafueradelafuncin.

Ejemplointegrador
Paraejemplificarelpasajeydevolucindevaloresharemosdosfunciones:unaquenosdigasiunvalor
estonodentrodeunarreglo.Yotraquenosdigacualeselmayorvalordentrodeunarreglo.
Elcdigodelprimerejemploser:
function esta($valorBuscar, $arreglo) {
foreach($arreglo as $valorArreglo) {
if($valorArreglo == $valorBuscar) {
return true;
}
}
return false;
}

Estafuncintomardosparmetros:elelementoabuscaryunarregloendondehacerlo.Luego
devolververdaderosiloencuentraofalsosinoloencuentra.Paraello,irrecorriendoelarregloy
preguntandocadaelementocontraelvalorabuscar.Siloencuentra,entoncesdevuelveverdaderoyla
funcintermina(nosesiguenconsultandolosdemasvalores).
Siseterminoderecorrerelarreglo,entoncesnosehaencontradoelelementoysedevolverfalso.
Siejecutamos:
$miArreglo = array(45, 76, 12, 765);
if(esta(76, $miArreglo)) {
echo "El valor se encuentra en el arreglo";
}

semostrarporpantallaelmensajedelecho.

CarreraLinux2008ProgramacionPHP26
Elcdigodelasegundafuncines:
function buscarMayor($arreglo) {
$indiceMayor = $0;
$valorMayor = $arreglo[0];
foreach($arreglo as $indice => $valor) {
if($valor > $valorMayor) {
$indiceMayor = $indice;
$valorMayor = $valor;
}
}
return array("INDICE" => $indiceMayor, "VALOR" => $valorMayor);
}

Enestecasoselepasaralafuncinunarregloyestanosdevolverotroarreglocondosdatos:el
ndicedelmayorelemento,yelvalordelmismo.
Parabuscaralmayoriremosguardandoenunavariableelmayorvalorencontradoalmomentode
recorrerelarreglo(comenzandoconqueelprimeroeselmayor).Entoncessiencontramosqueunvalor
delarreglo($valor)esmsgrandequeelqueteniamosguardado($valorMayor),lo
reemplazamosporelnuevo(aligualquealndice).
Alterminarelciclo,en$valorMayorquedarelvalormsgrandeyen$indiceMayorsundice.
Unallamadaaestafuncinpodraser:
$miArreglo = array(45, 76, 12, 765);
$mayor = buscarMayor($miArreglo);
echo "El mayor es $mayor[VALOR] y esta en la posicion $mayor[INDICE]\n";

Valorespordefecto
Cuandoselepasanargumentosunafuncinseledebenpasarlamismacantidaddeargumentosconla
quefuedefinida.
Sinembargo,esposibledarlevalorespordefecto.Siaunparmetroseledaunvalorpordefecto,
entoncesnoesobligatorioespecificarlo,yenelcasodenohacerlo,seusarelvalorquetengapor
defecto.
Ejemplo:
function factorial($numero = 26) {
$fact = 1;
while($numero > 0) {
$fact = $fact * $numero;
$numero = $numero - 1;
}
return $fact;
}
factorial();

CarreraLinux2008ProgramacionPHP27
Enestacasoaldarlecomovalorpordefecto26,sepuedellamaralafuncinsinparmetros.Porlo
tanto,alllamarladeestemodo,secalcularaelfactorialde26.
Comoltimaaclaracindiremosquelosparmetrosquetenganvalorespordefectosernlosque
aparezcanltimosenelmomentoenquesedefinelafuncin.

Recursividad
Elconceptoderecursividadessimplementehacerqueunafuncinsellameasimisma.Estoestil
cuandosenecesitahacerunprocesoquerequierehacersubprocesosqueseanigualesal.Porejemplo,
elrecorrertodaunajerarquadedirectorios.Recorrerunsubdirectorioeslomismoquerecorrerel
directorioactual,yassucesivamente.Elclsicoejemploeseldecalcularelfactorial.Elfactorialdeun
nmeron,esigualalproductodesimismoportodoslosdemasqueloprecedenhastael0(osea,el
nmeromultiplicadoporelfactorialdelanterior).Yadems,elfactorialde0es1.
Unafuncinquecalculeelfactorialdeunnmeronsera:
function factorial($n) {
if($n == 0) {
return 0;
}
return $n * factorial($n - 1);
}

Mdulos
Unavezquetengamosmuchasfunciones,vamosanecesitarutilizarladesdeotrosscripts.Seramuy
incomodotenerqueestarabriendoelarchivoquetienelafuncin,copiarlaypegarlaenelnuevo.
Ademssisemodificaenalgunladolafuncinhabraquebuscartodoslosarchivosquelatengan
definidaymodificarlostambin.
Lomejorestenertodaslasfuncionesquesepuedanutilizarporvariaspginasenarchivosseparados,y
"traer"estosarchivosanuestroPHP.Estoselograconlaconstruccinrequire_once.Sipor
ejemplotenemosunarchivoutils.phpquetienedefinidatodaslasfuncionesgenerales,podemos
traertodasestasfuncionesanuestroarchivoactualdelasiguienteforma:
require_once("utils.php");

Consoloagregarestalneaalprincipiodelprogramatendremosdisponiblestodaslasfuncionesquese
encuentreall.
Existeotraconstruccinqueesmuytilllamadainclude.includesediferenciaderequire_onceenque
includetraetodoelarchivoyloreemplazaendondeseencuentrelallamada.Porlotantoescribir:
include("error.php");

seraidnticoacopiarypegartodoelcontenidodeerror.phpendondeseencuentraelinclude.

CarreraLinux2008ProgramacionPHP28
Estaconstruccinsermstilcuandosevealaprogramacinwebyaqueservirpararedireccionara
otrapginahaciendounincludedelamisma.
Otradiferenciaentrerequire_onceeincludeesquelaprimeraseejecutasiempre,
independientementededondesehayaescritoylasegundaseejecutasolosilaejecucinpasaporall.

Ejercicios
1. Enunciecualessonlasventajasdeutilizarfunciones
2. Hacerunafuncion(elegir_opciones)queselepasenvariascadenas(cadaunadeellases
unaopcion)dentrodeunarreglo.Estafunciondebemostrarlealusuariotodaslasopciones
disponiblesyluegodebepermitirleelegirunadeellas.Sielusuarioingresaalgoquenoesta
contempladoenesasopcionesdebepedirlequeingreseunaopcionnuevamente(tambienle
muestralasopcionesnuevamente.Porejemplo,lallamada:
elegir_opciones (array("agregar", "borrar", "consultar", "salir"));

debeproducirunasalidasimilaraesta:
agregar
borrar
consultar
salir
Ingrese su opcion:

Sielusuarionoingresaningunadeesascuatrospalabraslasalidadeberepetirseytambienla
entrada.
3. RealizarunasubrutinaquedevuelvaunalistacontodoslosusuarioscuyoUIDseamenorque
500(privilegiosdeadministrador.Luegorealizarotrafuncionquetomandoestalistacomo
parametros,leadesdeotroarchivovariosnombresdeusuariosydevuelvaunalistaconaquellos
quenoseencuentrenalli.
4. Realizarunasubrutinaqueselepaseporparametroelnombredeunservicio(ejemplo,"ftp",
"http",etc)ydevuelvaelpuertoalqueestaasociado.Paraello,deberaobtenerlainformacion
desdeelarchivo/etc/services.
Sedebeinvestigarcomoeselformatodelarchivo/etc/servicesysedebecrearlaexpresion
regular(unasola)quelorepresente.
5. Hacerunasubrutinaqueimplementeloinversodelaanterior.Debeobtenerporparametroun
puertoyluegodebedevolverunacadenaconelservicioasociado.

Clase6Manejodearchivosydirectorios
Introduccin
Existenalgunasfuncionesparatrabajarsobrearchivosydirectoriosenelsistema.Estasfuncionesno

CarreraLinux2008ProgramacionPHP29
requierendecomandosexternossinoquesecomunicandirectamenteconelSistemaOperativoparaque
lashaga.

DirectorioActual
Lafuncingetcwddevuelveunacadenaconeldirectorioactual.Estafuncinnollevaparametros.
Ejemplo:
echo "El directorio actual es: ", getcwd(), "\n";

mostrarporpantallaunmensajeinformandoeldirectorioactual.

Cambiodedirectorio
Lafuncinchdircambiaeldirectorioactualalqueseleespecifiqueporparmetro.
Porejemplo:
chdir("/usr/bin");

cambiareldirectorioactuala/usr/bin.

Creacindeundirectorio
Lafuncinmkdircreaundirectorio.Estafuncinllevacomoprimerparmetroeldirectorioquese
quierecrearycomosegundoparmetro(opcional)lospermisosquesequierenotorgarle(NOTA:para
escribirunvalorenoctalparausarlodelamismaformaenqueseusaelchmod,elnmerodebe
empezarcon0).
Porejemplo:
mkdir("/home/pepe");

lecreaeldirectoriopersonalalusuariopepe.
mkdir("/home/pepe", 0700);

lecreaeldirectoriopersonalalusuariopepeconlospermisos700.

Eliminacindeundirectorio
Paraeliminarundirectorioseutilizalafuncinrmdir.Parapoderllevaracaboestaaccineldiretorio
debeestarvaco.Estafuncinsolollevaunparmetroqueindiqueeldirectorioquesedeseaeliminar.
Porejemplo:
rmdir("/home/pepe");

CarreraLinux2008ProgramacionPHP30
Lequitaeldirectoriopersonalalusuariopepe.

Copiadodeunarchivo
Lafuncincopysirveparahacerunacopiardeunarchivo.Estafuncinllevadeparmetroselnombre
delarchivoquesequierecopiaryelnombredelnuevoarchivo.Sielnombredelnuevoarchivoya
existe,entoncesseperdernlosdatosdelmismo.
Porejemplo:
copy("backup.tgz", "backup-2003-04-22.tgz");

Renombrarunarchivo
Lafuncinrenamesirveparacambiarleelnombreaunarchivo.Estafuncinllevadeparmetrosel
nombredelviejoarchivoyelnombredelnuevoarchivo.Sielnombredelnuevoarchivoyaexiste,
entoncesseperdernlosdatosdelmismo.
Porejemplo:
rename("backup.tgz", "backup-2003-04-22.tgz");

Eliminacindearchivos
Parallevaracaboestatareaexistelafuncinunlink.Estafuncinllevacomoparmetroelarchivo
quesequiereeliminar.
Porejemplo:
unlink("backup.tgz");

Cambiodepermisos
Esposiblemodificarlelospermisosaunarchivodeformasimilarautilizarelcomandochmod.Para
elloexisteunafuncindelmismonombre,lacualllevacomoparmetroselnombredelarchivoylos
nuevospermisos(lospermisosigualqueconmkdir).
Ejemplo:
chmod("/home/mi_dir/solo_yo_lo_leo", 0700);

ledalospermisos0700aalarchivo"solo_yo_lo_leo".

Cambiodedueo
Esposiblemodificareldueoaunarchivodeformasimilarautilizarelcomandochown.Paraello

CarreraLinux2008ProgramacionPHP31
existeunafuncindelmismonombre,lacualllevacomoparmetroselnombredelarchivoyelnombre
delnuevodueo.
Soloelsuperusuariopuedecambiarlosdueosdetodoslosarchivos.
Ejemplo:
chown("/home/mi_dir/solo_yo_lo_leo", "demian");

leotorgaelarchivo"solo_yo_lo_leo"alusuario"demian".

Cambiodegrupo
Esposiblemodificarelgrupoaunarchivodeformasimilarautilizarelcomandochgrp.Paraello
existeunafuncindelmismonombre,lacualllevacomoparmetroselnombredelarchivoyelnombre
delnuevogrupo.
Soloelsuperusuariopuedecambiarlosgruposdetodoslosarchivos.
Ejemplo:
chgrp("/home/mi_dir/solo_yo_lo_leo", "nobody");

leotorgaelarchivo"solo_yo_lo_leo"algrupo"nobody".

Separardirectorio/archivodeunarutacompleta
Siseposeelarutacompletaaunarchivoexistendosfuncionesparaobtenerestosdatosporseparados.
Laprimeraesdirnamelacualdevuelveeldirectorioylasegundaesbasenamelacualdevuelveel
nombredelarchivo.
Ejemplo:
$archivo = "/etc/X11/XF86Config";
echo "Archivo: ", basename($archivo), "\n";
echo "Directorio: ", dirname($archivo), "\n";

Estogenerarlassiguienteslneas:
Archivo: XF86Config
Directorio: /etc/X11

CarreraLinux2008ProgramacionPHP32

Informacinsobrearchivos
is_writeable
Estafuncintomacomoparmetroelnombredeunarchivoydevuelveverdaderosielarchivotiene
permisodeescritura.

is_readable
Estafuncintomacomoparmetroelnombredeunarchivoydevuelveverdaderosielarchivotiene
permisodelectura.

is_executable
Estafuncintomacomoparmetroelnombredeunarchivoydevuelveverdaderosielarchivotiene
permisodeejecucin.

is_dir
Estafuncintomacomoparmetroelnombredeunarchivoydevuelveverdaderosielarchivoesun
directorio.

is_file
Estafuncintomacomoparmetroelnombredeunarchivoydevuelveverdaderosielarchivoesun
archivonormal.

is_link
Estafuncintomacomoparmetroelnombredeunarchivoydevuelveverdaderosielarchivoesun
link.

file_exists
Estafuncintomacomoparmetroelnombredeunarchivoydevuelveverdaderosielarchivoexiste.

filesize
Estafuncintomacomoparmetroelnombredeunarchivoydevuelveeltamao(enbytes)delarchivo
especificado.

CarreraLinux2008ProgramacionPHP33
fileowner
Estafuncintomacomoparmetroelnombredeunarchivoydevuelvedueo(UID)delarchivo.

filegroup
Estafuncintomacomoparmetroelnombredeunarchivoydevuelvegrupo(GID)delarchivo.

fileatime
Estafuncintomacomoparmetroelnombredeunarchivoydevuelvelafecha(enformatotimestamp)
delltimoaccesoaesearchivo.

filemtime
Estafuncintomacomoparmetroelnombredeunarchivoydevuelvelafecha(enformatotimestamp)
delaltimamodificacinaesearchivo.

filectime
Estafuncintomacomoparmetroelnombredeunarchivoydevuelvelafecha(enformatotimestamp)
delltimocambioalinodocorrespondientealarchivo.

stat
Estafuncintomacomoparmetroelnombredeunarchivoydevuelveunarreglocontodala
informacinobtenidaporlasfuncionesanteriores.

ListadodeArchivosyDirectorios
Existedosformasparaobtenertodoslosarchivosysubdirectoriosqueexistandentrodeundirectorio.

Glob
Laprimeropcineslafuncinglob.Estafuncintienecomoargumentoeldirectorioylosarchivos
quesequierenlistar.Enestafuncinseespecificandelamismaformaquehaceelshell.Estosignifica
queelcaracter*yel?noseraninterpretadosliteralmentesinoqueel*concordarconcualquiertipo
ycantidadcaracteresyel?concordarconunsolocaractercualquiera.
globmedevolverunalistadondecadaelementoeselnombredeunodelosarchivosencontrados.
globomitepordefectotodoslosarchivosydirectoriosquecomienzenconunpunto(.).
Porejemplo,paraobtenertodoslosarchivosjpgdemidirectorioimgenes:
$archivos = glob("./imagenes/*jpg");
foreach($archivos as $archivo) {
echo "$archivo\n";

CarreraLinux2008ProgramacionPHP34
}

opendir,readdir,closedir
Lasegundaopcinessimilaralusodearchivos.Estaconstaenabrireldirectorio,leerdeeltodoslos
archivosysubdirectoriosyluegocerrarlo.Paralaprimeraoperacinseutilizalafuncinopendir
queesanlogaafopen.Estafuncindevuelveundescriptordedirectorio(nombredelavariablecon
lacualsevaahacerreferenciaeldirectorioenmiprogramaenPHP)yluegounacadenaconel
directorioquesequierever.
Luegolafuncinreaddirvadevolviendoporcadallamadaunarchivo.Pordefecto,lafuncin
readdirnoignora(comolohaciaglob)eldirectorio.(directorioactual)yel..(directoriopadre).
Comoparmetroparareaddirsedebeutilizarundescriptorabiertoconlafuncinopendir.
Unavezledostodoslosarchivossecierraeldirectorioconclosedir.
Ejemplo:
$dir_h = opendir("/etc");
while($archivo = readdir($dir_h)) {
echo "$archivo\n";
}
closedir($dir_h);

Argumentosdesdelalneadecomandos
Cuandoejecutamosnuestrosscriptsesposiblerecuperarlosargumentospasadosalmismodesdela
lneadecomandos.Paraello,existeunarreglollamadoargv,elcualsecreaylocompleta
automaticamenteporPHP.Estearreglocontendrenlaposicin0elnombredelscriptyenlas
posicionessiguientestendrtodoslosargumentosquerestan.
Porejemplo,siejecutamosnuestroscriptsdelasiguienteforma:
$ ./mi_programa -v -f datos.txt "Hola Mundo"

Elvectorargvtendr:
0
1
2
3
4

./mi_programa
-v
-f
datos.txt
Hola Mundo

Deestaformaesposiblerecuperartodoslosargumentes.
Tambinexisteunavariablellamadaargclacualcontienelacantidaddeelementosquehayenel
arregloargv(enestecaso5).

CarreraLinux2008ProgramacionPHP35
getopt
Siestamosinteresadosenquenuestrocomandotomeargumentosdelestiloseguidodeunaletra(o
seguidodeunaletrayunvalorasociadoaesaopcin),disponemosdeunafuncinqueinterpretaal
arregloargvdemaneradefacilitarnoselreconocimientodeesteformato.
Aestafuncinseledebeproveerunacadenalacualconsistirdelasletrasquedeseemosquese
reconozcancomoopcionesvlidas.Aquellasqueposeanunvalorasociadoseledebesponerun:
despuesdelaletra.
Luego,estafuncindevolverunarreglaendondelasclavessernlasopcionesingresadas,ycomo
valortendrfalsoenelprimercasoyelargumentoasociadoenelsegundo.
Porejemplo:
$ops = getopt("xhf:");
if(isset($ops["x"])) {
echo "Esta activada la opcion X\n";
}
if(isset($ops["h"])) {
echo "Esta activada la opcion H\n";
}
if(isset($ops["f"])) {
echo "Esta activada la opcion F\n";
}

Enesteejemplosoloseaceptanlasopcionesh,x,yf(estaposeeunvalorasociado).Siejecutamosel
script:./mi_prog -x -f holamostrarporpantalla:
Esta activada la opcion X
Esta activada la opcion F

Valedestacarquealponerfalsoenlasvariablesqueestanactivadas(elvalorasociadoesfalso,perola
entradaenelarregloestadefinida)sedebeutilizarlafuncinissetparadeterminarsiesaposicin
estaonoelegida.

Ejercicios
1. Cualesladiferenciaentreopendir/readir/closediryglob?
2. Hacerunprogramaquelistetodoslosarchivosdeundirectorio(especificadocomoun
argumentodesdeelshell)ordenadosalfabeticamente.Elprogramadeberamostrartodoslos
archivosdeldirectorioespecificadoytambientodosaquellosqueexistandentrodealgun
subdirectoriodelmismo.
3. Hacerunprogramaquehagaunacopiadeundirectorio(especficadocomounargumentodesde
elshell)aotrodirectorio(tambienespecficadocomounargumentodesdeelshell).Luegodela
operacionambosdirectoriosdeberianseridenticos.
NOTA:sedeberancopiartodoslosarchivosdeldirectoriocomoasitodoslosexistentesen
subdirectoriosdelmismo.
4. Hacerunprogramaquenosindiquecuanto(porparametrosedebeespecificarsiverloenbytes,

CarreraLinux2008ProgramacionPHP36
kilobytes,megabytes,gigabytes,etc)espacioseestautilizandoparacadausuarioenelsistema.
5. Hacerunprogramaqueguardeenunarchivodetextoplanotodaslasentradasdeundirectorio
dado(juntoconeltamaodelarchivo).Luegosedeberagenerarotroprogramaquecompareel
contenidodeesearchivoconelestadoactualeneldisco.
Elprogramadeberaalertartantoenelcasoqueseencuentreunaentradaqueestaenelarchivoy
noesteeneldisco,comoasitambienentradasqueesteneneldiscoperonoestenennuestro
archivodetexto.Tambiensedeberaalertarsieltamaohavariado.

Clase7Bibliotecaestndardefunciones
Manejodecadenas
addslashes
Estafuncinsirveparaescaparlascomillasdentrodeunacadena.Estoserespecialmentetilcuando
seutilicenconsultasdentrodeunabasededatos.
Siposeemoslacadena"Hola O'Reilly",silapasamosporaddslashesobtendremosotracadena
quetendrlaforma"Hola O\'Reilly".
Ejemplo:
$cadena = "Hola O'Reilly";
$cadenaNueva = addslashes($cadena);
echo "$cadenaNueva"; # Hola O\'Reilly

choprtrim
Eliminalosespaciosenblancodelfinaldeunacadena.
Ejemplo:
$linea = fgets(STDIN);
$lineaLimpia = chop($linea); #Elimino el \n y todos los blancos que haya ingresado
el usuario

str_replace
Estafuncinnospermitehacerreemplazodentrodeunacadena.Teniendounacadenadeorigen,
podemosreemplazarlapartedelamismaporunacadenaavoluntad.
Suprototipoes:
str_replace ( $cadena_buscada, $cadena_sustituta, $cadena_original)

CarreraLinux2008ProgramacionPHP37
Porejemplo:
$cadena = "aaaBBBccc";
$cadenaNueva = str_replace("BBB", "bbb", $cadena);
echo "$cadenaNueva\n"; # Mostrara aaabbbccc

strlen
Estafuncinnosdevuelvelacantidaddecaracteresqueposeeunacadena.
Ejemplo:
$cadena = "Hola Mundo";
$largo = strlen($cadena); # Devuelve 10

strtoupperstrtolower
Estasfuncionessirvenparatransformartodaunacadenaamaysculasoaminsculas,respectivamente.
Porejemplo:
$cadena = "Hola Mundo";
$cadenaMayusculas = strtoupper($cadena); # HOLA MUNDO
$cadenaMinusculas = strtolower($cadena); # hola mundo

ucfirst
Estafuncinponeenmaysculaelprimercaracterdeunacadena.
Porejemplo:
$cadena = "hola mundo";
$cadenaNueva = ucfirst($cadena); # Hola mundo

ucwords
Estafuncinponeenmaysculaelprimercaracterdecadapalabradentrodeunacadena.
Porejemplo:
$cadena = "hola mundo";
$cadenaNueva = ucwords($cadena); # Hola Mundo

wordwrap
Estafuncincortaaunacadenaencaracteresdecomomaximountamao,especificadospor

CarreraLinux2008ProgramacionPHP38
parmetro,agregandounseparadorentrelaspalabrasqueexcedaneselmite.
Porejemplo:
$cadena = "Este es un mensaje de prueba, para cortarlo y ver que queda";
$nuevaCadena = wordwrap($cadena, 20, "\n");

yen$nuevaCadenaquedar:
Este es un mensaje\n
de prueba, para\n
cortarlo y ver que\n
queda.\n

Manejodearreglos
array_merge
Estafuncinfusionamuchosarreglospasadoscomoargumentosenunnicoarreglo.Silosarreglosa
fusionartienenclavesrepetidas,entoncessetomarelvalordelaltimaaparicin.Sisonnmericasse
agregarntodosalfinal.
Porejemplo:
$arreglo1 = array(45, 67, 23);
$arreglo2 = array("nombre" => "Pepe", "color" => verde);
$arregloNuevo = array_merge($arreglo1, $arreglo2);
# el nuevo arreglo es
# 0
=> 45
# 1
=> 67
# 2
=> 23
# nombre => Pepe
# color => verde

array_pop
Devuelveelltimoelementodeunarreglo,yloeliminadelmismo.Sielarregloestavaco,devolver
vaco.
Ejemplo:
$arreglo = array(45, 76, 12, 33);
$ultimoElemento = array_pop($arreglo); # 33
# $arreglo quedara con (45, 76, 12)

CarreraLinux2008ProgramacionPHP39
array_push
Agregaunelementoalfinaldelarreglo.
Ejemplo:
$arreglo = array(45, 76, 12, 33);
array_push($arreglo, 29);
# $arreglo quedara con (45, 76, 12, 33, 29)

NOTA:Usararray_pusheslomismoqueutilizarloscorchetesvacos([])delasiguienteforma:
$arreglo[] = 29;

array_shift
Devuelveelprimerelementodeunarreglo,yloeliminadelmismo,reduciendolacantidadde
elementosenuno.Sielarregloestavaco,sedevuelvevaco.
Ejemplo:
$arreglo = array(45, 76, 12, 33);
$ultimoElemento = array_shift($arreglo); # 45
# $arreglo quedara con (76, 12, 33)

array_unshift
Estafuncinagregaunelementoalprincipiodelarreglo,desplazandoalosdemselementos.
Ejemplo:
$arreglo = array(45, 76, 12, 33);
array_unshift($arreglo, 29);
# $arreglo quedara con (29, 45, 76, 12, 33)

count
Devuelvelacantidaddeelementosdeunarreglo.
Ejemplo:
$arreglo = array(45, 76, 12, 33);
$cantidadElementos = count($arreglo); # 4

in_array
Estafuncinnospermitebuscarunelementodentrodeunarreglo.Siloencuentranosdirverdadero,

CarreraLinux2008ProgramacionPHP40
sinofalso.
Tomadosparmetros,elprimeroeselelementoabuscar,yelsegundoelarreglo.
Ejemplo:
$arreglo = array("hola", "jose", "pepe");
if(in_array("hola", $arreglo)) {
echo "Esta la palabra 'hola'\n";
}
if(in_array("report", $arreglo)) {
echo "Esta la palabra 'report'\n";
}

# Esto saldra por pantalla


# Esto NO saldra por pantalla

array_search
Estafuncinnospermitebuscarunelementodentrodeunarreglo.Siloencuentranosdevolverla
claveasociadaalmismoofalsosinoloencuentra.
Tomadosparmetros,elprimeroeselelementoabuscar,yelsegundoelarreglo.
Ejemplo:
$arreglo = array("hola", "jose", "pepe");
$clave = array_search("jose", $arreglo);
# 1
$clave = array_search("report", $arreglo); # false

sort
Ordenatodosloselementosdeunarreglodemenoramayor.Ademsasignarindicesnuevosacada
valor,porloquecualquierndiceoclaveexistenteseperder.
Ejemplo:
$arreglo = array(45, 23, 79, 55);
sort($arreglo);
# ahora el arreglo esta ordenado.
# quedara como (23, 45, 55, 79)

asort
Ordenatodosloselementosdeunarreglodemenoramayor,manteniendolarelacinentrelasclavesy
susvalores.
Ejemplo:
$arreglo = array("pepe" => 26, "anibal" => 23, "emilio" => 30);
asort($arreglo);
# quedara ("anibal" => 23, "pepe" => 26, "emilio" => 30)

CarreraLinux2008ProgramacionPHP41
ksort
Ordenaloselementosdeunarreglo,demenoramayor,segnlasclaves.
Ejemplo:
$arreglo = array("pepe" => 26, "anibal" => 23, "emilio" => 30);
ksort($arreglo);
# quedara ("anibal" => 23, "emilio" => 30, "pepe" => 26)

rsort
Anlogaasort,peroordenandordemayoramenor.

arsort
Anlogaaasort,peroordenandodemayoramenor.

krsort
Anlogaaksort,peroordenandodemayoramenor.

Manejodefecha
time
Estadevuelvalafecha/horaactualconelformatotimestampdeUNIX.Esteformatosecuentacomola
cantidaddesegundosdesdeelEpochdeUNIX(1deEnerode1970alas00:00:00).
Ejemplo:
$timestampActual = time();

date
Estafuncinsirveparadarleformatoaunafechaenformatotimestamp.Poseedosargumentos,el
primeroeselformatoyelsegundolafechaencuestin(sisoloseusaunparmetrosetomarpor
defectolafechaactual).
Lacadenadelformatoesunacadenanormal,endondealgunoscaracteressernreemplazadosporel
campodelafechacorrespondiente.Entrelosmscomunesencontramos:
Caracter

Descripcin

Da.0031

Mes.0012

CarreraLinux2008ProgramacionPHP42
Y

Ao4dgitos.AAAA

Ao2dgitos.AA

Hora.0023

Minutos.0059

Segundos.0059

Ejemplo:
# Fecha actual sin la hora
$fechaActual = date("d/m/Y");
# Fecha actual con la hora
$fechaHoraActual = date("d/m/Y H:i:s");
# Fecha de una semana a partir de la fecha actual
$fechaUnaSemana = date("d/m/Y", time() + (60 * 60 * 24 * 7));
# Dia actual
$dia = date("d");

checkdate
Controlasiunafechaesvlida(Aobisiesto,dasincorrectos,etc).Posee3parmetros:mes,diayao.
Ejemplo:
if(checkdate(2, 31, 2006)) {
echo "La fecha 31/2/2006 es correcta\"; # Esto NO se vera
}
if(checkdate(12, 20, 2006)) {
echo "La fecha 20/12/2006 es correcta\"; # Esto SI se vera
}

Ejercicios
1. HacerunprogramaqueleadesdeSTDINtantaslineascomohaya.Luegolasdeberamostrarpor
pantallaordenadasdemenoramayorporellargodelasmismas.
2. Sepidecargardosarreglosconnumeros(leidosdesdedosarchivosdetexto).Luegosedebe
ordenarambosarreglosporseparado.Finalmentesedebemostrarporlasalidaestandarlos
numerosdeambosarreglosordenadosensutotalidad,aplicandolasiguienteidea:Sedebeir
leyendosimultaneamentedecadaarreglounelemento,comparandolosymostrandoelmenor,
paraluegoleerelproximodesdeelarregloqueseacabademostrar.Alfinal,sedebetenertoda
unasalidaordenada.

CarreraLinux2008ProgramacionPHP43
3. Dadoundirectoriocualquiera,sepidehacerunscriptquenospermitavertodoslosarchivos
quecorrespondanaunmespedidoporparametro.
4. Mostrartodoslosarchivosdeundirectorio(ydesussubdirectorios)ordenadosporsufechade
ultimoacceso.
5. Sepidehacerunscriptquefiltrepalabrasenunarchivodetexto(origen).
Esteprogramarequierequelepasenunarchivodetextoporparametro.Tambienseposeeotro
archivoconpalabrasafiltrar(unaporlinea).Setienequegenerarunarchivonuevoconel
contenidodelarchivodeorigenperoreemplazandolaspalabrasqueaparezcanenelarchivode
filtrosporasteriscos(*).Sedebeponertantosasteriscoscomoletrastengalapalabra.

Clase8ServiciosdeInternet
SimpleMailTransferProtocol(SMTP)
Unodelosserviciosmscomneseninterneteselcorreoelectrnico.Msprecisamente,paraenviar
correoseutilizaelprotocoloSMTP(SimpleMailTransferProtocol).Parahacerusodeesteprotocolo,
PHPposeeunafuncinllamadamail.Estafuncinnoimplementaesteprotocolo,sinoqueharfalta
tenerinstaladosendmailenlamquinadondeseejecuteelscript.
Estafuncintiene3parmetrosobligatorios:el/losdestinatarios,elasuntoyelmensaje.
Veamoselejemplomssimple:
$destinatario = "alguien@algunlugar.com";
$asunto = "El coso tiene algo";
$mensaje = "Cuidado con los mensajes que divagan";
mail($destinatario, $asunto, $mensaje);

Elformatodeldestinatariopuedeincluirmsdeunadireccin(segnelRFC2822).Algunosformatos
posibles,segnelsitiodePHP,son:

usuario@example.com
usuario@example.com,otrousuario@example.com
Usuario<usuario@example.com>
Usuario<usuario@example.com>,OtroUsuario<otrousuario@example.com>

Elcampoasuntonodeberatenerningnsaltodelnea(\n)yaqueestopodrahacerqueelcorreono
puedaserenviadosatisfactoriamente.
Elcampomensajesipuedecontenersaltosdelnea.Tambinserecomiendaquesiexistealgunalnea
quecontengamsde70caracteres,estasecortadaendos.Paraestovienetillafuncinwordwrap.
Entonces,siqueremosestarsegurosqueelmensajequedeentreloslmitesdefinidospodemoshacer:
$mensaje = wordwrap($mensaje, 70, "\n");

CarreraLinux2008ProgramacionPHP44
TambinesposibleagregarotrascabecerasmsespecificasdelprotocoloSMTP.Paraello,selepuede
pasar,opcionalmente,uncuartoparmetroconunacadenaquecontengacabecerasSMTPparaenviar
talcualsepasa.
Siporejemplo,queremosconfigurarladireccinderespuesta(elFrom)podemosagregarlacabecera:
$cabeceras = "From: micorreo@miservidor.com";
mail($destinatario, $asunto, $mensaje, $cabeceras);

EntreotrascabecerascomnesencontramosReplyTo(ladireccinaquiendebenresponder),CC
(copiadelemail),BCC(copiaocultadelemail)yContentType(parasetearquetipodeemailes:texto,
html,etc).Lascabecerasdebenserseparadaspor\r\n.
Podramostenerentoncesunacabeceracomolasiguiente:
$cabeceras = "Content-type: text/html; charset=iso-8859-1\r\n
Reply-To: correo_real@miservidor.com\r\n
CC: quien_controla@unservidor.com\r\n
BCC: El Jefe quien_realmente_controla@unservidor.com";
mail($destinatario, $asunto, $mensaje, $cabeceras);

PostOfficeProtocol(POP)
ParadescargaryconsultarelcorreoelectrnicoseutilizaelprotocoloPOP3(PostOfficeProtocol).
Estenospermitirconsultarloscorreos,descargarlos,yobtenerinformacinsobreellos.

Conexinalservidor
Paraconectarnosalservidorutilizaremoslafuncinimap_open.Ellanospermiteconectaradistintos
servicios,peroporahorautilizaremossololonecesarioparaPOP3.
Lafuncinrequiere3parmetros:elservidorconelformato{servidor/pop3:110}INBOX,el
usuarioylacontrasea.
Siselograconectaralservidor,nosdevolverunobjetodesdeelcualpodremosconsultarlacasilla,en
casocontrariodevolverfalso.
Ejemplo:
$pop = imap_open("{pop.servidor.com/pop3:110}INBOX","usuario","password");
if(!$pop) {
die("Error: " .imap_last_error());
}

Cantidaddemensajes
Lacantidaddemensajesquehayenlacasillapuedeobtenermediantelafuncinimap_num_msg.
Estafuncinnosdevolverunnmerocondichacantidad.

CarreraLinux2008ProgramacionPHP45
Encdigo:
$cantidadMensajes = imap_num_msg($pop);

Recuperandomensajes
Pararecuperarlosenutilizaremoslafuncinimap_fetch_overviewlacualnosdarunarreglo
conunobjetocontodalainformacingenericaparacadaunodelosmensajeselegidos.
DeparmetrosdebermosespecificarleelrecursosPOPylasequenciademensajes.Lasecuencia
puedesertantounniconmerodemensaje(sedevuelveesesolo),unalistadenmerosseparadospor
comas(sedevolvercadaunodeloselegidos)odosnmerosseparadosporundospuntos(:)(locual
nostraertodoelrango,1:3trae1,2y3).
Entreloscamposparacadamensajesnosencontramoscon:
Campo

Descripcin

subject

Ttulodelmensaje

from

Quienenvioelmensaje

to

Destinatario

date

Fechadeenvo

message_id

IDdelmensaje

in_reply_to EsunarespuestaalIDdelmensajequetiene
size

Tamaodelmensaje,enbytes

uid

Identificadordelmensaje

msgno

Nmerodelmensaje

Ennuestroejemplo,traeremostodoslosmensajesutilizandolacantidad(1:cantidad):
$cantidadMensajes = imap_num_msg($pop);
if($cantidadMensajes > 0) {
$encabezados = imap_fetch_overview($pop, "1:$cantidadMensajes");
foreach($encabezados as $encabezadoMensaje) {
echo "$encabezadoMensaje[from]\t$encabezadoMensaje[subject]\n";
}
}

Pararecuperarelcuerpodelmensajeposeemoslafuncinimap_body.Estafuncinrecibedos
parmetros,elrecursoPOPyelnmerodemensaje.Luegoobtendremosunacadenacontodoel
cuerpo.Debemosaclararquecadalneaestarseparadaporun\r\n.
Pararecuperarelcuerpodelmensaje2solodebemoshacer:
$cuerpoMensaje = imap_body($pop, 2);
echo "$cuerpoMensaje";

CarreraLinux2008ProgramacionPHP46
Eliminacindemensajes
Paraeliminarlosmensajesdelservidorserequierendospasos.Primerosedebenmarcarlosmensajes
quesequiereeliminar.Luegosedebedarlaordendeeliminarlos.
Paraelprimerodelospasosseposeelafuncinimap_delete.Comoesdeesperarseestafuncin
requiereelrecursoPOPyelnmerodemensajeaeliminar.
Paraelsegundopasoseposeelafuncinimap_expunge.Paraesta,solosenecesitaelrecursosPOP.
Cabedestacarquesoloharfaltahacerunanicallamadaaestafuncin,mientrasqueseharnvariasa
imap_delete.
Porejemplo:
imap_delete($pop, 1);
imap_delete($pop, 2);
imap_delete($pop, 3);
imap_expunge($pop); // Los mensajes 1, 2 y 3 fueron eliminados por completo

FileTransferProtocol(FTP)
Esteservicioesmuyutilizadoparatransferirarchivos.ElFTP(FileTransferProtocol)es,en
definitiva,nimsnimenosqueunsimpleservidordearchivos.

Conexinalservidor
ConectarseaunservidordeFTPrequierededospasos:laconexinylaautentificacin.
Pararealizarelprimerpasoutilizaremoslafuncinftp_connect.Estafuncinrequieredeun
parmetrobsicoqueesladireccindelservidor.
LuegositodoafuncionadobiennosdevolverunrecursodesdeelcualaccederalFTP,encaso
contrarionosdevolverfalso.
Parahacerelsegundopasoutilizaremoslafuncinftp_login.Estafuncinrequierede3
parmetros:elrecursoquenospermitecomunicarnosconelFTP(elobtenidoporftp_connect),el
nombredeusuarioylacontrasea.
Estafuncindevolververdaderoofalsosegnhayaonopodidoautentificarsecontraelservidor.
Porltimo,unavezterminadadeusarlaconexin,podemoscerrarlautilizandolafuncin
ftp_closeypasndoleelrecursoFTPcomoparmetro.
Encdigo:
$servidor_ftp = "ftp.miservidor.com";
$usuario_ftp = "nombre_usuario";
$password_ftp = "secreta";
$ftp = ftp_connect($servidor_ftp);
if(! $ftp ) {

CarreraLinux2008ProgramacionPHP47
}

die("Error al conectarse a $servidor_ftp");

if (! ftp_login($ftp, $usuario_ftp, $password_ftp)) {


ftp_close($ftp);
die("Error al autentificarse contra el servidor");
}
// El programa...
ftp_close($id_con);

Subirarchivos
Parasubirarchivosalservidorposeemoslafuncinftp_put.EstafuncinprecisadelrecursoFTP,
unacadenaqueapuntealarchivolocalyotraalarchivoremoto.Valedestacarqueambasrutasal
archivopuedensertantoabsolutascomorelativas(comoenelshell).ElservidorFTPtambinposeeun
directorioactualparacadausuarioconectado.
Sitodoafuncionadocorrectamenteftp_putdevolververdadero,sinodevolverfalso.Veamosun
ejemplo(considerarquelaconexinyaestahechayseposeeelrecursoFTPenlavariable$ftp):
$archivo_local = "datos.txt";
$archivo_remoto = "./datos/usuario_datos.txt";
if (! ftp_put($ftp, $archivo_remoto, $archivo_local)) {
echo "Error al tratar de subir el archivo $archivo_local\n";
}
// Si no hubo errores el archivo datos.txt estar en el servidor como
./datos/usuario_datos.txt

Descargandoarchivos
Paratraerunarchivodesdeelservidoranuestramquina,debemosusarlafuncinftp_get.Estaes
similaraftp_putperoharloinversoytendr,porlotanto,lomismoparmetrosperoinvertidosel
archivolocalconelarchivoremoto.
$archivo_remoto = "libreria_quemefalta_lap-1.43.546376.rpm";
$archivo_local = "lib.rpm";
if (! ftp_put($ftp, $archivo_local, $archivo_remoto)) {
echo "Error al tratar de descargar el archivo $archivo_remoto\n";
}
// Si no hubo errores el archivo libreria_quemefalta_lap-1.43.546376.rpm estar en
la maquina local como lib.rpm

CarreraLinux2008ProgramacionPHP48
Eliminandoyrenombrandounaarchivoremoto
ParaeliminarunarchivoqueesencuentreenelFTPdebemosusarlafuncinftp_delete.
SencillamentehabrquepasarelrecursoFTPylarutaalarchivoaborrar.
Sitodofuncionabiennosdevolververdaderoofalsoencasocontrario.
Ejemplo:
$archivoBorrar = "datos_temp.txt";
$ok = ftp_delete($ftp, $archivoBorrar);
if($ok) {
echo "Se ha borrado exitosamente el archivo $archivoBorrar\n";
} else {
echo "Ha ocurrido un error al tratar de borrar el archivo
$archivoBorrar\n";
}

Pararenombrartenemoslafuncinftp_renamelacualnecesitadelrecursoFTP,elnombrede
archivoviejoyelnuevo.
Sitodofuncionabiennosdevolververdaderoofalsoencasocontrario.
Ejemplo:
$archivoViejo = "datos_temp.txt";
$archivoNuevo = "datos_hoy.txt";
$ok = ftp_rename($ftp, $archivoViejo, $archivoNuevo);
if($ok) {
echo "Se ha renombrado exitosamente el archivo $archivoViejo\n";
} else {
echo "No se ha podido renombrar el archivo $archivoViejo a
$archivoNuevo\n";
}

Manejodedirectorios
Aligualqueenlamquinalocal,poseemoscomandosparacrearyborrardirectorioscomoastambin
paracambiareldirectorioactual,yrecuperarelmismo.Respectivamentetenemos:
Comando

Descripcin

Retorno

ftp_mkdi Creaundirectorio.Sedebeespecificarelrecurso falsoencasodeerror,ounacadena


FTPyuncadenaconelnombredeldirectorio conelnombredeldirectoriocreado.
r
rmdir

Eliminaundirectorio.Sedebepasarpor
parmetroelrecursoFTPyeldirectorioa
eliminar

Verdaderoofalsosegnhayapodidoo
nocambiardedirectorio

ftp_chdi Cambiaeldirectorioactual.Sedebepasarpor Verdaderoofalsosegnhayapodidoo


parmetroelrecursoFTPyelnuevodirectorio. nocambiardedirectorio
r
ftp_pwd

Devuelveeldirectorioactual.Solosedebepasar Unacadenaconlarutadeldirectorio

CarreraLinux2008ProgramacionPHP49
elrecursoFTPcomoparmetro.

actual.

Recuperandolosarchivosdeundirectorio
PararecuperarlosnombresdelosarchivosdesdeunFTPposeemosdosfunciones:ftp_nlisty
ftp_rawlist.
Laprimeralternativaesusarftp_nlist.EstafuncinrequieredelrecursoFTPydeldirectoriodel
cualsequierenrecuperarlasentradas.
Nosdevolverunaarregloconcadaunadelasentradasencontradas(incluyendoeldirectorio.yel
directorio..).
Ejemplo:
$dirActual = ftp_passwd($ftp);
$entradas = ftp_nlist($ftp, $dirActual);
foreach($entradas as $entrada) {
echo "$entrada\n";
}

Lasegundaalternativaserutilizandoftp_rawlist.ftp_rawlistfuncionaigualque
ftp_nlist,peronosdevolverunasalidamsdetallada,paralacualdeberemoscrearunaexpresin
regularpararecuperarlaspartesdeinteres.
Encdigo:
$dirActual = ftp_passwd($ftp);
$entradas = ftp_rawlist($ftp, $dirActual);
foreach($entradas as $entrada) {
echo "$entrada\n";
}

Ejercicios
1. Hacerunprogramaqueacepteporparametrounadirecciondeemaildedestinatario,unemail
deorigen,unasuntoyelnombredeunarchivodetexto.Luegoelprogramadeberaenviarun
emailaldestinatarioconlosdatossuministrados.
2. Modificarelejercicioanteriorparaquelevanteelservidorydemasdatosconfigurablesdesde
unarchivodetextoqueposealaforma:
opcion=valor

dondeopcionseraunodelosaspectosconfigurable(comoServidor)yvalorseaelvalor
correspondiente.
3. HacerunprogramaqueeliminetodoslosemailsdesdeunPOP3cuyosRemitentesse
encuentrenenunalistanegra.
Lalistanegraconsistiraenunarchivodetextoelcualcontieneunemaildebajodeotro.

CarreraLinux2008ProgramacionPHP50
4. Modificarelejerciciosanteriorparaquelalistanegraestedivididaendospartes.Laprimer
serviraparaespecificarservidoresprohibidos.Deestemodoconindicarspammer.comtodo
emailquevengadesdealli(jose@spammer.com,pepe@spammer.com)deberasereliminado.
Lasegundaparteserviraparaponerdireccionesespecificas(comofuncionabaantes).
Elformatodelarchivosedejaacriteriolibre.
5. Hacerunprogramaquedescarguetodolosarchivosdesdeunftpdadoyundirectoriodadodel
mismo(ambospasadosporparametros).Elprogramadeberadescargartodoslosarchivosdel
directoriocomoasitambienlosdetodoslossudirectoriosquepuedanexistirydeberaquedar
localmenteunacopiafieldeldirectorioremoto.
Clase9Referencias

Introduccin
Hastaestemomento,siemprequehemosprogramado,hemosestadoutilizandovariables.Estasvariablessiempreposeanunnicocontenido(unnmero,unacadena,unarreglo,etc)yesemismocontenido
siempretenaunmismonombre(eldelavariable).EstononecesariamenteessiempreasiyaquePHPnospermitedarledistintosnombresauncontenidoatravsdelasreferencias.
Unareferenciamepermitiraccederuncontenidodefinidoanteriormenteporotravariable.Loqueharrealmenteesdarleotronombrealmismocontenido.
Paracrearunareferenciahayqueutilizareloperador&delasiguienteforma:
$var = 486;
$ref = &$var;
Deestaformahemoscreadounavariablenormalllamada$varquetieneelvalor486.Luegohemoscreadounareferencia(llamda$ref)quehacereferencia(valgalaredundancia)almismo486.
Siejecutamos:
echo "var = $var\n";
echo "ref = $ref\n";
ambosmostrarn486.Comolavariable$refy$varhacenreferenciaalmismocontenido,simodificamosunadeella,laotraseverinevitablementealterada.
Siporejemplo:
$ref = $ref + 1;
entonces:
echo "var = $var\n";
echo "ref = $ref\n";
ambosmuestranelvalor487.Estosedebaaqueunmismocontenido(originalmente486)puedetenerdistintosnombresalmismotiempo.Unavezcreadalareferenciaesindistintosiusamos$varo$ref
yaqueambossonnombresdelmismocontenido.
ReferenciasyFunciones
CuandotrabajamosenPHPlasreferenciasnossernespecialmentetilescuandotrabajemosconfunciones.
Paraejemplificarestoveamoslasiguientefuncin:
function incrementar($var) {
$var++;
echo "[incrementar] var = $var\n";
}
$contador = 1;
echo "[antes] contador = $contador\n";
incrementar($contador);
echo "[despues] contador = $contador\n";
Sicorremosesteprogramaveremoslasalida:
[antes] contador = 1
[incrementar] var = 2
[despues] contador = 1
Lacualfuncionaracomohabradeesperarse.Sinembargo,nuestroobjetivoalcrearlafuncinincrementaresquelavariablequesepasoporparmetroquedeconelvalorincrementadoen1.
Aquesdondeentranenjuegolasreferencias.Veamosunaversinmodificadadelafuncinanterior:

CarreraLinux2008ProgramacionPHP51
function incrementar(&$var) {
$var++;
echo "[incrementar] var = $var\n";
}
Lehemosagregadoun&enladeclaracindelafuncin.EstoleindicaaPHPqueeseparmetrosepasarporreferencia.Alpasarlosparmetroscomunmente(comoyahemosvisto)estossonpasadospor
valor.Estoquieredecirquelavariable(enestecaso$var)contendrunacopiadelavariablepasadaporparmetro(enestecaso$contador).Estonosiempreesdeseable.Siquiciesemosmodificardicha
variabledeberiamosutilizarunareferencia.Comohemosvistoalprincipioalutilizarunareferencia,ambasvariableapuntanalmismocontenidoporloquemodificandounasemodificalaotra.
Conestaversinmodificadaahoraobtendremoslosresultadosdeseados:
[antes] contador = 1
[incrementar] var = 2
[despues] contador = 2
Unaventajadepasarlosparmetrosporreferencias(ademasdepodermodificarlos)esquenoesnecesariocrearunacopiadelosmismo.Siloqueseintentapasaresmuygrande(digamosunarreglocon
muchasentradasquesonarreglosqueasuveztienenmuchasentradasyetc),alcrearunacopiaestaramosdesperdiciandoespacioytiempo.Encambio,alpasarloporreferenciasolohayqueagregarun
nuevonombreparaelcontenidoyaexistente.
Eliminandoreferenciasyvariables
PHPnospermitevolveradejarunavariablequeyahemosutilizadoenestadodeindefinida(comosinuncalahubiesemosusado).Paraelloexistelafuncinunset.Aestafuncinsolohayquedarle

comoparmetrolavariableautilizar.
Porejemplo:
$x = 3;
unset($x);
echo "x = $x\n";

mostrar"x ="yaquelavariablexestavaca.Comoxeraelniconombrequeteniaelcontenido
asociado(Queteniavalor3),aleliminarsexseperderesevalor(yanohaynadiequienhagareferencia
ael).Encambio,sidisponemosdeunareferencia,alaplicarunsetsolamenteborraremosesenombre
asociadoaesecontenido.Lasdemasreferenciasaesenombrenoseperdern,porlotanto,elcontenido
seguirexistiendo.
Ejemplo:
$x = 3;
$ref = &$x;
unset($x);
echo "x = $x\n";
echo "ref = $ref\n";

mostrar:
x =
ref = 3

tambinfuncionaralreves:
$x = 3;
$ref = &$x;
unset($ref);
echo "x = $x\n";
echo "ref = $ref\n";

CarreraLinux2008ProgramacionPHP52
locualmostrar:
x = 3
ref =

Ejercicios
1. Quesonlasreferenciasycualessonsusaplicacionespracticas?
2. Seposeeunavariablealacualselecreaunareferencia.Silavariableeseliminadaperola
referenciano,seperderelcontenido?
3. Unavezcreadaunareferencia,enquesediferencialavariablequetienelareferenciadela
original?
4. Realizareljuegotatetiparadosjugadores.Pararepresentareltablerosedeberusaruna
matriz.

Clase10Manejodeobjetos
Introduccinalaprogramacinorientadaaobjetos
Hastaelmomentohemosestadoprogramandodentrodeloquesellamaelparadigmade
programacinestructurado.Enesteesquema,siemprepartiamosdesdeelproblemamsgrandeylo
ibamospartiendoenpedazosmschicosparasuresolucin.
Enelparadigmadeobjetos,lahistoriaesunpocoalreves,partiendodesdeloespecfico(unobjeto)
hastalogeneral.
Unobjetoestacompuestoporsuestado(losatributos)ysusresponsabilidades(losmtodos).Los
atributossonelconjuntodevaloresqueguardacadaobjeto.Losmtodossonlosserviciosquepresta
eseobjeto(porejemplo,siseposeeunobjetoquerepresentaaunCliente,entoncessepodratenerun
mtodoCobrarelcualpermitaalsistemaregistraruncobrodelcliente).
Losobjetosexistendentrodeunambiente.Luegosepodrncomunicarconotrosobjetosmedianteel
pasodemensajes(invocacionesamtodos).Unmensajeesunpedidodeunobjeto(emisor)aotro
(receptor)unservicio,queesteserejecutadoenelreceptorporunmtodo.
DentrodeesteparadigmatambinexistealgollamadoClases.LasClasesson"losmoldes"delos
objetos.Osea,paracrearunobjeto,debotenerunaclasequelodefina.Enrealidad,unobjetoseruna
instanciadeunaclase.Podramospensarlocomoqueelobjetoeslaclaseenejecucin.

Clasesyobjetos
Elprimerpasoparacrearunobjeto,comohemosmencionado,estenerunaclasededondesacarlo.La
sintaxisparacrearunaclasecualquieraeslasiguiente:

CarreraLinux2008ProgramacionPHP53
class NombreClase {
// Definicion de atributos
// Definicion de metodos
}

Paradefinirunatributousaremosundelassiguientes3palabrasreservadas:public,private,
protected.
Antesdeexplicarlasveremoscomoseescribe:
public $nombre;
private $apellido;
protected $edad;

Atributos
Sidefinimosunatributocomopublic,entoncesestepodrseraccedido(tantoparaleerlocomopara
modificarlo)desdeafueradelobjeto.Osea,cualquierobjetopuedeteneraccesoaesteatributo.
Estoes,porlogeneral,malo.Esdemuymalaprcticaytraemuchosproblemasqueunobjetopueda
modificarelestadodeotro.Cadaobjetoesresponsablepormantenersuestado.Adems,deestaforma,
sisoloelobjetomismoesquienseocupademanejarsuestado,solohabraquecambiareneseobjeto
encasodenecesitarhacerunamodificacin.
Sidefinimosunatributocomoprivate,solopuedeseraccedidoporelobjetomismo.Ningnotro
objetobajoningunacircustanciapodrmodificardichoatributo.
Finalmente,silodefinimoscomoprotected,sololopodrnaccederelobjetomismouobjetosque
heredendeesaclase(verHerencia).
Estoquieredecirqueunasubclasepodrusarlosatributosdefinidosenlaclasemadre(losdistintos
objetos,instancias,deestaclasenopodrnaccederalosatributosdeotrosobjetos).
Dentrodelosmtodossiqueremosaccederaunatributo,entoncesdeberemoshacerloescribiendo
$this->seguidodelnombredadoalatributo(sinel$).

Mtodos
Paradefinirunmtodoutilizaremoslaestructurafunction.Estaesidnticaquelasfunciones
definidasporelusuarioexplicadasenclasesanterioressalvoqueestarndentrodeunaclase.Porlo
tanto,PHPlasinterpretarcomomtodosdedichaclase.
Losmtodostambinposeenunavisibilidadcomolosatributos(public,privateoprotected)
ycumplirnlasmismascondicionesperosobreelmtodo.Sinoseespecificaningunadelas3setoma
pordefectoqueelmtodoespublic.
Darmosunejemplodeunaclasesencillaparamostrartodoloexplicado:

CarreraLinux2008ProgramacionPHP54
class Persona {
private
private
private
private

$nombre;
$apellido;
$edad;
$pais;

public function setNombre($nombre) {


$this->nombre = $nombre;
}
public function setApellido($apellido) {
$this->apellido = $apellido;
}
public function setEdad($edad) {
$this->edad = $edad;
}
public function setPais($pais) {
$this->pais = $pais;
}
public function getNombre() {
return $this->nombre;
}
public function getApellido() {
return $this->apellido;
}
public function getEdad() {
return $this->edad;
}
public function getPais() {
return $this->pais;
}

public function getNombreCompleto() {


return "$this->apellido, $this->nombre";
}

Instanciacin
Unavezdefinidalaclase,podemoscrearobjetosapartirdeella.Esteprocesosellamainstanciacin.
Paraelloutilizaremoseloperadornewseguidodelnombredelaclaseylosparntesis.
Luego,paraaccederaunmtodo,(osea,enviarleunmensajealmismo),escribiremosellavariabledel
objetoseguidaporun->,elnombredelmtodoysusparmetros.

CarreraLinux2008ProgramacionPHP55
ConsiderandolaclasePersona,podramosescribir:
$persona1 = new Persona();
$persona1->setNombre("Pepe");
$persona1->setApellido("Estalag");
$persona1->setEdad(23);
$persona1->setPais("ARG");
echo "Persona: ", $persona1->getNombreCompleto(), "\n";

Herencia
Elconceptodeherenciasignificapoderdefinirunaclasetomandocomoenbaseaotra.Laprimera
serlaclasehijamientrasquelasegundaserlaclasepadre.Alheredardesdeunaclase,lanuevaclase
poseerautomticamentetodoslosatributosymtodosdelaclasepadre,peropodremosagregarle
nuevosatributosymtodos(y/omodificarlos).
Lasclaseshijasseescribenaligualquecualquierotraclase(sonclasesdespuesdetodo)conla
excepcinquehayqueagregarledequeclaseestanheredando.Paraello,luegodelnombredelaclase
hija,sedebeagregarlapalabrareservaextendsseguidadelnombredelaclasepadre.
Veamosunejemplo:
class Empleado extends Persona {
private $sueldo;
public function setSueldo($sueldo) {
$this->sueldo = $sueldo;
}
public function getSueldo() {
return $this->sueldo;
}
public function getTrabajo() {
return "Empleado";
}
}

AquhemosdefinidounaclaseEmpleadoqueextiende(hereda)dePersona.Estarelacintambin
seledice"esun"(EmpleadoesunaPersona).
Sicreamosunobjetodeestaclase,podremosllamartantoalmtodosetSueldoygetSueldo,
comoatodoslosmtodosdefinidosparalaclasePersona.

Redefinicin
Comohabiamosmencionadosanteriormente,cuandocreamosunaclasehija,estaheredatodoel
comportamientoylosatributosdelpadre.Sinembargo,nosiemprequeremosquetodoloheredado

CarreraLinux2008ProgramacionPHP56
funcioneigual.Tenemoslaposibilidadderedefinirlosmtodosquenosseannecesarios.
Expandiendoelejemploanterior,definiremossubclasesdeEmpleado:Vendedor,Gerente.
Elcdigodelasclaseseselsiguiente:
class Gerente extends Empleado {
public function getSueldo() {
return $this->sueldo * 5;
}

public function getTrabajo() {


return "Gerente";
}

class Vendedor extends Empleado {


private $ventas;
private $porcVentas;
public function venta($monto) {
$this->ventas[] = $monto;
}
public function getSueldo() {
$extra = array_sum($this->ventas) * $this->porcVentas;
return $this->sueldo + $extra;
}
public function setPorcVentas($porcVentas) {
$this->porcVentas = $porcVentas;
}

public function getTrabajo() {


return "Vendedor";
}

Enesteejemplovemosquealcrearlasnuevasclaseshijas,hemosredefinidoelmtodogetSueldoy
getTrabajo.Ahoralosnuevosmtodostrabajarandiferentealoriginal,pero,vistodesdeafuera,no
habrdiferenciaentrepedirleelsueldoaunobjetodeltipoEmpleado,quealdeltipoGerente.
Veamostodoestoenaccin:
$vendedor1 = new Vendedor();
$vendedor1->setNombre("Jose");
$vendedor1->setApellido("Gest");
$vendedor1->setEdad(25);
$vendedor1->setPais("ARG");
$vendedor1->setSueldo(500);
$vendedor1->setPorcVentas(0.1);
$vendedor1->venta(1000);
$vendedor1->venta(100);
$vendedor1->venta(700);

CarreraLinux2008ProgramacionPHP57
$vendedor2 = new Vendedor();
$vendedor2->setNombre("Pedro");
$vendedor2->setApellido("Arquimedes");
$vendedor2->setEdad(30);
$vendedor2->setPais("ARG");
$vendedor2->setSueldo(500);
$vendedor2->setPorcVentas(0.1);
$vendedor2->venta(7000);
$vendedor2->venta(400);
$vendedor2->venta(300);
$vendedor2->venta(600);
$gerente = new Gerente();
$gerente->setNombre("Armando");
$gerente->setApellido("Quilombo");
$gerente->setEdad(45);
$gerente->setPais("ARG");
$gerente->setSueldo(2000);
$empleado1 = new Empleado();
$empleado1->setNombre("Raul");
$empleado1->setApellido("Castillo");
$empleado1->setEdad(35);
$empleado1->setPais("ARG");
$empleado1->setSueldo(700);
$empleado2 = new Empleado();
$empleado2->setNombre("Paul");
$empleado2->setApellido("Blanco");
$empleado2->setEdad(28);
$empleado2->setPais("ARG");
$empleado2->setSueldo(700);
printf("Persona: %-30s Trabajo: %-10s Sueldo: \$%d\n",
$empleado1->getNombreCompleto(),
$empleado1->getTrabajo(),
$empleado1->getSueldo());
printf("Persona: %-30s Trabajo: %-10s Sueldo: \$%d\n",
$empleado2->getNombreCompleto(),
$empleado2->getTrabajo(),
$empleado2->getSueldo());
printf("Persona: %-30s Trabajo: %-10s Sueldo: \$%d\n",
$vendedor1->getNombreCompleto(),
$vendedor1->getTrabajo(),
$vendedor1->getSueldo());
printf("Persona: %-30s Trabajo: %-10s Sueldo: \$%d\n",
$vendedor2->getNombreCompleto(),
$vendedor2->getTrabajo(),
$vendedor2->getSueldo());

CarreraLinux2008ProgramacionPHP58
printf("Persona: %-30s Trabajo: %-10s Sueldo: \$%d\n",
$gerente->getNombreCompleto(),
$gerente->getTrabajo(),
$gerente->getSueldo());

Polimorfismo
Elltimoconceptoquenosquedaeseldepolimorfismo.Sedicequedosobjetossonpolimrficos
cuandosonintercambiables.Estoquieredecirquepodemosponercualquieradelosdosyelprograma
funcionarconambos.Paraelloambosobjetosdebentener,porlomenos,unmtodoquetengaigual
nombreeigualcantidadytipodeargumentos.
Paraejemplificaresto,haremosunaclaseEmpresa:
class Empresa {
private $personal;
private $costoFijo;
public function agregarEmpleado($empleado) {
$this->personal[] = $empleado;
}
public function setCostoFijo($costo) {
$this->costoFijo = $costo;
}
public function calcularTotalSueldos() {
$total = 0;
foreach($this->personal as $empleado) {
$total += $empleado->getSueldo();
}
return $total;
}
public function getGastosTotal() {
return $this->costoFijo + $this->calcularTotalSueldos();
}
public function listadoEmpleados() {
foreach($this->personal as $empleado) {
printf("Persona: %-30s Trabajo: %-10s Sueldo: \$%d\n",
$empleado->getNombreCompleto(),
$empleado->getTrabajo(),
$empleado->getSueldo());
}
}
}

Aqusepuedeapreciarelpolimorfismo,porejemplo,enelmtodocalcularTotalSueldos.All

CarreraLinux2008ProgramacionPHP59
cuandoserecorreelarreglosellamaalmtodogetSueldodecadaunodelosempleados.Cuandose
ejecutaestemtodonosesabequehayenelarreglopersonal.Puedehabertantoobjetosdetipo
Empleado,comodetipoGerente,comodetipoVendedor,ounamezcladeambos.Cualquiera
seaelcaso,selepediralobjetoqueejecuteelmtodogetSueldosinsabernicomolohace,nide
quetipoeselobjeto,nidedondesacalainformacin.
TambinsevelomismoenelmtodolistadoEmpleadoselcualgenerelmismoformatode
listadoqueelexpuestoenelejemploanterior.
Veamosunejemplodelusodeestanuevaclase,considerandocreadoslosobjetosdeempleados:
$empresa = new Empresa();
$empresa->agregarEmpleado($empleado1);
$empresa->agregarEmpleado($empleado2);
$empresa->agregarEmpleado($vendedor1);
$empresa->agregarEmpleado($vendedor2);
$empresa->agregarEmpleado($gerente);
$empresa->setCostoFijo(7000);
$empresa->listadoEmpleados();
echo "Total Gastos: \$", $empresa->getGastosTotal(), "\n";

Constructoresydestructores
Unconstructoresunmtodoqueseejecutaautomaticamentealmomentodeinstanciarunaclase.De
estaforma,disponemosdeunaherramientaparainicializarelestadodenuestroobjetoanuestra
voluntad.
EnPHP,yapartirdelasversiones5.X,elmtodoconstructortienepornombre__construct.
Elconstructorpuedeonotenerparmetros.Silostiene,entoncessernecesariopasarselosalmomento
deinstanciarlaclase.Losparmetrosalconstructorseescribiranentreloscorchetesenelmomentode
hacerelnewsobrelaclase.
Porejemplo,podramosmodificarlaclaseEmpleadoparaquequedeas:
class Empleado extends Persona {
protected $sueldo;
public __construct() {
$sueldo = 0;
}
public function setSueldo($sueldo) {
$this->sueldo = $sueldo;
}
public function getSueldo() {
return $this->sueldo;
}

CarreraLinux2008ProgramacionPHP60
public function getTrabajo() {
return "Empleado";
}
}

Deestamaneronosaseguraramosquesiempreseposeeunvalorcargadoenelatributosueldo,ya
quesilollegramosautilizarsinhaberlecargadounvalor(ennuestroejemplo,sinhaberllamadoa
setSueldo),nostirarunerror.
Eldestructoresunmtodoqueseejecutacuandotodaslasreferenciasalobjetosehayanperdido.Esto
ocurrircuandofinaliceelscriptocuandoforzadamenteseeliminenlasreferencias.
Elnombredelmtodo,anlogamentealconstructor,deberllamarse__destructynopodrrecibir
ningnparmetro.

Ejercicios
1.
2.
3.
4.
5.

Definirlos3conceptosbasicosdelparadigmadeobjetos.
Definirobjeto.CualesladiferenciaentreClaseyObjeto?
Definirelconceptodeherencia.Deunejemploendondeseriautil.
Definirelconceptoderedefinicion.Deunejemploendondeseriautil.
Definirelconceptodepolimorfismo.Deunejemploendondeseriautil.

Clase11Excepciones
Introduccin
Lasexcepcionessonunmtodoparaelmanejodeerrores.Bsicamentesonuncanalseparadopara
enviarerrores.Deestaformanospermiteeliminardenuestrocdigolosmtodosmsantiguoscomo
devolverelerrorcomovalorderetornodeunafuncin,unavariableglobal,usarifs,etc.
Paraelloseutilizarunanuevaestructura:try/catch.Estaestructuraestacompuestaporunbloque
decdigo,try,elcualpodronoarrojarunaexcepcin,yunbloquedecdigo,catch,quese
ejecutarcuandosearrojeefectivamentelaexcepcin.Encasocontrario,elbloquedelcatchNOse
ejecutar.
Conceptualmente,elsistemadeexcepcionesfuncionadelasiguientemanera.Enalgnpuntodondese
detecteunacondicindeerror,selanzarunaexcepcin.Enestemomento,PHPdejardeejecutarel
script,eirhaciaatrassuspasosenlalneadellamadashastaencontrarunbloquetry/catchque
capturelaexcepcin.Cuandoloencuentre,reanudarlaejecucinenelbloquedecdigodelcatch.
Denoexistirunbloquecatchqueatrapelaexcepcin,PHPterminarlaejecucindelscripty
mostrarunerrorfatal.

CarreraLinux2008ProgramacionPHP61

Manejobsico
Parademostrarloexpuesto,haremosunpequeoejemplo.Crearemosdosclases.Laprimeraser
ControladorTransferencia.Estaclasellevaruncontandodecuantosbytessehan
transmitidosycualeselmximoadmisible.LuegotendremoslaclaseUsuarioquerepresentaraun
usuariologueado.Estetendrunmtododescargar,parapoderbajarunarchivoydentrodelsele
pediralcontroladordetransferenciaqueestipulesipuedeonobajarelarchivopedido.Encasodeno
poder,elcontroladortirarunaexcepcin.
Veamoselcdigo:
class ControladorTransferencia {
private $maximoBajada;
private $bytesTransferidos;
function __construct($maximoBajada) {
$this->maximoBajada = $maximoBajada;
$this->bytesTransferidos = 0;
}
public function transferir($bytes) {
if($this->bytesTransferidos + $bytes > $this->maximoBajada) {
throw new Exception("Excedido el limite maximo de
transferencia");
}
$this->bytesTransferidos += $bytes;
}
}
class Usuario {
private $username;
private $controladorTransferencia;
function __construct($nombre) {
$this->controladorTransferencia =
new ControladorTransferencia(100 * 1024 *
1024); // 100Mb
$this->username = $nombre;
}
public function descargar($archivo) {
$tamArchivo = filesize($archivo);
$this->controladorTransferencia->transferir($tamArchivo);
// Aqui codigo para enviar
}
}

EnelmtodotransferirdeControladorTransferenciasepuedeverdondesetiralaexcepcin.La
estructuraparatirarunaexcepcinesthrowseguidadeunobjetoException.
Aqusepuedeverque,endefinitiva,anivelcdigo,unaexcepcinesnimsnimenosqueunobjeto.
UsamoslamsbsicadetodasqueesExceptionperoluegoveremosotrasposibilidades.Es

CarreraLinux2008ProgramacionPHP62
importantedestacarquesedebehacerunnewdelaclaseyaquesinoestaramostratandodearrojarla
clasemismaocurriendounerrordeejecucin.
Tambinpodemosconfigurarleunmensajedeerrorparaesaexcepcinenparticular,suministrndoleal
constructordelaexcepcinunacadenaarbitraria.
Veamosestasclasesenuso:
$usuario = new Usuario("mister");
try {

$usuario->descargar("misteriuos_data.tgz");
} catch (Exception $e) {
echo "Excepcion atrapada\n";
echo "Archivo: ", $e->getFile(), "\n",
"Linea:
", $e->getLine(), "\n",
"Mensaje: ", $e->getMessage(), "\n";
}

echo "\nBacktrace:\n", $e->getTraceAsString();

Aquapareceporprimeravezelbloquetry/catch.Comoseveenelbloquetryhemospuesto
todaslassentenciasquepuedantirarunaexcepcin(esestecasoesunasolaperopodranserms).
Luegovieneunbloquecatch,elcualtienecomo"argumento"unaexcepcinqueseguardaenla
variable$e.EstolohaceautomticamentePHPy,afinesprcticos,nosotrossolousaremosesavarible
dentrodelbloque.Laexcepcinnosdamuchainformacinsobreelerror.Enparticular,unobjeto
Exceptiontienevariosmtodosinteresantes.Asaber:
Mtodo

Descripcin

getFile

Nosdevuelveelnombredelarchivo.phpdesdeelcualsearrojolaexcepcin

getLine

Nosdevuelveelnmerodelneadesdedondesearrojolaexcepcin(donde
estaelthrow).

getMessage

Nosdevuelveunacadenaconelmensajedeerror(elqueconfiguramos
cuandocreamoselobjetoException)

Nosdevuelveunacadenacontodaslasllamadasquesehicierondesdeelnivel
getTraceAsString msaltohastaelmtodoquetirolaexcepcin.Deestaformapodemosir
siguiendoelcaminoquellevoelprogramayencontrarelerrorlgico.

Excepcionesdefinidasporelusuario
HastaaqusolohemosutilizadolaexcepcinException,peroPHPtambinnospermitecrear
nuestraspropiasexcepciones.Estoserviraparadarleunsignificadomayoralaexcepcin.Alrecibir
unaexcepcindiferentepodemossabermsprecisamenteelerrorypodremosdiferenciarlasdeotras
excepciones(verelapartadosiguienteManejodemultiplesexcepciones).
Tambinnospermiteagregarlefuncionalidadesextraalobjetodeexcepcin,agregndoletambin
informacinextraparticularparaesecaso.

CarreraLinux2008ProgramacionPHP63
ParacrearunanuevaexcepcinsolamentehayquecrearunaclasequeherededelaclaseException.
Estosolobastaparacrearlanuevaexcepcin.Detodosmodos,comomencionanmosantes,podemos
agregarlemsatributosymtodos.
Ennuestroejemplo,crearemosunaexcepcinnuevapararepresentarellimiteexcedidoyguardaremos
enellalosvalores(mximo,actualylopedido)paraluegodarmsinformacincuandofalle.
ElcdigodelanuevaclaseylamodificacinenlaclaseControladorTransferenciaparaque
empleeestanuevaexcepcin:
class limiteExcedidoException extends Exception {
private $maximo;
private $actual;
private $pedido;
public function getMaximo() {
return $this->maximo;
}
public function getActual() {
return $this->actual;
}
public function getPedido() {
return $this->pedido;
}
public function setMaximo($maximo) {
$this->maximo = $maximo;
}
public function setActual($actual) {
$this->actual = $actual;
}
public function setPedido($pedido) {
$this->pedido = $pedido;
}
}
class ControladorTransferencia {
private $maximoBajada;
private $bytesTransferidos;
function __construct($maximoBajada) {
$this->maximoBajada = $maximoBajada;
$this->bytesTransferidos = 0;
}

public function transferir($bytes) {


if($this->bytesTransferidos + $bytes > $this->maximoBajada) {
$e = new limiteExcedidoException("Excedido el limite maximo de transferencia");
$e->setMaximo($this->maximoBajada);
$e->setActual($this->bytesTransferidos);
$e->setPedido($bytes);
throw $e;
}
$this->bytesTransferidos += $bytes;
}
}

Veamosahoracomoatraparestanuevaexcepcin:
$usuario = new Usuario("mister");
try {
$usuario->descargar("users.php");
} catch (limiteExcedidoException $e) {
echo "Excepcion atrapada\n";
echo "Archivo: ", $e->getFile(), "\n",
"Linea:
", $e->getLine(), "\n",
"Mensaje: ", $e->getMessage(), "\n";
echo "Maximo admisible: ", $e->getMaximo(), "\n",
"Bytes Transferidos: ", $e->getActual(), "\n",

CarreraLinux2008ProgramacionPHP64
"Bytes pedidos: ", $e->getPedido(), "\n",
"Bytes excedentes: ",
($e->getActual() + $e->getPedido()) - $e->getMaximo(), "\n";
echo "\nBacktrace:\n", $e->getTraceAsString();
}
ParaatraparunaexcepcinenparticularcambiaremoseltipoExceptionporeldenuestraexcepcinenelbloquecatch.Deestaforma,yparaesteejemplo,lavariable$etendrnuevosmtodosqueno
poseenlasexcepcionescomunes(getMaximo,getActualygetPedido).Porlotanto,ademsdelainformacinestndarhemosagregadoinformacinextrarelacionadaconlostamaosrequeridos.

Manejodemultiplesexcepciones
Puedeocurrir,yesmuycomn,queparaunbloquetrysepuedandispararvariasexcepcionesdiferentes.Puedesernecesariotratardeformadistintacadaexcepcin.Porlotantopodemosdefinirtantos
bloquescatchcomoexcepcionestengamos.
Cadabloquecatchdeberdefiniracadatipodeexcepcin.Elprimerbloquecatchdebertenerlaexcepcinmsespecficayeltlimolamsgeneral(Exception).Silosescribimosalreves,
Exceptionconcordarconcualquierexcepcintiremosyseutlizaresesinrevisarlosdems.
ModificaremoslaclaseUsuarioparaquearrojeotraexcepcin:
class Usuario {
private $username;
private $controladorTransferencia;
function __construct($nombre) {
$this->controladorTransferencia =
new ControladorTransferencia(1024); //*1024);//*100);
$this->username = $nombre;
}
public function descargar($archivo) {
if(!file_exists($archivo)) {
throw new Exception("El archivo $archivo no existe");
}
$tamArchivo = filesize($archivo);
$this->controladorTransferencia->transferir($tamArchivo);
// Aqui codigo para enviar
}
}
Luegoagregaremoselmanejoparaambasexcepciones(limiteExcedidoExceptionyException):
$usuario = new Usuario("mister");
try {
$usuario->descargar("users.php");
} catch (limiteExcedidoException $e) {
echo "Excepcion atrapada\n";
echo "Archivo: ", $e->getFile(), "\n",
"Linea:
", $e->getLine(), "\n",
"Mensaje: ", $e->getMessage(), "\n";
echo "Maximo admisible: ", $e->getMaximo(), "\n",
"Bytes Transferidos: ", $e->getActual(), "\n",
"Bytes pedidos: ", $e->getPedido(), "\n",
"Bytes excedentes: ",
($e->getActual() + $e->getPedido()) - $e->getMaximo(), "\n";
echo "\nBacktrace:\n", $e->getTraceAsString();
} catch (Exception $e) {
echo "Excepcion atrapada\n";
echo "Archivo: ", $e->getFile(), "\n",
"Linea:
", $e->getLine(), "\n",
"Mensaje: ", $e->getMessage(), "\n";
echo "\nBacktrace:\n", $e->getTraceAsString();
}
ComoseveaquprimerosecapturalaexcepcionlimiteExcedidoExceptionyluegoException.PHPseencargarautomticamentedeejecutarelprimerbloquecatchqueconcuerdeconla
excepcintiradaynosasegurarquenoseejecutaningnotrobloquecatch.
Ejercicios
1.

2.
3.
4.

Queesunexcepcionyparaquesirve?
Cuantosbloquescatchpuedehaberenunaconstrucciontry/catch?porque?
Queinformacinmeproveeunaexcepcion?
Comoseextiendeunaexcepcion?Quefuncioncumple?

CarreraLinux2008ProgramacionPHP65

Clase12Introduccinalaprogramacinweb
ConceptosGeneralessobreProgramacinWeb
Laprogramacinwebconsistebasicamente,engenerarpginasHTMLdinamicamente.Estoquiere
decirquecadavezquesequieraverunapgina,estadebercrearseenelmomentoyparaquienla
pida.
Cuandoseaccedeaunapginahaytresatoresenescena:Elcliente(unnavegador),Elservidorweby
PHP(enestecaso).
Lospasossonlossiguientes:
1.
2.
3.
4.

Elclientepideverunapgina.php
ElservidorwebreconocequenoesunHTMLesttico
SeejecutaelinterpretedePHPyejecutalapgina.php
Lasalidagenerada(todoloqueelscriptenvealasalidaest)poresteprogramaseenviaal
clienteparaquelavisualice

ParacomunicarseentreelclienteyelservidorseutilizaelprotocoloHTTP.Esteprotocolosirvepara
muchomsquedevolverpginasHTMLperoporelmomentosolousaremosestacaracterstica.
Enelpaso3esdondeocurrelamagia.Cuandoseejecutalapginaseutilizatodounlenguajede
programacion(PHP)paracrearla.Estoimplicaqueseusarnvariables,decisiones,operaciones,ciclos,
etc.Enunprograma,lasvariablesmantienenel"estado",esdecir,losvaloresprocesados.Estosvalores
sepierdencompletamentecuandoseterminadeejecutarlapgina.

EstructurabsicadeunHTML
TodoHTMLdebetenerporlomenosestostrestagsquedefinenlaestructurabsica:HTML,HEAD,
BODY.
EltagHTMLsirveparaencerrartodoelarchivodehtml.
Sera:
<HTML>
</HTML>

EntremediodeestosdostagsseescribirtodoelcontenidodeHTMLquesequieraquemuestreel
archivo.
EltagHEADsirveparadeterminaralgunosparmetrosgeneralesdelHTMLqueseesteeditando.Se
puedesetearelttulodelapgina(elquenormalmenteelnavegadorutilizacomottulodelaventana)o
algunasreglasgeneralesdelmanejodefuentes,ometadata.Estetagseraelprimeroquesedebe
encontrarluegodel<HTML>.
ParaestablecerelttuloseutilizaeltagTITLE.

CarreraLinux2008ProgramacionPHP66
Quedaraalgoasi:
<HTML>
<HEAD>
<TITLE> El ttulo </TITLE>
</HEAD>
</HTML>

EltagBODYeselquedelimitaelcuerpodelHTML.Dentrodeestetagseescribirtodoloquese
quieraqueseveaenlapantallacuandoseintenteverelarchivo.
Laestructurabsicaquedarafinalmente:
<HTML>
<HEAD>
<TITLE> El ttulo </TITLE>
</HEAD>
<BODY>
Hola Mundo
</BODY>
</HTML>

Enesteejemplo,semostraraporpantallaeltexto"Hola Mundo".
NOTA:LosejemplosdeHTMLqueaparecerandeaquenadelante,sonfragmentosdelenguajequese
escribedentrodeltagBODYanoserqueseindiquelocontrario.
Primeroquenadaveamosquepasarasiescribimosesto:
Hola a todos,
queria informarles que esto sale mal

Lasalidasera:
Hola a todos, queria informarles que esto sale mal

Locualnoesloqueseesperaba.EstosedebeaquecuandoseinterpretaelHTML,anoserquese
encuentreuntag,loscaracteresqueseencuentransemuestrandirectamenteyseignorantodoslos
espacios.Parapoderlograrquesebajedelneahayqueponeruntagquelohaga.Dichotageseltag
BR.Estetagnotienefin,simplementecuandoseloencuentraelnavegadorbajardelinea.Sera:
Holas a todos,<BR>
queria informarles que esto casi sale bien

Lasalidaseraahora:
Holas a todos,
queria informarles que esto casi sale bien

CarreraLinux2008ProgramacionPHP67
Sibienmejorqueantesnolosuficientementebien.Paraponerespaciossepuedealinearlotodousando
tablasoponerlosespacios.Paraponerespaciossedebecomoescaparelespacio,locualselogra
escribiendo&nbsp;
Tambinpuedenespecificarseprrafos.Laventajadeestoesquedentrodeunprrafosepuede
configurarlajustificacindeltexto(izquierda:left,centrado:center,derecha:right).Eltagque
haceestoeseltagP.Laopcinparalajustificacinesalign.CuandoseescribeuntagP,elnavegador
comenzarelprrafocomenzandoinmediatamentedesdelalneaprxima.Sinoseespecificaelfindel
tag(el</P>)secerrarautomaticamentecuandosetermineelarchivo.
Veamosunejemplo:
Entonces el dijo:<P ALIGN=CENTER>"No olvidar.<BR>Lo que ves ya se ha visto ya."

Lasalidaser:
Entonces el dijo:
"No olvidar.
Lo que ves ya se ha visto ya."

EltagPdejounalneaenblancoycomenzoelnuevoprrafo.SibienelHTMLescritoescorrecto,ya
pesardequelos"ENTER"seignorenalahorademostrarlosporpantalla,esbuenacostumbrebajar
unalnealuegodeescribirun<P>oun<BR>.

Dandoleestiloaltexto
Esposibledarleestilosaltexto.Quepasarasienelejemploanterior,quicieramosquelaparteentre
comillasaparezcaenitlicas(cursiva).ParaelloexisteneltagI.Quedaraalgoas:
Entonces el dijo:
<P ALIGN=CENTER>
"<I>No olvidar.<BR>
Lo que ves ya se ha visto ya.</I>"

Ahoraelnavegadorlomostrarenletracursiva(tambinquedamsclaroelhaberloorganizado
diferente,no?).
Enelsiguientecuadroselistantodoslostagssimilaresquedanotrosefectos:
TAG

EFECTO

<B>...</B>

Negrita

<I>...</I>

Itlica(Cursiva)

CarreraLinux2008ProgramacionPHP68
<U>...</U>

Subrayado

<SUB>...</SUB> Subindice
<SUP>...</SUP>

Supraindice

Tambinexisteuntagparasetearuntextocomottulo.ParaelloestaeltagHseguidodeunnmero
entre1y6.Estoledareltamaoalttulosiendoel1elmsgrandeyel6elmspequeo.Estetag
tambintienelaopcinALIGNparasetearlajustificacin.
Porejemplo:
<H1 ALIGN=CENTER>Profecias</H1>

Pondrunttulobiengrandeycentradoquedira"Profecias"ennuestroHTML.

CreandoLinks
Unlinkesunaenlaceentredospginas.Deestaformacuandoelusuarioapretesobreellink,selo
llevarautomaticamenteaesedocumento.Laideabsicaesqueunlinkvinculeoenlaceinformacin
relacionadadeformatalquequiennavegelapginapuedairdescubriendotodalainformacinque
busca.
ParacrearunlinkseutilizaeltagA.EstetagtienelaopcionHREFlacualmepermiteespecificaraque
documentohacereferencia.Porejemplo:
Grandes obras:
<A HREF=la_biblia_segun_vox_dei.html>La Biblia segun Vox Dei</A>
<A HREF=the_lamb.html>The Lamb Lies Down On Brodway, Genesis</A>

Aqusecrearandoslinks.Elprimerollevaralarchivola_biblia_segun_vox_dei.html.Sinembargoel
usuarioveraenlapantallaloqueseencuentredentrodeltagA,enestecaso,LaBibliasegunVoxDei.
Lomismoocurrirconelsegundolink.
EltagAtieneotrascuantasopciones.Veremos,sinembargo,unasolams,laopcionTARGET.Esta
opcinnospermiteespecificaradondequeremosquesehabraellink.Puedellevarelnombredeun
frameparaqueloabraall,opodrallevarunnombrequenoesteusadoenningnladoyabrirallink
enunanuevaventana,comounpopup.Porlogeneralseledaelnombre_webparaestetipodetarget.
Porejemplo:
<A HREF=propaganda.html TARGET=_web>Gane mucho dinero</A>

Enesteejemplo,cuandoseapretesobreellink(creyendoganarmuchodinero)aparecerunpopupcon
propaganda.

CarreraLinux2008ProgramacionPHP69

Tablas
LastablassonunadelasherramientasmstilesdelHTMLyseusaranhastaelcansancio.Unatabla
essimplementeunareadelhtmlqueestadivididaenceldas,yendondecadaceldapuedecontener
cualquiercosadeHTML.
LastablaslasutilizaremosparaorganizarvisualmenteelHTMLcomotambinparacrearcuadros.
Estasconsistenenfilasycolumnas(aunquenonecesariamentecoincidanencantidad).
EltagparacreartablassellamaTABLE.Estetagtienevariasopciones,entreellasencontramos:
ALIGN:DeterminalaalineacindetodalatablaenelHTML(aligualqueconeltagP)
BORDER:Determinaelanchodelbordequetendrnlasceldas.Sies0notendraningnborder.Por
defectoelvalores1.
WIDTH:Determinaelanchodelatabla.Sepuedeespecificarenpixeles(poniendoleunvalor)oen
porcentaje(poniendoun%luegodelvalor).PorejemploWIDTH=100ledarauntamaode100
pixelesmientrasqueWIDTH=100%usartodoelanchodelaventana.
BGCOLOR:Determinaelcolordefondoquetendralatabla.Loscoloresseescribencomouna
combinacindeRojo,VerdeyAzul(RGB).Cadacolorpuedevariarentre0y255(oenhexadecimal
entre0yFF).Sedebeescribirunnumeral(#)yluegolostresvaloresdeloscolores(enhexadecimal).
Porejemplo,paraobtenerelcolorazulsera#0000FF
ParacrearunafilaseutilzaeltagTR.EstetagtieneunaopcinALIGNparaalineareltextodentrode
esafila,yunaopcinBGCOLORparadarleuncolordefondoalafilaunicamente.Dentrodeestetagse
deberespecificarcadaceldaquehabraenesafila.
ParacrearunaceldaseutilizaeltagTD(tambintienelasopcionesALIGNyBGCOLORquese
comportanigualquelasdeTRperoanivelcelda).Veamosunejemplocompletodeunatabla:
<TABLE BORDER=1>
<TR>
<TD>Celda 1</TD>
<TD>Celda 2</TD>
</TR>
<TR>
<TD>Celda 3</TD>
<TD>Celda 4</TD>
</TR>
<TR>
<TD>Celda 5</TD>
<TR>
</TABLE>

Lasalidaser:
Celda1 Celda2
Celda3 Celda4
Celda5

CarreraLinux2008ProgramacionPHP70
Comovemosnohemosespecificadolaltimacolumnaporlocualquedarvaca.Comocantidadde
columnassetomarlafilaquetengamsceldayaquellasfilasquenolleguenaesacantidadquedarn
vacas.
Esposiblejuntarlasultimasdosceldasparaquequedeprolijo,paraelloenlaltimaceldadeberiamos
indicarlequedebeutilizardoscolumnasdeancho.ParaelloestalaopcinCOLSPAN.Siledamosel
valordossetomarlasdoscolumnas.Quedaraas:
<TABLE BORDER=1>
<TR>
<TD>Celda 1</TD>
<TD>Celda 2</TD>
</TR>
<TR>
<TD>Celda 3</TD>
<TD>Celda 4</TD>
</TR>
<TR>
<TD COLSPAN=2>Celda 5</TD>
<TR>
</TABLE>

Yahoralasalidaseracorrecta:
Celda1 Celda2
Celda3 Celda4
Celda5
Tambinpuedehacerseestoanivelfilas(juntardosfilasenunacolumna)siutilizamoslaopcin
ROWSPANenvezdeCOLSPAN.

Ejercicios
1. Queesunpaginawebdinamica?Adondedebeenviarselasalidadelamismayquefuncion
conocidadePHPutilizariaparaello?
2. EnquesebasalosarchivosHTML?Comoestaconformadountag?
3. DequesirvepodercreartablasenHTML?Comosedeterminalacantidaddefilasy
columnasdeunatabla?
4. Quehacenlosnavegadoresconunconjuntoconsecutivodecaracteresblancos(espacios,
ENTER,tabulaciones,etc)?Queutilidadleencuentraadichohecho?
5. Senecesitacrearunaseriedescriptsqueinformensobrealgunosaspectosdelestadoactualdel
sistema.
Estosscriptsdebegenerar:
a. Unhtmlquesebasaraeninformacionqueencuentreenelarchivo/etc/lilo.conf.De
dichoarchivodeberaextraerelcampomessageytodosloscamposlabel.Luegodebera
mostrarelcampomessageyluegoenunatablacentradatodosloslabelsqueencontro.
b. Unhtmlquesebasaraenlainformacionqueencuentreenelarchivo/etc/inittab.Este

CarreraLinux2008ProgramacionPHP71
HTMLdebemostrarunatablacondosentradas(doscolumnas)endondelaprimerasera
laaccionylasegundaelcomando.Desdeelarchivo/etc/inittabsedebeextrarelcampo
accionycomandodetodosaquellosquepertenezcanalosrunlevels3,4o5.
NOTA:Cadaentradadelarchivoinittabtieneelformato:
id:runlevel1,runlevel2,...,runlevelN:accion:comando

Paramasinformacionverelmanualinittab(5)
c. AquisedeberangeneraunHTML(usuarios.html)conunlistadodetodoslosusuarios.
Cadausuarioseraunlinkaotrapagina(llamadausuario_nombre.html,porejemplo,
pararootserausuario_root.html)quetendralainformaciondelusuario.Todala
informaciondelosusuariosseencuentraen/etc/passwdyladelosgruposen/etc/group)
Enparticularcadapaginadelusuariotendralasiguienteforma:
Primeroentitulo1ycentrado(h1)estaraelnombredelusuario.Luegovendraunatabla
quetendraenlaprimerfila,doscolumnas:unaquediraelUIDyotraelGID.Enla
segundafiladiraeldirectoriopersonalyelshell.Enlatercerfiladeberainformala
informacionextraquehaya(estefiladebeocupardoscolumnas).
Luegosedeberamostrarotratablaquelistetodoslosgruposaloscualpertenecedicho
usuario.Cadaentradadeestegruposeraunlinkalainformaciondelgrupo(vermas
adelante).
d. Tambiensedebegenerarunarchivo,grupos.html,elcualcontendraunlistadodetodos
losgruposexistentes(segunelarchivo/etc/group).Cadaentradaseraunlinkala
informaciondelgrupo(similaralosusuarios).Decadagruposedebeponeruntitulo
centradoH1conelnombredelgrupoyluegounatabladeunasolacolumnaqueliste,en
cadafila,atodoslosusuariosdeesegrupo.Cadausuarioseraunlinkalainformacion
delmismo.
Esnecesariocreartambienunhtml,menu.html,paraaccederacadaunodeestoscuatro
puntos.Tambien,cadahtmldebetenerunlink,abajoaladerecha,quediga"Volver"el
cualmepermitiravolveralapaginaanterior(almenu.html,salvocuandosetratadela
informaciondeunusuarioogrupo,endondellevarallistadocorrespondiente).
NOTA:Porsimplicidadsesugierehacerdosscriptsseparadosparaelpuntoayb,yuno
soloparaelpuntocyd.

CarreraLinux2008ProgramacionPHP72

Clase13HiperTextMarkupLanguage(HTML)
Parte2
Listas
EnHTMLunalistaessimplementelaenumeracinodenotacindevarioselementos.Estoselementos
sernendefinitiva,texto.Laslistasservirnentoncesparadarleformatoalasalida.
Unalistapuedeserordenadaodesordenada.Aquellasquesonordenadasllevarnalgntipode
numeracin,lasotrasllevarnsimplementealgunavieta.

Listasdesordenadas
Laslistasdesordenadasquedandefinidasporeltag<ul> ... </ul>(UnorderedList).Dentrode
estetagseespecificarntodosloselementosdelalista.Cadaelementodelalistasedefinireneltag
<li>...</li>.
Ejemplo:
<ul>
<li><A HREF=http://www.atptennis.com>Tenis</A></li>
<li><A HREF=http://www.freeprogrammingresources.com>Free Books</A></li>
<li><A HREF=http://www.clarin.com.ar>Las noticias</A></li>
</ul>

DeestaformaelHTMLexibiralgoas:

Tenis
FreeBooks
Lasnoticias

Loqueesposibleconfigurardelaslistasdesordenadasesquedibujoutilizarcomovieta.Entrelos
posiblesestanuncirculo,uncuadradooundisco(pordefecto).Paraellohabrqueagregarlelaopcin
TYPEaltagUL.LosvaloresdeesaopcinsonCIRCLE,SQUAREyDISCrespectivamente.Elfindel
tagLI(</LI>)puedeser,ynormalmenteloes,omitidoyaqueesclaroparaelnavegadorqueen
dondeencuentreotrotag<LI>significaquecomienzaotroelemento.

ListaOrdenadas
Laslistasordenadassediferenciadelasanterioresenquecadaelementodelalistaposeeunaposicin
(numricaoalfabtica),osea,identificarancomounasecuenciadepasos.Eltagqueseutilizapara
estaslistaseseltag<ol>...</ol>yparaloselementoseltag<li>(mismocasoqueconlaslistas
desordenadas).EltagoltambinposeeunparmetroTYPEquepermitedeterminareltipode
numeracin.Entrelosposiblesexisten:

CarreraLinux2008ProgramacionPHP73
Valor

Numeracin

Ejemplo

AlfabticaMayscula

A,B,C,D...

AlfabticaMinscula

a,b,c,d...

1(defecto) NmerosArbigos

1,2,3,4...

NmerosRomanosMayscula

I,II,III,IV...

NmerosRomanosMinsculas i,ii,iii,iv...

Frames
Hastaelmomentotodaslaspginasquegeneramosocupabantodalaventana.Sisedeseadividirla
ventaenpartesdeformaquepodamoscargarvariaspginasdistintasdentrodelamismaventana,ser
necesarioutilizarframes.Unframeessimplementeun"porcin"deunaventana.Parautilizarframes
esnecesariocrearunHTMLquecontengasolamenteladefinicindelosframesyluegootrohtmlpor
cadaframequeseutilice.
Paracrearunframeseutilizaeltag<FRAMESET>...</FRAMESET>.EstagREEMPLAZAaltag
BODY,porlotanto,eltagBODYnoestarpresente.UnFRAMESETmepermitedividirlaventanaen
filasoencolumnas.SiluegosequieredividirmslapginasepuedenanidarFRAMESETs.Estetag
llevarunparmetroCOLS(columnas)ounROWS(filas),peronoambos.Cadaunodeellosdividirala
ventanaenfilasoencolumnas.Lasdivisionessepuedenespecificarenpixeles(ej.ROWS=100,300)
oenporcentajes(ej.ROWS=40%,60%).Aligualqueconlastablassepuedeutilizarunasterisco(*)
paraaquellosvaloresquenodeseemosespecificaryquequedarnlibradosaltamaodisponible(ej.
COLS=50,*).
EltagFRAMEeselqueseutilizaparaespecificarquepginascargarencadaframeset.Estetagtiene
tresopcionesbsicas:

SRC:especificaquepginasevaacargar
NAME:eselnombrequetendrelframe.Estoesutilizadoporloslinksquequierandesplegar
elcontenidodeunapginaenunframedistintoalqueseencuentran.
SCROLLING:puedeserYES(siempreexistirnlasbarrasdedesplazamiento),NO(nunca
existirnlasbarrasdedesplazamiento,aunsielcontenidonoentraenlaventana),onada
(aparecernlasbarrassolosisonnecesarias).

VeamoscomoseraelHTMLprincipaldeunapginadenoticiasqueestedivididaentrescolumnas,en
dondelaprimeratendrunconjuntodeopcionesdelsitio(ocuparel15%delaventana),lacolumna
deladerechatendrlosencabezadosdenoticiasdeotrossitios(ocuparun15%delaventana),yla
columnacentraltendrlasnoticiasdelsitio(ocuparloquequededelaventana).
ElHTMLsera:
<HTML>
<HEAD>

CarreraLinux2008ProgramacionPHP74
<TITLE>Muchos Frames</TITLE>
</HEAD>
<FRAMESET COLS=15%,*,15%>
<FRAME SRC=opciones.html SCROLLING=NO>
<FRAME SRC=cgi-bin/noticias.pl SCROLLING=NO NAME=Central>
<FRAME SRC=cgi-bin/noticias_ajenas.pl SCROLLING=NO NAME=Otros>
</FRAMESET>
</HTML>

Formularios
ElHTMLnosolamenteproporcionautilidadesparadarleformatoalasalidasinoquenosproveede
algunoselementosparapoderinteractuardeformamsavanzadaconelusuario.Estoscomponentes
sonlabaseparapodercrearCGIs.Losformulariosnospermitirnponerbotones,cajasdetexto,etc,en
nuestraspginasparaqueelusuariopuedaproveerinformacinmscompletaypoderhacerverdaderas
pginasdinmicas.
SibienestoespartedelaprogramacindeCGIs(discutidaenlaprximaclase)diremosquetodolo
queseencuentreenunformularioytengaasignadounnombre,podrserrecuperadoporelprograma
queloreciba.Cadaformulariotendrtambin,unprogramaasociadoparaprocesarlo.Dentrodeuna
mismapginasepuedentenervariosformularios(aunquenosepuedenanidar)yloscomponentesque
estenenunformularionosevernenlosdems.
Unformularioquedadefinidoporlostags<FORM>y</FORM>.EltagFORMnotieneuna
representacingrfica,sinoquesimplementeagrupaatodosloscomponentesqueluegoagreguemos
enel.
EntrelasopcionesquetieneFORMpodemosencontrar:

ACTION:aquseespecificaaqueprograma(scripts)sedebellamarcuandosesubeel
formulario(porejemplo,ACTION=http://www.misitio.com/cgibin/vender.pl)
METHOD:Determinaconquemtodosesubiranlosdatosdelformulario.Elmtodopuede
serGEToPOST.
SielmtodoesGETlosvaloresviajarnatravsdelaURL(servisiblealusuario)ytienela
desventajadequeeltamaodelaURLeslimitadoypuedenllegaraperdersepartedelosdatos
siestossonmuygrandes.
SiesPOSTlosvaloressepasaronporotraconexinalservidor.LaventajadelPOSTesqueno
seestalimitadoconeltamao,yladesventajaesquese"mslento"(sehaceotraconexin).
NAME:Nombrequetieneelformulario.

Ejemplo:
<FORM ACTION=cgi-bin/procesar.pl METHOD=POST>
</FORM>

CarreraLinux2008ProgramacionPHP75

EltagINPUT
EltagINPUTeselutilizadoparaingresardatos.Estetagpermitecrearcajasdetexto,cajasde
contrasea,botones,checkbox,opciones,botonesdeimgenesycamposescondidos.
Todasestasposibilidadestienealgoencomn:todastienenunnombrequelasidentificaytienenun
valorasociado.EstasopcionessernNAMEyVALUErespectivamente.
EltagINPUTtendrtambinunaopcin,TYPE,quedeterminardecualdetodosloscomponentes
queremosusar.
SiTYPE=TEXTentoncessecrearunacajadetexto.SilaopcinVALUEestaespecificada,dichovalor
serelquecontengalacajapordefecto.EltipoTEXTtienedosopcionesms:SIZEquedeterminael
anchodelacajadetexto(cuantoscaracteressevern)yMAXLENGTHquedeterminacuantoscaracteres
admitircomomximo.
SiTYPE=PASSWORDserasimilaraTEXTperocuandoseescribedentrodeesacajadetextolos
caracteresaparecerncomoasteriscos(*).
SiTYPE=SUBMITentoncessecrearunbotnquepermitesubirelformularioparaserprocesado.El
valorquetengalaopcinVALUEsereltextoqueaparecerdibujadosobreelbotn.
SiTYPE=IMAGEentoncessecrearunbotnquefuncionaigualqueSUBMITperoconladiferencia
queesteserunaimgen.Paraello,seposeeunaopcinextra,SRC,quedeterminardesdedondese
obtendr(laURL)laimgenquesedeseamostrar.
SiTYPE=HIDDENentoncessecrearuncampoescondido.Estetipodecampoesespecialmentetil
paraprogramarCGIs,enparticularparapasarvaloresentredistintosformularios.
SiTYPE=CHECKBOXentoncessecrearnlasclsicascasillasparaseleccionar.Enestecasoelvalor
quetengalaopcinVALUEserlaquesemuestrealladodelrectngulodeseleccin.Sisedeseaque
pordefectolaopcinaparezcamarcadasedebeagregarlaopcinCHECKED.
SiTYPE=RADIOentoncessecrearnlaseleccindeopcionesunitaria.Esdecir,elnavegadoragrupar
atodosaquelloscomponentesdetipoRADIOquetengaelmismonombre,ysolopermitirqueseelija
unoysolounodeellos.AligualqueconlosCHECKBOXelvalorquetengalaopcinVALUEserel
textoquesemuestrealladodelcirculodeseleccin.Sisedeseaquepordefectolaopcinaparezca
marcadasedebeagregarlaopcinCHECKED.

EltagTEXTAREA
Estetagpermitecrearcuadrosdetextobidimensionales.AdiferenciadelosINPUT TYPE=TEXTlos
TEXTAREApermiteningresarvariaslneasdetexto.Cadalneaestardelimitadaporun\r\n(para
cuandoseprocesaelformulario).Estetagtiene,porsupuesto,laopcinNAMEparaseridentificado
luegodesdeelCGI.TambinposeelaopcionesCOLSquedeterminalacantidaddecolumnasque
ocuparelcuadro,yROWSquedeterminalacantidaddefilasqueocuparelcuadro(visualmente).
Estetag,ytambinadiferenciadeltagINPUT,tieneuntagquelocierra(</TEXTAREA>
obviamente).Todoloqueseencuentredentrodeestosdostagssetomarcomovalorpordefecto.Se
debeaclararquesolosepermitetextoplanodentrodeestosdostags,yaqueloqueseescribacomo

CarreraLinux2008ProgramacionPHP76
HTMLserignoradoypasadodirectamentealcuadrodetexto.

EltagSELECT
Estetagseutilizaparacreartantolistascomocombobox(listasdesplegables).SELECTcrearun
cuadrocontodaslasopcionesqueseleotorguenypermitirelegirunaomsdeellas.Lasopcionesse
determinanmedianteeltag<OPTION>...</OPTION>.Loqueseencuentredentrodeestostags
serloqueveraelusuarioporpantalla(ypordefectoelvalorqueseobtendrcuandosesubeel
formulario).SisedeseadarotrovaloracadaopcinsepuedeutilizarlaopcinVALUEdentrodeltag
OPTIONyasignarleelvalorquesedesee.
TambinexistelaopcinSELECTEDparaquepordefecto,esaopcinaparezcaseleccionada.
EltagSELECTtambintienealgunasopciones.PrimerotienelaopcinNAMEaligualquetodoslos
demscomponentes.PoseetambienlaopcinMULTIPLElacualledicealnavegadorsedebeono
permitirqueseelijanmsdeunaopcin.TambinposeelaopcinSIZEquedeterminalacantidadde
elementosqueseveranalmismotiempoenpantalla.Silacantidaddeelementosesmayorquela
especificadaenSIZE,entoncesaparecerunabarradedesplazamientoparapodermoverseyelegir
cualquierelemento.
SinoseespecificolaopcinMULTIPLEySIZE=1entonceslalistaseconvierteenunalista
desplegable.

Ejercicios
1.
2.
3.
4.
5.

CualesladiferenciaentrelosmetodosGETyPOST?
QueformasdeentradatieneelusuariomedianteeltagINPUT?
CualesladiferenciaentreeltagOLyUL?
Paraquesirvenlosframes?
Comoarmariaunapaginaqueestedivididaen5partes,demodoquequeden3paginasenla
primerfilay2enlasegunda?

Clase14Programacinweb
UnprogramaenPHP,dentrodeunapginaweb,sepuedepensarcomounconjuntodeseccionesde
cdigoPHPintroducidasdentrodeunarchivoHTML.
Entonces,definiremosunbloquedePHP,comolohemoshechoalinicio,delasiguienteforma:
<?php
# Codigo en PHP
?>

Endonde<?phpabreelbloquedecdigoy?>cierradichobloque.Todoloqueseencuentredentro
deestebloquedecdigoseejecutarcomocdigoPHPylasalida(osea,todoloqueseescribaenla
salidaestndar)resultanteiralnavegador.ParaquenuestroprogramagenereHTMLseutilizarla
funcinecho.

CarreraLinux2008ProgramacionPHP77
Porejemplo,sicreamoselarchivohola.php:
<HTML>
<HEAD>
<TITLE>Saludos!</TITLE>
</HEAD>
<BODY>
<?php
echo "Hola Mundo";
?>
</BODY>
</HTML>

GeneraremosunapginawebenPHPqueescribeHolaMundo.
Veamosunejemplounpocomscomplejo:
<HTML>
<HEAD>
<TITLE>Ejemplo</TITLE>
</HEAD>
<BODY>
<?php
echo "La suma de antes era: $x";
while($x < 10) {
$x = $x + 1;
$s = $s + $x;
echo "$x dot<br>";
}
echo "La suma es: $s<br>";
?>
</BODY>
</HTML>

Cuandoejecutemosestapgina,porprimeravez,lasvariables$xy$snoexistirn.Cuandoempiezael
ciclowhileambasvariablesseirnincrementandohastallegara$x=9y$s=55.Estainformacinse
verenelnavegador:
La suma de antes era:
1 dot
2 dot
3 dot
4 dot
5 dot
6 dot
7 dot
8 dot
9 dot
10 dot
La suma es: 55

CarreraLinux2008ProgramacionPHP78
Comosepodraapreciar,elprimerechonomuestraningnvalorpara$s,queesloqueintuitivamente
unosupondrayaqueeslaprimeravezqueseejecuta.Sinembargo,cuandovolvemosaejecutarla
pgina,volveraproducirlamismasalida.Estosedebealhechoquenosecompartenestados
(variables)entredosejecucionesdistintas.Cuandoseejecutaporsegundavez,todaslasvariablesque
seutilizaronantes,noexistenhastaquesehayanutilizado.
Estonoquieredecirqueesimposiblecomunicarseentredospginasyaqueestoesposibleutilizando
HTML(linksyformularios)omedianteelprotocoloHTTP(cookies).

Pasodeinformacinentrepginas
Comohemosdichoanteriormentedosejecucionesdeunamismapginanocompartensusvariables.
Sinembargo,siesposiblepasarinformacinentredospginascualquiera(olamismaparaelcasoque
sea).CuandosetrabajasobrelaWebexistendosmtodos:GET(links)yPOST(formularios).
CuandoseutilizanlinksesposiblepasarinformacinmediantelaURLquellevan.Unlinkcomn
sera:
<A HREF=index.html>Volver a la pagina principal</A>

Estelink,simplementeapuntaalindex.html.Ahora,supongamosqueposeemosunlinkquenosllevaa
losproximos200resultados(apartirdelresultado400)deunabsqueda:
<A HREF=busqueda.php?desde=400&cantidad=200&criterio=crucis>Pagina siguiente</A>

EnestaoportunidaderanecesariopasarleanuestroCGIciertainformacinparaquefuncionasecomo
unoesperara.Cuandoseejecutenoserigualelresultadosiseempiezaamostrardesdeelresultado
100quedesdeelresultado5000.Elscriptprocesarlabsquedadeigualformaenamboscasospero
mostrarcosasdistintas.
ParapasardatosporlaURLesnecesariosepararelarchivodelosparmetrosusandoelsigno?.Luego
cadaunodelosparametrostendrunnombre(fijoparapoderencontrarlodespues)yunvalorasociado
(queesloquepersonalizalaejecucin).Losdistintosparmetrosseseparanluegoporampersands(&).
DesdePHPparaobtenerestosvaloresexisteelarreglo$_GET.Enestearreglo,lasclavessonlos
nombresdelosparametros.$_GETesunavariablecomolasdemasqueseutilizanenPHP.Estoquiere
decir,quecuandoseterminolaejecucindelCGI,todosucontenidotambinsepierdejuntocontodas
lasvariables.EstearreglolocargarPHPautomticamenteconlaejecucindecadaCGI.Sienuna
ejecucindadanosepasoningnparmetroporlaURL,entonces$_GETestarcompletamentevaco.
Sisepasounaopcin,entonces$_GETtendrunanicaentrada.
Veamosesquematicamentecomoseraelejemploanterior:
<?php
# Si hay algo para buscar
if(isset($_GET["criterio"])) {
# Si no se especifico desde que resultado (probablemente la
# primera ejecucion), comenzamos desde 0

CarreraLinux2008ProgramacionPHP79
if(!isset($_GET["desde"])) {
$desde = 0;
} else {
$desde = $_GET["desde"];
}
# Si no se especifico de a cuantos mostrar, usamos un valor por defecto
if(!isset($_GET["cantidad"])) {
$cantidad = 200;
} else {
$cantidad = $_GET["cantidad"];
}
# Esta funcion seria la que ejecutase la consulta y la mostrara en
# pantalla. Para este ejemplo no es relevamente como lo hace, sino
# que lo haga
mostrar_resultados($_GET["criterio"], $desde, $cantidad);
# Crea el link a la proxima pagina
echo "<A HREF=busqueda.php?desde=", $desde + $cantidad,
"&cantidad=", $cantidad, "&criterio=", $_GETS["criterio"],
">Pagina Siguiente</A>";
?>

Sepuedeobservarqueellinkdelaprximapginairaumentandosucampodesdeamedidaquese
vanpasandolaspginas,yaquesiempreselepasaelvalorquetenia($desde)msunincremento
($cantidad).Losotrosdoscampospermanencenfijos(cantidadycriterio).

Formularios
Cuandosenecesitaqueelusuariointeractuedemaneramscontundente(lease,tipeealgo
basicamente)debemosrecurriralosformularios.
Unformulario,comolovistoenlaguiadeHTML,esunconjuntodecontrolesquepermitenalusuario
ingresardatos,seleccionardesdeuncombo,elegiruncheckbox,etc.Sinembargolosformularios
tienenotrapropiedad:puedenserenviados.Estoquieredecirquetodalainformaciningresadapodr
serutilizadaluego(Deserenviada)porunCGI.
Laformaenquesepasanlosdatosessimilaraladeloslinks.Enelcasodelosformularioscadauno
deloscomponentestendrunnombre(Fijo)quetendrunvalorasociado(loqueingresoelusuario).
Luegotodoesteconjuntodeclaves,valoresestarndisponiblesdesdeelarreglo$_POST.
Laformadeutilizar$_POSTestotalmenteigualaladeusar$_GET.Ladiferenciaresideenelorigen
delosdatos(unosvienenporlaURL,generadospornuestroprogramaylossegundossonloque
ingresoelusuario).
Veamosunejemplodeunprogramaquenosdicesiunnmeroingresadoesonoespar:
<HTML>
<HEAD>
<TITLE>Par o no par, esa es la cuestion</TITLE>

CarreraLinux2008ProgramacionPHP80
</HEAD>
<BODY>
<FORM METHOD=POST>
Numero:<INPUT TYPE=TEXT NAME=nro VALUE=<?php echo $_POST[nro]; ?>
SIZE=5>
<INPUT TYPE=SUBMIT VALUE=Controlar>
<P>
<?php
# No se ingreso nada
if(!isset($_POST["nro"])) {
echo "No se ha ingresado ningun valor todavia";
# Si es par el modulo al dividirlo por 2 da 0
} elseif($_POST["nro"] % 2 == 0) {
echo "<H1>El numero es PAR!</H1>";
# Si se ingreso y no es par, entonces sera impar
} else {
echo "<H1>El numero es IMPAR!</H1>";
}
?>
</BODY>
</HTML>

Recordemosquealigualque$_GET,$_POSTsereliminadocuandoseterminedeejecutarel
programaysercargadonuevamentecuandosevuelvaacorrerelprograma.Estaclaroque$_POST
sercargadosolamenteconlosvaloresingresadosenelmomentoenqueseenvioelformulario.
Elprogramaesbastantelineal,ysunicafuncinesinformarsobrelostresposiblesestados:Nose
ingresonada,oeslaprimeravezqueseejecuta($_POST["nro"]nocontieneningnvalor);Se
ingresounnumeroqueespar(entonces$_POST["nro"]contieneunnmeropar);oseingresoun
nmeroimpar(entonces$_POST["nro"]contieneunnmeroimpar).

DiferenciasentreelmtodoGETyelmtodoPOST
Sibienambosmtodosseutilizanbsicamenteigualposeenalgunasdiferenciasentreellos.
Unadeellasyalamencionames,yeselorigendesdedondevienenlosdatos.EnelmtodoGET
vendranjuntoconlaURL,encambio,enelmetodoPOSTvieneporotraconexin.
Antesdecontinuaraclararemosquelasdiferenciastcnicasmencionadasaqunoafectanalaformade
programar,sinoquesedebenutilizarparaentenderelprocesoysabercuandoconvieneenviardatospor
GETycuandoporPOST.
LosdatosdelGET,aliratravesdelaURL,viajanalservidorWebjuntoconelpedidodelapgina.El
servidorinterpretarlaURL,ladividiryselaenviaranuestroprograma.Encambio,cunadolos
datossonenviadosusandoelmetodoPOST,segenerandosconexiones.Laprimeraseralacomnenla
quesepidelapginanecesaria.Aesta,lesigueotraconexinporlacualseenviarnlosdatosdel
POST.Luego,elservidorseencargardejuntarlosdatosdelPOSTparaenvirselosanuestro
programa.
ElmtodoPOSTnospermitirpasarunamayortamaodedatos.ElmtodoGET,alestarlimitadopor
laURL,noaceptaraproximadamentemsde512bytes.EncambioeltamaodeunPOSTesdelorden

CarreraLinux2008ProgramacionPHP81
delosmegas.

Ejercicios
1. Comoeselcicloparainteractuarconunusuariomedianteformularios?Comoserecuperan
desdeunapaginaweblosvaloresingresadosporelususario?
2. Hacerunapaginaquelistetodoslosusuariosdelsistema(usandodebaseelarchivo
/etc/passwd).Cadausuariodebeserunlinkaotrapagina,lacualdeberamostrartodala
informaciondisponibledelmismo(usandodebaseelmismoarchivo).
AmboslistadosdeberanestardentrodetablasHTML.
3. Hacerunapaginaquepermitaalusuarioingresarunnumero.Luegolapaginairaindicandosiel
numeroesmenor,mayoroigualaunoelegidoalazar.Dichonumeroalazardeberaserel
mismodurantetodoeljuego(sedeberairpasandoentrelasdiferentespaginasenuntagINPUT
deltipoHIDDEN).
4. Modificarelprogramaanteriorparaqueeljuegosereiniciesolocuandoelusuariohalla
adivinadoelnumero.Tambiensedebeagregarunbotonparareiniciareljuegomanualmente.
Agregartambienuncontadorparaqueindiqueencuantosintentosseadivinoelnumero.
5. SerequierecrearunMessageBoard(librodevisitas)paraunsitioweb.Unmessageboard(de
aquienadelanteMB)consistesimplementeenpermitiralusuariodejarmensajesenelsitioy
quetodospuedanverestosmensajes(losmensajesnotienenrelacionentreellos).
PorrestricciondelsitionotodoslosusuariospuedenescribirenelMB.Soloaquellosqueesten
registradoslopodranhacer.
Sedeberacreaunaseriedescriptsparaagregarusuarios(yversuinformacion),ingresar
mensajes,yverlosmensajesingresados.Pararegistraraunusuarioseledebepedircierta
informacion:
*nickname:aliasconelqueseveraalusuario
*nombreyapellido:realesdelusuario
*email:direcciondecorreoelectronico
*contrasea:sucontrasea
Unavezdadodealtaalusuarioestepodraingresarmensajes.Cuandoseingresaunmensajese
debepermitiringresarelusuario,lacontraseayelmensajepropiamentedicho.
Losusuarioseranlistadosdentrodeunalistadesplegable(oseaSELECTnomultiplecon
SIZE=1),ylacontraseaenunacajadecontraseas(PASSWORD).Elmensaje,portenerun
tamaoconsiderablementelargo,debeseringresadomedianteunTEXTAREA.Tambiensera
registradalafechayhoraenqueserealizolatransaccion.
Elusuariosolopodraagregarelmensajesilacontraseaingresadaescorrecta.
Losmensajesselistaranunodebajodelotroconelsiguienteformato:
Fecha y hora
Nick_del_usuario (email) escribio:
Mensaje

CarreraLinux2008ProgramacionPHP82
Donde"Fechayhora"eslafechayhoraenquesegeneroelmensaje,"Nick_del_usuario"esun
linkaalinformaciondelusuario,"email"esunlinkalemail(osea,un
mailto:usuario@serv.com)y"Mensaje"eselmensajeingresadoporelusuario.Cabedestacar
queelMensajedebeestarseparadoporlineasdelamismaformaenquelaingresoelusuario.
Comoelsitioseramuyvisitadosepidequesemuestrendea5mensajesporvezordenadosdel
masrecientealmasantiguo.Sedebeproveerentonces,enlaparteinferiordelapagina,links
parairhaciaatrasyhaciaadelante.

Clase15CookiesyManejodeSesiones
Lascookiessonunaformadepasarinformacinentreelservidoryelclientedeformatalquenose
pierdaentredistintospedidosdepginas.Estoseutilizayaquecadavezqueelclientepideunapgina
secreaunaconexinnuevaindependientedelaspginasqueyahapedido,porloquenospermiteir
pasandoinformacinentreformularios.Lascookiestienenlaventajaqueseenvianunasolavezyesta
sesiguereenviandoatodaslaspginasquesevisitenposteriormentesinnecesidaddeagregarcdigo
extra(anoserquesedeseemodificarelvalordelamisma).
LascookiesdebenserenviadasjuntoconlacabeceraHTTPderespuestaquegeneraelservidorcuando
unclientepideunapgina.Poresolascookiesdebenserenviadasantesdequehayacualquiertipode
salidaenHTML(antesdeltag<HTML>yantesdequehayaunsoloespacioenblanco).
Paraenviarunacookiedisponemosdelafuncionsetcookie:
setcookie($nombre, $valor, $expira, $path, $dominio, $seguro);

Lasnicasopcionesquesonobligatoriasson$nombrey$valor.$nombredebesernicoyaque
nopuedenexistirdoscookiesconelmismonombre.
Laopcin$expiradeterminaeltiempoquedurar(ensegundos)lacookie.Luegodequepaseese
tiemposedebergenerarunanuevacookie.Paradarleuntiempotilizaremoslafuncintime()que
nosdevuelvelacantidaddesegundosalafechadehoyyaesolesumaremoseltiempoquedeseemos
quedure.Porejemplo,time() + 3600harquelacookieexpiredentrodeunahora.
Laopcin$dominioespecificaundominioalcualunicamenteleservlidoalnavegadordevolverla
cookie.Siseespecificoeldominiowww.misitio.comsoloserenviadalacookiesilapginapedida
perteneceaesedominio(sinotodoslossitiospodrianverinformacinconfidencial).
Laopcin$pathessimilaradomain.Soloenviarlacookiesilapginapedidaperteneceaese
directorio(osubdirectorio).
Finalmentesilaopcin$seguroestaactivadasoloseenviarlacookiesielservidoryelcliente
soportanelusodeencriptacin(SSLSecureSocketLayer).
Pararecuperarelvalordeunacookieexisteunarreglollamado_COOKIE.Estearregloposeeuna
entradaparacadacookiequesehallaenviado,endondelaclaveserelnombredelacookieyelvalor
serelvalorquetengalacookie.
Elsiguienteejemploconstade4archivos:

CarreraLinux2008ProgramacionPHP83
Archivo:menues.php
<?php
$menues = array("Configurar" => "configurar.php", "Principal" => "principal.php",
"No Principal" => "no_principal.php");
function mostrar_menu($menu_actual, $menues) {
echo "< P ALIGN=center>";
foreach($menues as $nombre => $link) {
echo $separador;
$separador = " - ";
if($menu_actual == $nombre) {
echo "<B>$nombre</B>";
} else {
echo "<A HREF=$link>$nombre</A>";
}
}
echo "</P>";
echo "<hr>"; # Genera una linea divisora
}
function crear_lista($nombre, $opciones, $defecto) {
echo "<SELECT NAME=$nombre SIZE=1>";
foreach($opciones as $texto => $valor) {
$seleccionado = "";
if($defecto == $valor) {
$seleccionado = "SELECTED";
}
echo "<OPTION VALUE=$valor $seleccionado>$texto</OPTION>";
}
echo "</SELECT>";
}
?>

Archivo:configurar.php
<?php
require_once("menues.php");
$colores = array("Roj izo" => "#FF9999", "Verd oso" => "#99FF99", "Azul ado" =>
"#9999FF");
if(isset($_COOKIE["color"])) {
$color_elegido = $_COOKIE["color"];
}
if(isset($_POST["actualizar"])) {
setcookie("color", $_POST["color"]);
$color_elegido = $_POST["color"];
}
?>

CarreraLinux2008ProgramacionPHP84
<HTML>
<HEAD>
<TITLE>Configuracion de color</TITLE>
</HEAD>
<BODY BGCOLOR=<?php echo $color_elegido;?>>
<?php
mostrar_menu("Configurar", $menues);
?>
<FORM METHOD=POST>
Eliga un color:
<?php
crear_lista("color", $colores, $color_elegido);
?>
<br>
<INPUT TYPE=SUBMIT NAME=actualizar VALUE=Actualizar>
</FORM>
</BODY>
</HTML>

Archivo:principal.php
<?php
require_once("menues.php");
$colores = array("Roj izo" => "#FF9999", "Verd oso" => "#99FF99", "Azul ado" =>
"#9999FF");
if(isset($_COOKIE["color"])) {
$color_elegido = $_COOKIE["color"];
}
if(isset($_POST["actualizar"])) {
setcookie("color", $_POST["color"]);
$color_elegido = $_POST["color"];
}
?>
<HTML>
<HEAD>
<TITLE>Configuracion de color</TITLE>
</HEAD>
<BODY BGCOLOR=<?php echo $color_elegido;?>>
<?php
mostrar_menu("Configurar", $menues);
?>
<FORM METHOD=POST>
Eliga un color:
<?php
crear_lista("color", $colores, $color_elegido);
?>
<br>
<INPUT TYPE=SUBMIT NAME=actualizar VALUE=Actualizar>
</FORM>
</BODY>

CarreraLinux2008ProgramacionPHP85
</HTML>

Archivo:no_principal.php
<?php
require_once("menues.php");
$color_elegido = $_COOKIE["color"];
?>
<HTML>
<HEAD>
<TITLE>Pagina Principal</TITLE>
</HEAD>
<BODY BGCOLOR=<?php echo $color_elegido;?>>
<?php
mostrar_menu("Principal", $menues);
?>
<H1 align=center>ESTA ES LA PAGINA PRINCIPAL!</H1>
La moraleja del dia es:<br><br>
<i>El problema no es que los programas tenga errores,
sino que los errores tenga programas.
</i>
</BODY>
</HTML>

Laideadeesteejemploesmostrarquelascookiessesiguenenviandosolassinnecesidaddeagregar
nada.Paraellodisponemosde3pginas:configurar.php,principal.phpyno_principal.php.
Enlaprimeradeellasconfiguraremosquecolordefondoqueremosver.Luegosipasamosacualquiera
delasotrasdosveremosqueestandelcolorqueseteamossinnecesidaddeagregarnada.
Primeroquenadaharemosunaaclaracinglobal.Elarchivomenues.phptienedefinidounarreglocon
todoslosmenuesqueexistanyunafuncinlacualmuestraelmenuactual.Deestaformaessencillo
agregarmsopcionesalmenu,yaquesoloharafaltaagregarunaentradaendichoarregloybastar
paraquesereflejeentodaslaspginas.Lafuncinmostrar_menuquedacomoejercicio
interpretarlayentenderla.
Lafuncincrear_listageneralostagdeHTMLnecesariosparacrearuncombocontodaslas
opcionesqueselepasenatravezdelarreglo$opciones.
Elarchivoconfigurar.phpeselquealmacenatodalamagiadeestesistema.Laideageneralesteneruna
cookiequesellamecoloryquetengacomovalorelcolorquesequieremostrar(enelformatoqueusa
HTML).SilacookienoestaseteadaquedareltagBGCOLORdeBODYvaco,queporlogeneral,los
navegadoreslointerpretancomoblanco.
ParacomenzarsaltearemoslosprimerosdosifsyanalizaremoselHTMLgenerado.
EltagBODYposeelaopcinBGCOLOR(paradarleelcolordefondo)seteadaconelvalordeuna
variable(color_elegido)queserlaquecontengaelcolor.Luegoseejecutarlafuncin
mostrar_menuparamostrarelmenudelsistemaconlaopcinactualseleccionada(Configurar).
LuegosecreaunformularioyuntagSELECT(conlafuncincrear_lista)parapoderelegirentre
todosloscoloresquehaydefinidos.
Ahoraanalizemoselsegundoif.Esteseejecutarcuandosepresionesobreelbotnactualizar.Su

CarreraLinux2008ProgramacionPHP86
tareaserladecrearlacookiesinoexisteymodificarlasiexiste.Simplementehacefaltallamarala
funcinsetcookieparahaceresto.Elprimerparmetroeselnombredelacookie(colorennuestro
ejemplo)yelsegundoelvalor(elquefueseleccionadoenelSELECT).Estafuncinseencargarde
crearlacookiesinoexisteodemodificarlasiyaexiste.Porlotanto,cuandoseenvieestapgina,leira
alnavegadorlarespuestajuntoconunacookiequesereenviarenlasproximaspaginasquepida.
Comoacabamosdeseleccionaruncolor,lecambiamoselvaloralavariablecolor_elegidoalque
seacabadeelegirparaqueenestamismaejecucin(quenorecibioningunacookie)seveaelcolor
elegido.
Elsegundoifesparasetearelcolorcuandoseaccedealapginayyaseestaenviandolacookie.Si
yahabiamosseteadoelcolorynavegamosporlasdemspginas,cuandovolvamosaqusernecesario
(aligualqueenlasdemspginas)setearelcolorbasandoseenlacookieexistente.Poreso,silacookie
existeseusaesecolor.
Lasotrasdospginassonsimilares.Simplementetomanelvalordelacookieylomandanalaopcin
BGCOLORdirectamente.Silacookienollegaaexistirsimplementequedarvacoelcoloryel
navegadormostrarelfondoenblanco.ElrestodelapginaesHTMLpuroparacompletarconalgo
interesanteenelejemplo.
Veamosotroejemplo.Esteejemplosirveparacontarcuantasvecessepresionelbotonderefreshen
unapgina.
Archivo:cuenta_refresh.php
<?php
if(isset($_COOKIE["cont"])) {
$contador = $_COOKIE["cont"] + 1;
} else {
$contador = 0;
}
setcookie("cont", $contador);
?>
<HTML>
<HEAD>
<TITLE>Cuenta refresh</TITLE>
</HEAD>
<BODY>
<h1>Contador de refreshs</h1>
Se apretaron <b><?php echo $contador; ?></b> veces el boton de refresh<br>
Presione el boton de refresh para incrementar el contador
</BODY>
</HTML>

Lamagiadeesteejemploresideenelif.Esteifdeterminasiexisteonolacookiellamadacont.Sino
existe(recinsecargalapgina)inicializaelcontadoren0ygeneraunacookieconvalor0.Sillegaa
existirlesuma1alvaloranteriorycrear(omodificamejordicho)unacookieconigualnombrepero
conunvalor1msgrande.
Cadavezqueserecarguelapginalacookieseenviaryseincrementarhastaelinfinitoohastaque
alguienseaburradeapretarrefresh.

CarreraLinux2008ProgramacionPHP87

Sesiones
Alutilizarcookiestodalainformacinquenosinteresaviajaconstantementeentreelclienteyel
servidor.Concadaaccesodepginatodalainformacintienequeviajardosveces.Esto,ademsde
pocoeficiente,hacequeseamsprobablequealguienmodifiqueesainformacinintencionalmente,
alterandoelnormalfuncionamientodelsitio.
Paraelloexistenlassesiones.Unasesinesunaconjuntodevariablesquepermanencenenelservidor
ysoloviajadelclientealservidor(yviceversa)unidentificadordelamisma.Deestaforma,esposible
tenerparacadaclientelainformacinpertinente(distintaparacadausuario)enformalocalysoloviaja
elmnimodeinformacinnecesaria.Utilizandosesionesresultamssencilloidentificarqueusuario
estaaccediendoacadapaginayaquecadausuariotendrasupropiasesin.

Iniciodeunasesin
ParacrearoutilizarunasesinenPHPutilizaremoslafuncinsession_start.Estafuncinno
llevaningnparmetroysutareaescrearunanuevasesinoutilizarunaqueyaexista.Hayque
destacarquelassesionesdebeninicializarse,aligualqueconlascookies,antesdequehallacualquier
tipodesalidaHTML.
Cuandotenemosunasesinpodemoscrearvariablesdesesiones.Estasvariablesnoseperderncuando
setermineelscript,sinoquequedarnalmacenadasenelservidorparalaprximavezquesecorrael
scriptconesamismasesion(paraelmismousuario).
Parainicializarlasesinsolohayqueejecutar:
session_start();

Cuandosegeneralasesinselecreaunidentificadornico,elcualpuedeserobtenidomediantela
funcinsession_id.

Variablesdesesin
Luegotenemosdosformasdecrearvariablesdesesiones.Laprimeraesutilizandolafuncin
session_register.EstallevacomoparmetroelnombredelavariablePHPqueseguardar.Por
ejemplo:
session_register('persona');
$persona = "Mr Blue Sky";

Aqulavariable$persona(noimportacuandosellamaasession_register,puedeseranteso
despuesdeusarlavariable)estardisponibleenlasesin.Tambinesposibleguardararreglosdeigual
forma:
session_register('personas');
$persona = array("Mr Blue Sky", "Mister IO", "Vespuscio");

CarreraLinux2008ProgramacionPHP88
Lasegundaformadeguardarvariablesdesesinesutilizandoelarreglo_SESSION.Esteesun
arregloquecreaautomaticamentePHP(aligualque_POSTy_GET)elcualcontienetodaslas
variablesdesesincreadasenelmomentodelaejecucin.Silomodificamos,loscambiossevern
reflejadosenlaprximaejecucin.Estaformaeslarecomendadayaqueeslamsclaraylams
segura.Parahacerelmismoejemplodeantes:
$_SESSION['persona'] = "Mr Blue Sky";
$_SESSION['personas'] = array("Mr Blue Sky", "Mister IO", "Vespuscio");

Lasvariablesdesesinsepodranacceder,entonces,desdeelmismoarreglo_SESSION.Sienotro
scriptqueremosmostrartodaslaspersonasquetenemoscargadashastaelmomentosoloharafalta:
foreach($_SESSION['personas'] as $nombre) {
echo "$nombre<br>";
}

yaque$_SESSION['personas']esunarreglovlidoqueyafuecargado.

Destruccindelasesin
Paraterminarconlasesindebemosllamaralafuncinsession_destroy(nollevaargumentos).
Estafuncindebeserllamadaluegodellamarasession_start,asiPHPpuedeidentificarque
sesindestruir.
Estafuncinnoeliminalacookiedelasesinqueviajaentreelclienteyelservidor,porloquehabra
queagregarunmecanismoextraparadeterminarcuandoseterminolasesin.

Controlandolasvariablesdesesin
Cuandoutilizamossesionesestilsabersiestaonocargadaunavariableenlasesin.Paraello(yuna
vezabiertalasesinconsession_start)dispondremosdelafuncinsession_is_register
lacualdndoleelnombredelavariablenosdiraverdaderoofalsosiestaonoesavariableregistrada.
Porejemplo:
if(session_is_register('persona')) {
echo "La persona esta presente<br>";
} else {
echo "La persona no ta<br>";
}

Siantesdeejecutarestecdigo,habamosejecutadoelejemploanterior,elifserverdaderosinoser
falso.

Verificandolasesin
Comonoesposibleeliminarlacookiequeutilizalasesin,siemprelasesinestarpresente.Para
sabersiunusuarioestaono"logueado"enlasesin,debemosguardarporlomenosunavariablefija

CarreraLinux2008ProgramacionPHP89
quemientraseste,lasesinservlida.Cuandoelusuariosesalgadelsistema(mediate
session_destroyoporqueseleacaboeltiempo)estavariablesseperderaynuestroscriptpodr
notarlo.
Paraello,porejemplo,guardaremosenlasesinunavariablequeledaremoselnombreID_SESION
(puedesercualquiera)yledaremoseliddelasesinactual.
Cuandoelusuarioinicialasesinejecutaremos(luegodesession_start):
$_SESSION['ID_SESSION'] = session_id();

o
session_register("ID_SESSION");
$ID_SESSION = session_id();

yaqueeslomismo.
Luegoencadascriptalcualsololosusuariosvlidospuedanacceder,habrquecontrolarporlomenos
queestavariableexista:
session_start();
if(!session_is_register("ID_SESSION")) {
echo "ERROR!!! PELIGRO!!! DANGER!!! CORRAN POR SUS VIDAS!!!";
exit(); # No ejecuta mas nada
}

Sipasoporesteif,entoncesesseguromostrarlapgina.
Veamosunejemplo:
Archivo:control_acceso.php
<?php
session_start();
if(!session_is_registered("ID_SESION")) {
include('error.html'); # Trae la pagina con el mensaje de error
exit();
# Termina la ejecucion del script
} else {
echo "<h1 align=center>Acceso Permitido</h1>";
}
?>

Archivo:login.php
<?php
require_once("funciones.php");
session_start();
mostrar_menu("LOGIN", $menues);
echo "<BODY BGCOLOR=#FFFFAA>";
if(session_is_registered("ID_SESION")) {

CarreraLinux2008ProgramacionPHP90
echo "<h1>Acceso Permitido (Cuantas veces te quieres loguear hoy?)</h1>";
} else {
$_SESSION["ID_SESION"] = session_id();
echo "<h1>Has creado una nueva sesion!</h1>";
}
echo "<h2>ID_SESION: ", $_SESSION["ID_SESION"], "</h2>";
echo "</BODY>";
echo "</HTML>";
# Para mostrar en la proxima pagina de donde viene guardamos el
# nombre de esta pagina en la sesion.
$_SESSION["pagina_anterior"] = "LOGIN";
?>

Archivo:pagina1.php
<?php
require_once("control_acceso.php");
require_once("funciones.php");
mostrar_menu("Pagina 1", $menues);
echo "<h2>ID_SESION: ", $_SESSION["ID_SESION"], "</h2>";
# Gracias a que guardamos el valor en pagina_anterior sabemos
# desde donde viene el usuario
echo "<h3>Vienes de la pagina <FONT SIZE=+2>$_SESSION[pagina_anterior]</FONT></
h3>";
# Para mostrar en la proxima pagina de donde viene guardamos el
# nombre de esta pagina en la sesion.
$_SESSION["pagina_anterior"] = "Pagina 1";
?>
<BODY BGCOLOR=#66DD44>
<u>Oido al pasar</u>:<br><br>
Todos los rios desembocan en el mar, pero el mar nunca desborda.
<i>-- Proverbio chino</i>
</BODY>
</HTML>

Archivo:pagina2.php
<?php
require_once("control_acceso.php");
require_once("funciones.php");
mostrar_menu("Pagina 2", $menues);
echo "<h2>ID_SESION: ", $_SESSION["ID_SESION"], "</h2>";
# Gracias a que guardamos el valor en pagina_anterior sabemos
# desde donde viene el usuario
echo "<h3>Vienes de la pagina <FONT SIZE=+2>$_SESSION[pagina_anterior]</FONT></
h3>";
# Para mostrar en la proxima pagina de donde viene guardamos el

CarreraLinux2008ProgramacionPHP91
# nombre de esta pagina en la sesion.
$_SESSION["pagina_anterior"] = "Pagina 1";
?>
<BODY BGCOLOR=#7777DD>
<u>Oido al pasar</u>:<br><br>
La verdad siempre resplandece al final, cuando ya se ha ido todo el mundo.
<i>-- Julio Cern</i>
</BODY>
</HTML>

Archivo:logout.php
<?php
require_once("control_acceso.php");
require_once("funciones.php");
mostrar_menu("LOGOUT", $menues);
session_destroy();
?>
<BODY BGCOLOR=#666677>
<H1 ALIGN=CENTER>Venias de la pagina <?php echo $_SESSION[pagina_anterior]; ?>
y ahora... Estas afuera...</H1>
<BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR>
<P ALIGN=RIGHT><FONT SIZE=-2>adios . . .</FONT></P>
</BODY>
</HTML>

Archivo:funciones.php
<?php
$menues = array("LOGIN" => "login.php", "Pagina 1" => "pagina1.php", "Pagina 2"
=> "pagina2.php", "LOGOUT" => "logout.php");
function mostrar_menu($menu_actual, $menues) {
echo "<P ALIGN=center>";
foreach($menues as $nombre => $link) {
echo $separador;
$separador = " - ";
if($menu_actual == $nombre) {
echo "<B>$nombre</B>";
} else {
echo "<A HREF=$link>$nombre</A>";
}
}
echo "</P>";
echo "<hr>"; # Genera una linea divisora
}
?>

Archivo:error.html
<HTML>
<HEAD>
<TITLE>Acceso denegado</TITLE>

CarreraLinux2008ProgramacionPHP92
</HEAD>
<BODY BGCOLOR=#FF9988>
<H1 ALIGN=CENTER>ACCESO DENEGADO!</H1>
Usted esta tratando de acceder a un area restriginda a la cual (ovbiamente)
usted no tiene acceso.<br>
Presione <A HREF=login.php>aqui</A> para ir a la pagina principal o vayase a
otro sitio distinto que sea mas divertido que este.
<br>
Ah, y muchas gracias por visitar nuestro sitio web!
</BODY>
</HTML>

Esteejemploconstade4pginasprincipales:login.php,pagina1.php,pagina2.phpylogout.php.
Eliniciodelsistemadebeserutilizandoelscriptlogin.php.Estescriptcreaunanuevasesinysino
existaasignaelnuevoidalavariablesdesesinID_SESION(usadaparacontrolarlosaccesos).Siya
existaesavariablesimplementeemiteunmensaje.
Esteprocesodadealtalasesin(enunsistemaquetienemuchosusuariosantesdehacerestepasose
deberiaverificarqueelusuarioyexistaylacontraseaseacorrecta).Luegosepuedeviajaralasdemas
pginas.
Laspginaspagina1.phpypagina2.phpsoncasiidnticas(salvoporlasabiduradelmensajeque
muestra)porloquediscutiremosunasoladeellas.
Lamagiaestaenquetodaslaspginasquetengaqueserrestrigindasincluyanelarchivo
control_acceso.php.EstearchivorevisasiexistelavariableID_SESION,sinoexiste,esporqueel
usuariosehadeslogueadooatratadodeaccederaunapginasinhaberpasadoporladelogin.
Encualquiercaso,lavariabledesesionID_SESIONnoestardefinidayletraerelarchivoerror.html
(conunhermosomensajedeerror)yterminarlaejecucindelscript(conlafuncinexit)paraqueno
seejecutemsnada.Silavariableexista,mostrarunmensajedemostrativo(Estemensajenosuele
estarensistemasreales).
Finalmenteelscriptlogout.phpdestruirtodaslasvariablesdesesinporloqueelusuarioestar"fuera
delsistema".Paraellosimplementeutilizalafuncinsession_destroy.
Unavezejecutadaestapginaserimposibleaccederapagina1.phpopagina2.phpoalmismo
logout.php(intentarloparaverelmensajedeerror).

Desconectandoalosusuarios
Sibienleesposiblealosusuariosdesconectarseutilizandoellogout(quedeberadarsiempremi
sistema),serabuenopoderdesconectaralosusuariossialcabodeuntiempoelusuarionohizonada
(oseanoaccedioaningunapgina).
EstoselimitadandoleuntiempomximoalacookiedeIDdesesinparaquenoseaceptemsluego
deesetiempo.
UnaformaesconfigurndoloenelarchivodeconfiguracindePHP(php.ini).Allhayquebuscarla
entradasession.cookie_lifetimeyponerleelvalor(ensegundos)alcualqueremosquese
desconecteelusuarioporinactividad.Pordefectotienevalor0queesilimitado.
Lasegundaopcinessetearlomanualmenteparacadaacceso.Esposible,entonces,modificar
manualmenteladuracindelacookie.Paraelloexistelafuncinset_cookie_paramsalacual

CarreraLinux2008ProgramacionPHP93
podemospasarlecuantodeseamosquedurelacookieapartirdelmomentoenquesedevuelvela
pgina.Estohabraquesetearloenelarchivocontrol_acceso.php(oelanlogoqueusen)paraquecada
vezqueseaccedeaunapginaserenueveeltiempo.
Sera:
session_start();
session_set_cookie_params(900); # 900 segundos = 15 minutos

Sien15minutoselusuarionoaccedeanada,lacookieseeliminardelservidor.Porlotanto,cuando
quieravolveraacceder,laverificacinencontrol_acceso.phpfallaryestarfueradelsistema.

Ejercicios
1. Comofuncionaunacookie?Comopuedorecuperarlasdesdemisscripts?
2. Dequesirveunasesion?ComosepuedenutilizardesdePHP?
3. Modificarelprograma3/4delosejerciciosdelaclase14,paraquelosvaloresdelnumeroal
azar,cantidaddeaciertos,cantidaddefallosycantidaddepasossepasenatravesdecookies
4. Modificarelprogramaanteriorparaquelosdatosseguardenenunasesionenlugardeenviarse
porcookies
5. Sepidecrearuncarritodecomprassencillo.
Comobasededatosdearticulosutilizaremosundiccionariollamadoarticuloselcualsera
similaralsiguiente:
my $articulos = array("Tornillo" => 0.1, "Tuerca" => 5.76, "Sillas" =>
39.25);

yunarticuloconlacantidaddestockquehaydecadauno:
my $stock = array("Tornillo" => 1000, "Tuerca" => 200, "Sillas" => 50);

luegosedebegenerarunapaginaquelistetodoslosarticulosexistentesylepermitaalusuario
agregarasucarritocuantosdesee.
Finalmente,debeexistirunlinkaunapaginaquelehagaunlistadodetodolopedidocontotal
incluido.

CarreraLinux2008ProgramacionPHP94

Clase16Introduccinalasbasesdedatos
relacionalesyalLenguajedeDefinicinde
Datos
MySQLesunmotordebasededatos.Lapreguntaesahora,queesunmotordebasededatos?Bien,
unmotordebasededatosesunservidorelcualprestaserviciosparaaccederymanipulardatos.Esto
sehaceutilizandoellenguajeSQL(StructuredQueryLanguageLenguajeEstructuradodeConsulta).
Dentrodelmotorlosdatossealmacenarnentablasqueasuvezestasseencuentrandentrodeunabase
dedatos.Paraaclararunpoco,diremosquedentrodeunmismomotorpuedenexistirvariasbasede
datosdistintasfuncionandosimultaneamente.Unabasededatosagrupardatosdelmismoproyecto
(aunqueestoestotalmentearbitrario).Enunabasededatossealmacenarntablas(tambinconocidas
comorelaciones).Enlastablasesendondeefectivamentesealmacenarlainformacin.Unatabla
consisteenunoomsatributos,dondeunatributoesuntipodevalorquesiquiereguardar.Por
ejemplo,sitenemosunatablaqueguardalainformacindeuncliente,estatendrcomoatributosel
nombre,elcdigo,ladireccin,eltelfono,etc.Dentrodelatablasepodrir,luego,insertando
entradasconestosdatos.Aestasentradasselasconocecomofilas,tuplasoregistros.Endefinitivauna
tablasercomounamatrizdondelascolumnasrepresentanlosatributosylasfilaslastuplas.
Dentrodeunatablaexisitrunoomscamposquesirvenparaidentificaraunafiladeformaunvoca.
Estoscamposselosconocecomoclavesalternativas.Podrnexistirvariasclavesalternativasdistintasy
seeligirunacomoclaveprimaria.Laclaveprimariaesunaclavealternativaqueseusarcuandose
quierahacerreferenciaaunaentradaespecficadelatabla.
Laideadetenertodalainformacinenunsolomotoresparaevitarlaredundancia.Deestaformasi
cambia,porejemplo,elnombredeuncliente,entoncessoloharfaltacambiarloenlatabladeclientes
yautomaticamenteseverareflejadoencualquierpartedelprogramaqueobtengaelnombredelcliente.
Estoselograyaquelainformacinde,enestecasoelcliente,seencuentraenunnicolugar.Cuando
senecesitebuscarohacerreferenciaaeseclienteseloharporlaclaveprimarialograndoasel
cometido.Existiranotrastablasquenecesitarnregistraralcliente(porejemploenunaventa).Estas
tablastendrnsolamentecomounodesuscamposalaclaveprimariadelcliente(digamossucdigo).
Deestaforma,cualquiercambioquehagamosenlatabladeclientesnoafectaralasdemsque
puedenfuncionarindependientementedeestehecho.Enlatabladeventas,elatributodelcdigodel
clienteserunaclaveforneaoexterna(osea,quehacereferenciaaotratabla).Selepuedeobligaral
motordebasededatosquecompruebeenelmomentodeinsertarunafila,enlatablaventas,existaen
latablaclientesalclientequeseestatratandodeingresar.Estoestilparaasegurarquenoentrebasura
enlainformacin.
ExistentressublenguajesdentrodeloquehoyendaesSQL:
a. DataDefinitionLenguage(DDL)(LenguajedeDefinicindeDatos):Bsicamenteesto
incluirlassentenciasCREATE,DROP,ALTER
b. DataManipulation(Management)Language(DML)(LenguajedeManipulacin
(Administracin)deDatos):BsicamenteestoincluirlassentenciasSELECT,INSERT,
DELETE,UPDATE

CarreraLinux2008ProgramacionPHP95
c. SecurityManagementLanguage(SML)(LenguajedeAdministracindeSeguridad):
BsicamenteestoincluirlassentenciasGRANT,REVOKE

IntroduccinalservidorMySQL
ParainstalarelservidorMySQLprimerosedeberdescargarelpaquetedesdesusitioweb
(www.mysql.org).Lainstalacinessencilla,bajandoelpaquetequecontienelosbinarios
(recomendado).
Enprincipiosedebedesempaquetareltgzeneldirectorio/usr/local/mysql.Esesereldirectorioraz
denuestroservidor.
Luegohayquedarlelossiguientescomandosdesdeelshell:
cd /ur/local/mysql
scripts/mysql_install_db
chown -R root .
chown -R mysql data
chown -R mysql .

Unavezhechoestoyaestarlistoparaserminimamenteejecutado.
Luegoparainiciarlodentrodeldirectoriosupportfilesseencuentraelscriptmysql.server(estepuede
serusadoparaponerleenelrc.dyseejecuteautomaticamente).Entoncesejecutaremos:
support-files/mysql.server start

ysitodomarchobienelservidorseestarejecutando.
Paraconectarnosconelservidorutilizaremoselcomandomysql.Desdeelshellsimplemente
ejecutaremos:
mysql

ynoshabremosconectadoscontraelservidorutilizandoelusuarioactual.Unavezhechoestepasose
podraningresartodosloscomandosquesedescribiranapartirdeahora.
Elmanejodeusuariosseverenclasesposteriores,porlotanto,sernecesarioconectarsecomorootal
servidoryaqueeselnicousuarioqueexisteenelmotoralmomentodeinstalarlo(yhastanotiene
contrasea!).

ElLenguajedeDefinicindeDatos(DDL)
NOTA:Deaquenadelanteenlasintaxisdeloscomandosloqueseencuentreencerradoentre
corchetesseinterpretarcomoqueesdecaracteropcional.Loscorchetesnoformanpartedela
sintaxisdelasentenciaens,solosirveparaexpresarlaopcionalidaddeloqueencierran.
Cuandoseencuentreunsmbolodetubera(|)seinterpretarcomounopcin.Sepodrutilizarloque
seencuentraalaizquierdadelmismooladerechaperonoambasopciones.

CarreraLinux2008ProgramacionPHP96
CREATE
ElprimercomandodelDDLeselCREATE.CREATEnospermitircrearbasededatosytablas.Para
crearunabasededatosescribiremos:
CREATE DATABASE nombre_de_la_bd;

Estocrearlanuevabasededatos.Luegoseranecesarioelegirlaparapodercrearlastablasdentrode
ella.ParaesoutilizaremoselcomandoUSE:
USE nombre_de_la_bd;

Locomplejoaquescrearlastablasyaqueenellasresidetodalainteligencia.Paraelloutilizaremos
CREATEdelasiguienteforma:
CREATE TABLE nombre_tabla (definicion_create,...) opciones;

Ladefinicion_createserntodaslosatributosquetendralatablaademsdequeallsepodran
definir,porejemplo,laclaveprimaria.
Lasintaxisdedefinicion_createes:
nombre_columna tipo [NOT NULL | NULL] [DEFAULT valor] [AUTO_INCREMENT] [PRIMARY
KEY]
| PRIMARY KEY (col1, col2, ...)
| UNIQUE (col1, col2, ...)

Laprimeradelasopcionessirveparaagregaruncampoenlatabla.nombre_columnaserel
nombrequetendrelcampoytiposerelconjuntodevaloresqueaceptareseatributo(vercuadro
msadelante).LaopcinNOT NULLoNULLsirveparaespecificarsiesecampopuedeonotomarel
valorNULL.ElvalorNULLsignificaquenosetieneinformacinsobreesecampoyesdistintoa
cualquierotrovalorquepuedallegaraconteneresecampo.
LaopcinDEFAULTsirveparaqueenelcasodequeuncampoquedelibradoalmotorparaser
llenado,elmotorutilizarelvalorquenosotrosleespecifiquemos.
LaopcinAUTO_INCREMENTseutilizaparaqueesecampovayaautoincrementandose
automaticamenteamedidaqueseagreganvalores.
FinalmentesiseespecificalaopcinPRIMARY KEY,eseatributoquedaraelegidocomoclave
primaria.
Lasegundaalternativaseutilizaparaespecificarcualocualesatributossernlaclaveprimaria.Sila
claveprimariaestacompuestapormsdeunatributodeberaserespecificadadeestaformayno
dndolelaopcinPRIMARY KEYacadaatributo.
FinalmentelaopcinUNIQUEsirveparaespecificarquecolumnassernclavesalternativas,esdecir,
quecolumnastendranvaloresquenopodranrepetirseenningunaotrafila.
Entrelostiposdedatosquehayparaunacolumnapodemosencontrar:

CarreraLinux2008ProgramacionPHP97
Tipo

Tamao(bytes)

TINYINT

SMALLINT

MEDIUMINT

INTEGER

BIGINT

FLOAT

4u8

DATE

DATETIME

TIMESTAMP

TIME

CHAR(M)

Mbytesdonde1<=M<=255

VARCHAR(M)

L+1bytesdondeL<=My1<=M<=255
Leslacantidaddecaracteresusados

TINYBLOB/TINYTEXT

L+1L<2^8

BLOB/TEXT

L+2L<2^16

MEDIUMBLOB/MEDIUMTEXT

L+3L<2^24

LONGBLOB/LONGTEXT

L+4L<2^32

ENUM(valor1,valor2,...)

1o2

Finalmenteelcampoopcionesenladefinicindelatablaes:
[ COMMENT = "Comentario" ]
[ TYPE = {BDB|HEAP|ISAM|MyISAM|InnoDB|Merge} ]

Laprimeropcinsirveparadarleunadescripcinalatablaparaexplicarsucontenido.Lasegunda
opcinsirveparaespecificareltipodetablaqueseutilizar.PordefectoseutilizaeltipoMyISAMque
eselpropiodeMySQL.ElotrotipointeresanteesInnoDBquedasoporteparahacertransacciones.

CarreraLinux2008ProgramacionPHP98
DROP
LasentenciaDROPseutilizarparadestruirunatablaounabasededatos.CuandoseejecutaDROP
sobreunatablaseperdertodosucontenidoyademslaestructuradelatabla.Sisebajaunabasede
datosseperderntodaslastablascontodossucontenido.Paraborrarunatablaejecutaremos:
DROP TABLE nombre_de_la_tabla;

yparabajarunabasededatosejecutaremos:
DROP DATABASE nombre_de_la_base_de_datos;

ALTER
Cuandosedeseahacerunamodificacinaunatablaqueyaexiste(yprobablementetengamuchosy
valiososdatoscargados)seutilizalasentenciaALTER TABLE.Lasintaxisdeestasentenciaesla
siguiente:
ALTER TABLE nombre_tabla

especificacion

especificacionserlaaccinatomarsobrelatabla.Encontraremos:
ADD COLUMN definicion_create [FIRST | AFTER nombre_columna]
ADD PRIMARY KEY (col1, col2, ...)
DROP COLUMN nombre_columna
DROP PRIMARY KEY
MODIFY definicion_create
CHANGE nombre_columna definicion_create

Laprimeradelasposibilidadesnospermiteagregarunanuevacolumnaalatabla.Paraello
utilizaremoslamismasintaxisqueenelCREATE(definicion_create).Lodiferenteestaenel
opcionalltimoparmetro.Estenospermitedeterminarenqueposicinagregaremoselatributo:siir
alprincipio(FIRST)oluegodequecolumna(AFTER).Sinoseespecificaningunoiralfinal.
Lasegundaposibilidadnospermiteasignarlelaclaveprimariaalatabla(similaracomosehaciaenel
CREATE).
Laterceraycuartaposibilidadnospermitenquitarunacolumna(juntocontodossusdatos)oquitarle
lasclavesprimariasalatabla.
Laltimasdosposibilidadesnospermitencambiaraunatributo.SiutilizamosCHANGEpodremos
cambiarlealatributonosololadefinicinsinotambienelnombredelatributo(recuerdenqueen
definicion_createhabiaqueespecificarelnombredelacolumna).
SiutilizamosMODIFYlepodremoscambiartodaslasopcionesaunacolumnasalvosunombre.

CarreraLinux2008ProgramacionPHP99

Ejemplo
Estaesunabasededatosdeejemplocreadacondatosgeneradosalazarlacualservirparalos
ejemplosdeestaclaseylassiguientes.
Elscriptconlosdatosacargarpuedeserdescargadodesdeelsitio.
Labasededatosdeejemplo(aviones.sql):
# Para ejecutar este script es necesario tener corriendo un servidor de MySQL.
# Una vez levantado el servidor pueden hacer desde la linea de comandos:
# cat aviones.sql | mysql
#
#
#
#
#
#

En el modelo de datos, el asterisco al final de una linea denota que


la tabla posee una cardinalidad de N y en donde no posee asterisco
posee una cardinalidad de 1. Por ejemplo, si vemos las tablas AVION
y VUELO podemos leer que un AVION tiene MUCHOS VUELOS o que cada VUELO
tiene un UNICO AVION asignado.
El modelo de la base de datos aviones es el siguiente:

CarreraLinux2008ProgramacionPHP100
# NOTA: En MySQL lo que empieza con un # es un comentario
DROP DATABASE IF EXISTS aviones;
CREATE DATABASE aviones;
USE aviones;
DROP TABLE IF EXISTS AEROPUERTO;
CREATE TABLE AEROPUERTO (
ATO_ID int(10) unsigned NOT NULL auto_increment,
ATO_NOMBRE varchar(20) NOT NULL default '',
ATO_PIS_ID int(10) unsigned NOT NULL default '',
PRIMARY KEY (ATO_ID),
KEY(ATO_PIS_ID)
) ENGINE=InnoDB;
DROP TABLE IF EXISTS AVION;
CREATE TABLE AVION (
AON_ID int(10) unsigned NOT NULL auto_increment,
AON_AEROLINEA varchar(20) NOT NULL default '',
AON_TATO_TIPO char(1) NOT NULL default '',
PRIMARY KEY (AON_ID),
KEY (AON_TATO_TIPO)
) ENGINE=InnoDB;
DROP TABLE IF EXISTS ESCALA;
CREATE TABLE ESCALA (
ELA_VLO_ID int(11) unsigned NOT NULL default '0',
ELA_ORDEN int(11) unsigned NOT NULL default '0',
ELA_ATO_ID int(11) unsigned NOT NULL default '0',
ELA_HORA_SALIDA datetime default NULL,
PRIMARY KEY (ELA_VLO_ID,ELA_ORDEN),
KEY (ELA_ATO_ID)
) ENGINE=InnoDB;
DROP TABLE IF EXISTS PASAJE;
CREATE TABLE PASAJE (
PJE_ID int(10) unsigned not null auto_increment,
PJE_VLO_ID int(10) unsigned NOT NULL default '0',
PJE_TATO_CLASE enum('Primera','Negocios','Turista') NOT NULL default 'Primera',
PJE_NRO tinyint(4) NOT NULL default '0',
PJE_PRO_ID int(10) unsigned not null,
PRIMARY KEY(PJE_ID),
KEY(PJE_VLO_ID),
KEY(PJE_TATO_CLASE),
KEY(PJE_PRO_ID)
) ENGINE=InnoDB;
DROP TABLE IF EXISTS TIPO_ASIENTO;

CarreraLinux2008ProgramacionPHP101
CREATE TABLE TIPO_ASIENTO (
TATO_TIPO_AVION char(1) NOT NULL default '',
TATO_CLASE enum('Primera','Negocios','Turista') NOT NULL default 'Primera',
TATO_DESDE_NRO tinyint(3) unsigned NOT NULL default '0',
TATO_HASTA_NRO tinyint(3) unsigned NOT NULL default '0',
TATO_PRECIO DECIMAL(9,2) NOT NULL default '0',
TATO_CANTIDAD int(10) unsigned NOT NULL default '0',
PRIMARY KEY (TATO_TIPO_AVION,TATO_CLASE),
KEY (TATO_CLASE)
) ENGINE=InnoDB;
DROP TABLE IF EXISTS PASAJERO;
CREATE TABLE PASAJERO (
PRO_ID int(10) unsigned not null auto_increment,
PRO_NOMBRE varchar(40) NOT NULL default '',
PRO_APELLIDO varchar(40) NOT NULL default '',
PRO_EDAD tinyint(4) NOT NULL default '0',
PRO_PIS_ID int(10) unsigned not null,
PRIMARY KEY(PRO_ID),
KEY (PRO_PIS_ID)
) ENGINE=InnoDB;
DROP TABLE IF EXISTS PAIS;
CREATE TABLE PAIS (
PIS_ID int(10) unsigned not null auto_increment,
PIS_NOMBRE varchar(40) NOT NULL default '',
PIS_NOMBRE_CORTO char(3) NULL default '',
PRIMARY KEY(PIS_ID)
) ENGINE=InnoDB;
DROP TABLE IF EXISTS VUELO;
CREATE TABLE VUELO (
VLO_ID int(10) unsigned NOT NULL auto_increment,
VLO_AON_ID int(10) unsigned NOT NULL default '0',
PRIMARY KEY (VLO_ID),
KEY(VLO_AON_ID)
) ENGINE=InnoDB;
##################################################################################
######
# Reglas de integridad
ALTER TABLE AVION
ADD CONSTRAINT AON_TATO_TIPO_FK
FOREIGN KEY (AON_TATO_TIPO)
REFERENCES TIPO_ASIENTO(TATO_TIPO_AVION);
ALTER TABLE VUELO
ADD CONSTRAINT VLO_AON_ID_FK
FOREIGN KEY (VLO_AON_ID)
REFERENCES AVION (AON_ID);

CarreraLinux2008ProgramacionPHP102

ALTER TABLE ESCALA


ADD CONSTRAINT ELA_VLO_ID_FK
FOREIGN KEY (ELA_VLO_ID)
REFERENCES VUELO (VLO_ID);
ALTER TABLE ESCALA
ADD CONSTRAINT ELA_ATO_ID_FK
FOREIGN KEY (ELA_ATO_ID)
REFERENCES AEROPUERTO (ATO_ID);
ALTER TABLE PASAJE
ADD CONSTRAINT PJE_VLO_ID_FK
FOREIGN KEY (PJE_VLO_ID)
REFERENCES VUELO (VLO_ID);
ALTER TABLE PASAJE
ADD CONSTRAINT PJE_TATO_CLASE_FK
FOREIGN KEY (PJE_TATO_CLASE)
REFERENCES TIPO_ASIENTO (TATO_CLASE);
ALTER TABLE PASAJE
ADD CONSTRAINT PJE_PRO_ID_FK
FOREIGN KEY (PJE_PRO_ID)
REFERENCES PASAJERO (PRO_ID);
ALTER TABLE AEROPUERTO
ADD CONSTRAINT ATO_PIS_ID_FK
FOREIGN KEY (ATO_PIS_ID)
REFERENCES PAIS (PIS_ID);
ALTER TABLE PASAJERO
ADD CONSTRAINT PRO_PIS_ID_FK
FOREIGN KEY (PRO_PIS_ID)
REFERENCES PAIS (PIS_ID);

Ejercicios
1. QueesyparaquesirveSQL?
2. Esposiblemodificarlaestructuradeunatablaluegodesercreada?Queproblemaspuede
traeraparejados?
3. ExplicarparaquesirvelassentenciasCREATE,DROPyALTER.AquesublenguajedelSQL
corresponden?
4. Sepidegenerarelmodeloparaunaaplicacinqueposeelassiguientescaractersticas:
Sequieregenerarunaagenda.Lamismausarcomobaseunconjuntodepersonas.Delas
mismasequierepoderalmacenar:nombreyapellido;direccin;pas;telefonosmuchosyde
distintostipos(casa,celular,trabajo,fax);fechadenacimiento;observacin.
Sedebetenerprecargadosenlabasededatosalosdistintospases.Luegosedebepoder
almacenareventos.Loseventostendrnunadescripcin,unaobservacin,unafechaasociada(y

CarreraLinux2008ProgramacionPHP103
ademslahorayduracin),y,opcionalmente,unahoraasociada.Paracadaevento,sedebe
poderagregarlosparticipantes(unooms)delmismo.Estosdebenestaryacargadosenlabase
comounapersona.
Loseventosdebenestarcategorizadossegnunalistadecategoriascargada.
5. Sesugieremodelaralgnsistemaavoluntadsobrealgntemadeinteresparticular.

Clase17LenguajedeManipulacindeDatos
INSERT
LasentenciaINSERTeslaqueseutilizaparaagregarfilasaunatabla.
Susintaxises:
INSERT INTO nombre_tabla VALUES (valor1, ..., valorN), (...), ....

Estasentenciaagregarvaloresalatablanombre_tabla.Loqueseencuentraentreparntesisser
unregistroaagregar.Hayquedestacarquelacantidaddevalorescorresponderalacantidadde
columnasquetienelatabla.Elvalor1corresponderalaprimercolumna,elsegundovalorala
segundacolumnayassucesivamente.Tambinsepermiteespecificarvariastuplasenunamisma
sentenciaINSERTseparndolasporcomas.
PorejemploparaagregarunregistroalatablaPAISpodramosescribir:
INSERT INTO PAIS (PIS_ID, PIS_NOMBRE, PIS_NOMBRE_CORTO) VALUES (NULL, 'Argentina',
'ARG');

osisupieramosqueIDqueremodarle(235porejemplo),podramosescribir:
INSERT INTO PAIS (PIS_ID, PIS_NOMBRE, PIS_NOMBRE_CORTO) VALUES (235, 'Argentina',
'ARG');

DELETE
LasentenciaDELETEsirveparaeliminartuplasdeunatabla.
Susintaxises:
DELETE FROM nombre_tabla [ WHERE definicion_where ]

SisellamaestasentenciasinlaclusulaWHERE,DELETEeliminartodoslosregistrosdelatabla.
EstonoeslomismoquehacerunDROP,yaquelatablaseguirexistiendo.LaclusulaWHEREse

CarreraLinux2008ProgramacionPHP104
utilizaparaseleccionarquetuplassequiereborrar.Lastuplasaborrarserntodasaquellasque
cumplanconlacondicinespecificadaendefinicion_where.Estadefinicinseverendetalleen
elapartadodelSELECT.
Siporejemploquicieramosborrartodalatabladepaisespodramosescribr:
DELETE FROM PAIS

osiporejemploquicieramosborrartodoslospasajesdelvuelo15podramosescribir:
DELETE FROM PASAJE WHERE PJE_VLO_ID = 15

UPDATE
UPDATEseutilizaparaactualizarvalorenunregistroqueyaexiste.
Susintaxises:
UPDATE nombre_tabla SET col1=expr1 [, col2=expr2, ... ] [ WHERE definicion_where ]

EstasentenciaactualizarlascolumnasespecificadasluegodelaclusulaSETalvalorqueseles
asignaall.LaclusulaWHEREcumplelamismafuncinqueparalasentenciaDELETE.
Sidesearamoscambiarleelnombredelaaerolinadelavion23escribiramos:
UPDATE AVION SET AON_AEROLINEA = 'TranSink' WHERE AON_ID = 23

osideseareamossubirleun10%atodoslospreciospodramosescribir:
UPDATE TIPO_ASIENTO SET PRECIO = PRECIO * 0.1

SELECT
SELECTeselalmadelmotordebasededatos.Estaeslainstruccinmsutilizadayaqueeslaquese
utilizapararecuperarinformacindelastablasyaexistentes.
Susintaxises:
SELECT [DISTINCT | ALL] * | columnas | expresiones
FROM referencia_tabla [, referencia_tablas, ...]
WHERE definicion_where
GROUP BY columna | nro_columna [, columna | nro_columna]
HAVING definicion_where
ORDER BY columna | nro_columna [ASC | DESC] [, columna | nro_columna [ASC | DESC]
]

CarreraLinux2008ProgramacionPHP105
LIMIT [offset, ] cantidad_filas

Estesentenciapermitirobtenercolumnasoexpresionesdesdeunaomstablasquecumplanconun
criteriodebsquedadado.Lascolumnasyexpresionesquedevolversonlasespecificadasalprincipio.
El*equivaleportodaslascolumnasdetodaslastablasqueseestenutilizando.
LaopcinDISTINCTsirveparaquetodaslasfilasquepertenezcanalresultadoseandistintas(lasfilas
quesonigualessedescartanautomaticamente).
LaclusulaFROMnospermiteespeficiarsobrequetablasvamosatrabajar.
Lareferencia_tablasedefinecomo:
nombre_tabla [, otra_tabla | INNER JOIN otra_tabla ON condicion]

lapartequeseencuentraentrecorchetespuederepetirseindefinidamente.
Siseeligentablasseparandolasporcomaloqueseharescombinarcadafiladelaprimertablacon
todaslasfilasdelasegundatabla.Deestaformaseobtienentodaslascombinacionesposibles.Sise
utilizaINNER JOINsevinculanlastablasconrespectoalacondicinestablecida(porlogeneralser
tabla1.atributo_clave=tabla2.atributo_clave).Osea,primerosebuscaranlasfilas
delatablaunoyluegoconesosresultadossebuscarenlatabladoslasfilasqueconcuerdenconla
condicindada.
Tomemoselejemplomssencillo,traertodoslosdatosdetodoslosaeropuertosqueestenregistrados.
Paraelloescribiremos:
SELECT * FROM AEROPUERTO

Comoelnombredelpasnoaparece,relacionaremosestatablaconladepaisesparaobtenerlos
nombres.Ahoraquedaracomo:
SELECT * FROM AEROPUERTO, PAIS WHERE ATO_PIS_ID = PIS_ID

Paraseguirmejorandolaconsulta,solotraeremosloscamposquenosinterese.Paranuestroejemplo
traeremoselnombredelaeropuertoconsuidyademaselnombredelpas.
Finalmentenosquedar:
SELECT ATO_ID, ATO_NOMBRE, PIS_NOMBRE FROM AEROPUERTO, PAIS WHERE ATO_PIS_ID =
PIS_ID

ClusulaWHERE
LaclusulaWHEREseutilizarparaaplicarelcriteriodebsquedas.Allsepodranutilizartodoslos
operadoresdecomparacinclsicos(= < <= > >= !=)paracrearcondicionesylascondicionesse
puedenjuntarutilizandoAND(y)yOR(o).
Siporejemplosebuscaalcliente2425lacondicionpodraser:

CarreraLinux2008ProgramacionPHP106
WHERE CODIGO=2425

Siporejemploquicieramosvertodalainformacindelosavionesperosolodeaquellosqueseandel
tipoA,podramosescribir:
SELECT AON_ID, AON_AEROLINEA FROM AVION WHERE AON_TATO_TIPO = 'A'

Enesteejemplo,notraeremoselcampoAON_TATO_TIPOporqueyasabemosquetendrsiempreel
valorA.

ClsulaGROUP BYyHAVING
LaclusulaGROUP BYseutilizaparaagruparlosresultados.Estaclusulaagruparalosresultados
cuyascolumnastenganlosmismovalores.Lascolumnasqueseutilizarnparaagrupardebenser
enumeradas.Cuandoseagrupasepuedenutilizaralgunasfuncionesparaseleccionar.
Siquicieramossabercuantasescalastieneunvuelo(contandoelpuntodepartidayeldellegada),
deberiamosagruparlatablaESCALAporelcampoqueidentificaaunvuelo(ELA_VLO_ID)ycontar
cuantosregistroshay.Estonosquedarcomo:
SELECT ELA_VLO_ID, COUNT(1) FROM ESCALA GROUP BY ELA_VLO_ID

LaclusulaHAVINGessimilaraladelWHEREperoenvezdefiltrarsobretodaslasfilas,loharsobre
lasresultantesdelaagrupacin.
Siquicieramosacotarelresultadodelaconsultaanterior,porejemplo,trayendosolamenteaquellosque
tengan4omsescalas,podramosescribir:
SELECT ELA_VLO_ID, COUNT(1) FROM ESCALA GROUP BY ELA_VLO_ID HAVING COUNT(1) >= 4

ClsulaORDER BYyLIMIT
LaclusulaORDER BYsirveparaqueelresultasalgaordenadoporunaomscolumnas.Acada
columnaselepuedeponerDESCparaqueordeneenformadescendentementeoASCparaquelohaga
enformaascendente(pordefecto).
Comoejemploobtendremosunlistadoconlacantidaddepasajesquetienecadapersonaordenadosdel
quemspasajeshayatenidoalquemenoshayatenido.Luego,paraaquellosconigualescantidades,lo
ordenaremosporapellidoynombre.Paraelloescribiremos:
SELECT PRO_APELLIDO, PRO_NOMBRE, COUNT(1) AS CANTIDAD
FROM PASAJERO, PASAJE WHERE PRO_ID = PJE_PRO_ID
GROUP BY PRO_NOMBRE, PRO_APELLIDO
ORDER BY CANTIDAD DESC, PRO_APELLIDO, PRO_NOMBRE

CarreraLinux2008ProgramacionPHP107
Aclararmosquesiqueremosutilizarparaordenarunafuncinagregada(COUNTenesteejemplo),en
vezdeuncampo(pudimoshaberordenadoellistadoporapellidoynombresolamente),seledebedar
unALIASadichafuncinparaquelaclusulaORDER BYpuedaencontrarla.
TambinsepuedenlimitarlacantidadderesultadosutilizandolaclusulaLIMIT.Sisoloseespecifica
lacantidadsedevolvernlasprimerascantidad_filasderesultados.Siseespeficiaoffset,
(desplazamiento)sedevolveresacantidaddefilasperopartiendodesdeeloffsetespecificado.
Siquicieramoshacerunrankingdelas100personasquemspasajeshayacomprado,podramos
agregarlealaconsultaanterior:
SELECT PRO_APELLIDO, PRO_NOMBRE, COUNT(1) AS CANTIDAD
FROM PASAJERO, PASAJE WHERE PRO_ID = PJE_PRO_ID
GROUP BY PRO_NOMBRE, PRO_APELLIDO
ORDER BY CANTIDAD DESC, PRO_APELLIDO, PRO_NOMBRE
LIMIT 100

Subconsultas
Unasubconsultaessimplementeunaconsultadentrodeotra.Osea,esunmecanismoquenospermite
ejecutarunSELECTdentrodeotraconsulta(porlogeneralotroSELECT).ElSELECTqueseejecuta
dentrodeotraconsultaseloconocecomosubconsultayalaotraconsultacomoconsultaexterna
(outerquery).
Lasubconsulta,tambinconocidacomosubquery,siempredebeescribirseentreparntesis.
Paravercomoseescribeunasubconsultaveremosunejemplo.Recuperaremostodoslosvuelosconsus
aeropuertosdedestino(dondeterminaelviaje).Elproblemaestaquecadavuelopuedeteneruna
cantidaddeescalasdistinta(oseaqueelcampoELA_ORDENvariarsegnelvuelo).Conlovisto
hastaahoranohabraformaderesolverloenunanicaconsulta.Unaformaderesolverlocon
subconsultasescomparandoenlaclusulaWHEREelcampoELA_ORDENconelmximoordende
cadavuelo(lasubconsulta).Estonosquedara:
SELECT VLO_ID, ATO_NOMBRE, ELA_ORDEN
FROM VUELO, ESCALA, AEROPUERTO
WHERE VLO_ID=ELA_VLO_ID AND ELA_ATO_ID=ATO_ID AND
ELA_ORDEN =
(SELECT MAX(E2.ELA_ORDEN)
FROM ESCALA AS E2
WHERE E2.ELA_VLO_ID = VLO_ID)

Comosepuedeverlasubconsultaestaescritaentreparntesis.Ademscomohemosutilizadolamisma
tablaqueenlaconsultaexterna,enlaconsultainterna(sedicequeesunasubconsultacorrelacionada)
debermosdarleunaliasparaqueMySQLpuedadiferenciaentreloscamposdeunaydelaotra.
Enesteejemplopodemosverquelasubconsultasolodevuelveunnicovalor,peropodradevolver
ms.

CarreraLinux2008ProgramacionPHP108
Paraelloenvezdeutilizarsoloeligual,utilizaremos,adems,eloperadorANY.Deestaformanos
quedarlacondicincomocolumna = ANY (subconsulta),loquesignificarqueelcampo
columnapuedeconcordarconcualquieradelosquedevuelvasubconsulta.Tambinpodemos
utilizareloperadorINenlugarde= ANY(enrealidadINescomounaliasde= ANY).
Comoejemplogeneraremosunlistadoconlacantidaddepasajescompradosporpersonaquevivanen
elmismopasquealgunodelosaeropuertosexistentes.Estaconsultanosquedar:
SELECT PRO_APELLIDO, PRO_NOMBRE, COUNT(1) AS CANT
FROM PASAJERO, PASAJE
WHERE PRO_ID = PJE_PRO_ID AND
PRO_PIS_ID IN (SELECT ATO_PIS_ID FROM AEROPUERTO)
GROUP BY PRO_APELLIDO, PRO_NOMBRE
ORDER BY PRO_APELLIDO, PRO_NOMBRE

Comoltimoejemplo,utilizaremosunasubconsultaperoparatraerundatoextradentrodellistadode
campos.Traeremoslacantidaddepasajesvendidosparacadavuelo,perosoloparaaquellosvuelosque
hayanvendidomsde200pasajes.Ademstraermoslacantidaddeescalasqueposeecadaunodelos
vuelosseleccionados.ComolatablaVUELOconESCALAtieneunarelacinde1amuchosyVUELO
conPASAJEtambin,nopodemosrelacionarlastodasdirectamenteenelFROM.
Paraelloescribiremoslasiguienteconsulta.
SELECT VLO_ID, COUNT(1) AS CANT_PASAJES,
(SELECT COUNT(1)
FROM ESCALA
WHERE ELA_VLO_ID = VLO_ID) AS CANT_ESCALAS
FROM VUELO, PASAJE
WHERE VLO_ID = PJE_VLO_ID
GROUP BY VLO_ID HAVING CANT_PASAJES > 200
ORDER BY CANT_PASAJES DESC

Paramejorarlasalidahemosdecididoasignarleunaaliasalasubconsulta.Estoesunabuena
costumbreyademsserextremadamentenecesariohacerlocuandoestemosprogramandoyquerramos
recuperardichacolumna.

INSERTINTOtablaSELECT...
ExisteunavariacindelINSERT.EstavariacinconsisteenutilizarelresultadodeunSELECTpara
agregarvaloresenunatablaenvezdetenerqueespecificarunocadatupla.Sedebetenerencuentaque
elresultadodelabsquedadeberdevolverlamismacantidaddecolumnas(conenelmismoordeny
losmismotiposdedatos)quetienelatablaenlacualsequiereningresarlosdatos.

Ejercicios
Considerarelmodelodedatosdefinidoenlaclaseanterior.
1. EscribirunINSERTparacadaunadelastablasexistentes

CarreraLinux2008ProgramacionPHP109
2. Escribirunaconsultaquedevuelvatodoslospasajesylainformaciondelospasajerosparaun
vuelodeterminado(paraelvuelo46porejemplo).
3. Escribirunaconsultaquedevuelvalacantidaddepersonasquehayporpais.Modificarla
consultaparaqueagregueotracolumnaindicandocualeselporcentajequerepresentacada
cantidad.
4. Averiguarescribiendounaconsulta,cualeselpaisquemasvuelospasanporel.
5. Escribirunaconsultaquetraigalarecaudaciontotaldecadavueloylacantidaddepasajes
vendidos.
6. Traerunlistadodetodoslosvuelosconsusaeropuertosdeorigenydestino.Ademassedebe
indicarenelmismolistado,lacantidaddeescalasquerealizaylacantidaddepasajesvendidos.

Clase18LenguajedeAdministracinde
Seguridad.
Comofuncionalaseguridad
PrimeroquenadadiremosqueMySQLidentificaaunusuariomediantesunombredeusuarioyel
hostdesdeelcualseestaconectando.Deestaformapodemostenerdosusuariosconigualnombre
peroquetienendistintosconjuntosdeprivilegios(yaqueseelusuariopepeenlocalhostes
distintoquepepeenalgun_otro_lado.com).
Enprincipio,elservidorcontrolalaseguridadendosmomentos:
1. Cuandoelusuarioseloguea,secontrolaquesuusuario/host/contraseaseancorrectos.
2. Concadasentenciaqueelusuarioejecuta,secontrolaquetengalosprivilegiosnecesariospara
realizarla.SielusuariopidehacerunSELECT,unCREATEounDROPsecontrarquetenga
lospermisos,encasodenotenerlosselenegarlasentencia.

LasentenciaGRANT
Estesentenciaseutilizaparaotorgarprivilegiosaunusuario(ocrearlosinoexiste).
Susintaxises:
GRANT tipo_privilegio
ON objetos
TO usuario [ IDENTIFIED BY 'password' ]

GRANTotorgaelprivilegioespecificadoentipo_privilegiosobrelosobjetosdefinidosen
objetosalusuariodefinidoenusuario.Opcionalmenteselepuedeagregarunacontraseapara
dichousuarioagregandolaclusulaIDENTIFIED BY.
Alejecutarestasentencia,sielusuarionoexiste,escreado.

CarreraLinux2008ProgramacionPHP110
Lostiposdeprivilegiosposibles(tipo_privilegio)son:
Privilegio

Descripcin

ALL [PRIVILEGES]

Otorgatodoslosprivilegiossimple,exceptoGRANT
OPTION

ALTER

PermiteusarALTER TABLE

CREATE

PermiteusarCREATE TABLE

CREATE TEMPORARY
TABLES

PermiteusarCREATE TEMPORARY TABLE

DELETE

PermiteusarDELETE

DROP

PermiteusarDROP TABLE

INDEX

PermiteusarCREATE INDEXyDROP INDEX

INSERT

PermiteusarINSERT

SELECT

PermiteusarSELECT

SHOW DATABASES

PermiteejecutarSHOW DATABASES,elcualmuestra
todaslasbasesdedatosdelabase

SHUTDOWN

Permiteusarmysqladmin shutdown

UPDATE

PermiteusarUPDATE

USAGE

SinnimodeNO PRIVILEGES

GRANT OPTION

Permiteotorgarprivilegios

Losobjetospermitidosson:
nombre_tabla | base_datos.* | *.*

Estonospermiteotorgarlosprivilegiossobreunasolatabla(nombre_tabla),sobretodaslastablas
deunabasededatos(base_datos.*)osobretodaslastablasdetodaslasbasesdedatos(*.*).
Finalmente,usuariodefinealusuarioquesequierecrear/otorgarprivilegios.Comomencionamos
anteriormente,unusuarioestaidentificadoporsunombreysuhost.Porlotanto,elformatonormal
parausuarioes'nombre'@'host'.Unejemplopodraser,'pepe'@'locahost'.
MySQLpermiteelusodewildcardsenelcampohost.Estossonelsmbolodeporcentaje(%)yel
guinbajo(_).Ambossonanlogosalasterisco(*)yalsignodeinterrogacin(?)delshell.El
primero,%,concuerdaconcualquiercaracter,cualquiercantidaddeveces.Deestaformapodramos
definiraunusuariocomo'pepe'@'%.tuxsys.com.ar'paraqueelusuario'pepe'pueda
conectarsedesdecualquierdominiotuxsys.com.ar.Opodramosdefiniraunusuariocomo
'pepe'@'%'paraquepuedaloguearsedesdecualquierlugardelplaneta.
Elguinsirveparalomismoqueelporcentajeperosoloconcuerdaconuncaracter.
Porejemplo,paracrearunusuariopepeenlamquinalocal,quetrabajaenunproyectosobreunabase
dedatosllamadaavionesyconcontrasea'epep',podramosescribir:

CarreraLinux2008ProgramacionPHP111
GRANT USAGE on aviones.* TO 'pepe'@'localhost' IDENTIFIED BY 'epep';

oparapermitiralmismousuarioconsultartodaslastablasdedichabasedadatos:
GRANT SELECT ON aviones.* TO 'pepe'@'localhost';

LasentenciaREVOKE
Estasentenciaseutilizaparaquitarleprivilegiosaunusuario.
Susintaxises:
REVOKE tipo_privilegio
ON objeto
FROM usuario

Losparmetrostipo_privilegio,objetoyusuariosonlosmismoqueparalasentenciaGRANT.
Paraquitarletodoslosprivilegiosaunusuariosepuedeutilizarlasiguientesintaxis:
REVOKE ALL PRIVILEGES ON *.* FROM 'pepe'@'localhost'

UtilidadesRelacionadas
mysql
Estaaplicacineselcliente,paramodotexto,quevienepordefectoentodapaquetedeMySQL.Desde
lpodemosconectarnosacualquierbasededatos.
Paraellosimplmementedebemosejecutarlodesdelalneadecomandossoloporsunombre.Por
defecto,sinoespecificamosunhostounusuario,tomaralamquinalocalyalusuarioconelquenos
hayamoslogueadoenelsistema.
Paraespecificarleelhostalcualnosqueremosconectardeberemossuministrarlelaopcin-hseguida
delnombredelhost.
Paraespecificarleelusuariodeberemosespecificarlelaopcin-useguidadelnombredelusuario.
Sielusuarioconelcualnosqueremosconectarposeecontraseadeberemosespecifcicarleademsla
opcin-o,encasocontrariononospodremosloguear.
Tambinpodemosespecificarlesobrequebasededatosqueremostrabajar(ahorrndonosdehacer
luegounUSEdelamisma).Paraellosimplementenombraremoscomoltimoparmetroelnombrede
lamisma.

CarreraLinux2008ProgramacionPHP112
mysqladmin
Estaherramientanospermiteejecutaralgunastareasadministrativassobrenuestroservidor,comocrear
basesdedatos,observarlasconsultasenproceso,chequearelestadoactualyms.
Lasintaxisdeestecomandoes:
mysqladmin [OPCIONES] comando [OPCIONES_COMANDO]

Entreloscomandoqueexistenpodemosdestacar:
Comando

Descripcin

create
base_datos

Creaunabasededatosconelnombrebase_datos

drop
base_datos

Eliminalabasededatosqueposeeelnombrebase_datos

kill id, id, Terminaalafuerzabrutaconsultasqueseestenejecutando


...
(verprocesslist)
Cambialacontraseadelusuarioconelqueseesta
password
"nueva_contr conectandomysqladmin
asea"
ping

Chequesielservidorestalevantado.

processlist

Muestraunalistacontodosloshilosqueseestanejecutando
enelservidor.Encadahiloseejecutaunaconsulta.Aqu
podemosverqueiddelhilolecorrespondeaqueconsulta,
comoastambinqueusuariolaestaejecutando(ydesdeque
host),sobrequebasededatos,cuantotiempolleva
ejecutndoseyenqueestadoseencuentra.

shutdown

Detieneelservidor

status

Muestraalgunasestadsticassobreelestadodelservidor.En
particularsever:Eltiempo(ensegundos)quesehaestado
ejecutandoelservidor;Lacantidaddehilosactivos(clientes);
Lacantidaddeconsultasprocesadas;Lacantidaddeconsultas
quehantomadomsquelong_query_time(definidopor
parmetroalinicializarelservidor)enejecutarse;Lacantidad
detablasquehaabiertoelservidor;Lacantidaddetablas
abiertasenelmomento;

variables

MuestraelcontenidodelasvariablesglobalesdeMySQL

version

Muestralaversinactual

mysqlcheck
Estaherramientaseutilizaparacomprobarycorregirtablasquehayanquedadorotasporalgnmotivo.

CarreraLinux2008ProgramacionPHP113
SolosirveparatablasdeltipoMyISAM.
Susintaxises:
mysqlcheck [OPCIONES] base_datos [tablas]
mysqlcheck [OPCIONES] --databases base_datos1 [base_datos2 base_datos3 ... ]
mysqlcheck [OPCIONES] --all-databases

Enelprimerodeloscasos,seaplicaelcomandosobretodaslastablasdebase_datos,anoserquese
especifiquentablas.
Elsegundodeloscasosseaplicasobretodaslastablasdelasbasesdedatosespecificados.
Finalmente,eltlimomodoessobretodaslastablasdetodaslasbasesdedatos.
Entrelasopcionesimportantesencontramos:
Opcin

Descripcin

--check

Compruebasilatablaestaenunestadocorrecto.

--repair

Reparaunatablasiposeeerrores

--optimize Optimizalastablas.Estoesrecuperarelespacioempleadopor
registrosquehansidoeliminados.MySQLsigaguardandodicho
espacioparareutilizarloconnuevosregistrosynotenerque
volverapedireseespacioalSistemaOperativo.

mysqldump
Estautilidadsirveparahacercopiasderespaldodebasesdedatos/tablas.
EstecomandogenerarunarchivocontodaslassentenciasSQLparapodervolveracrearlastablasy
cargarlosdatosdelasbasesespecificadas.
Susintaxises:
mysqldump [OPCIONES] base_datos [tablas]
mysqldump [OPCIONES] --databases base_datos1 [base_datos2 base_datos3 ... ]
mysqldump [OPCIONES] --all-databases

EnelprimerodeloscasossegenerarelSQLnecesarioparagenerarlabasededatosbase_datos
completa.Siseespecificaademslastablas(separadasporespacios)segenerarsolodeaquellastablas
ynodelabasecompleta.
LasegundaposibilidadnospermitegenerarSQLparavariasbasededatospasndolecomoparmetro
--databasesyluegoelnombredecadaunadelasbasesquequeremos.
Porltimo,podemoshacerlosobretodaslasbasesdedatosdenuestrosistemautilizandoelparmetro
--all-databases.
Entodosloscasos,mysqldumpenviartodoelSQLnecesarioalasalidaestndar.Paraguardarenun
archivoparautilizarlaluego,deberemosredireccionarlasalidaalmismo:
mysqldump --all-databases > mi_backup.sql

CarreraLinux2008ProgramacionPHP114
EntralasOPCIONESimportantespodemosencontrar:
Opcin
Descripcin
--add-droptable

EstaopcinagregardelantedelCREATE TABLEunDROP
TABLE.Deestaforma,podemoscorrerelscriptsobreuna
basequeyaexistasinquenosarrojeerroresaltratardecrear
lastablas.

PermitegenerarSQLcompatibleconotrosmotoresdebases
-compatible=ti dedatos.Entrelosposiblesvaloresdetipopodemos
po
encontrar:ansi, mysql323, mysql40,
postgresql, oracle, mssql, db2, maxdb,
no_key_options, no_table_options, o
no_field_options
--no-create-db NoagregalalneadelCREATE DATABASEalbajaruna
basededatos.
--no-createinfo
--no-data

NoagregalosCREATE TABLEdecadatabla
NoagregalosINSERTconelcontenidodelastablas.Esto
nospermiteobtenerunarchivoconsololaestructuradela
basededatossinlosdatos.

mysqlhotcopy
Estescriptnospermitecrearbackupsdelabasededatosduplicandolasmismasenunnuevodirectorio.
Susintaxises:
mysqlhotcopy base_datos1 [base_datos2 basedatos3 ...] /nuevo/directorio

Deestaforma,segenerarunacopiadela/sbase/sdedatosbase_dato1,base_dato2,etcenel
directorio/nuevo/directorio.

mysqlimport
Estaaplicacinsirveparacargardatosdesdearchivosdetextoatablas(esunaaplicacinsobrela
sentenciaLOAD DATA INFILE).
Elformatodelarchivodebeserunregistroporlneaycadacamposeparadoporundelimitador
(generalmenteunatabulacinounacoma).
Lasintaxisdelcomandoes:
mysqlimport [OPCIONES] base_datos archivo_datos1 [archivo_datos2 ...]

Elnombredelatablasedeterminarporelnombredelarchivo,quitandolecualquierextensinque
posea.Porlotanto,losarchivosAVION.txt,AVION.textoAVION.csvharnreferenciaalatablaAVION.

CarreraLinux2008ProgramacionPHP115
Entrelasopcionesdestacadaspodemosencontrar:
Opcin

Descripcin

-Esunalista(separadaporcomas)delosnombresdelas
columns=lista_c columnas.Deestaformaseconcordarnlascolumnasen
olumnas
elarchivodetextoconlacorrespondienteenlatablade
labasededatos.
--delete

Vacalatablaantesdeagregarlosregistros

--fieldsterminatedby=caracter

Determinaquecaractereseldelimitadordeloscampos.

--ignore

Encasodequesetratedeagregarunregistroqueya
existe(claveduplicada)elnuevoregistroseignorayse
continuainsertandolosdems.

--replace

Encasodequesetratedeagregarunregistroqueya
existe(claveduplicada)elviejoregistrosereemplaza
porelltimoysecontinuainsertandolosdems.

mysqlshow
Estaherramientanospermiteconsultarsobrelaestructuradelasbasesdedatos.
Susintaxises:
mysqlshow [OPCIONES] [base_datos [tabla [columna]]]

Estecomandomostrarinformacindependiendolacantidaddeargumentos,segnelorden
establecido.
Sinoselepasaningnargumento,mostrartodaslasbasesdedatosquehayaenelsistema.
Sisolsecompletaelargumentobase_datos,mostrartodaslastablasquehayadentrodedichabase
dedatos.
Siademssecompletatabla,entoncesmostrarlaestructuradelamisma.Incluyendotodaslas
columnas,consustiposdedatosydemsconfiguraciones.
Siseespecificcolumnasolosemostrarlainformacindelpuntoanteriorperosoloparalacolumna
especificada.
Entrelasopcionesdisponiblespodemosencontrar:
Opcin
--keys

Descripcin
Enelcasodeestaviendolainformacindeunatabla,tambinse
agregantodoslosndicescreadosobrelamisma.

--status Muestrainformacinextrasobrelastablas.

CarreraLinux2008ProgramacionPHP116

Ejercicios
1. ComoseaplicalaseguridadenMySQL?
2. Quesentenciasseposeenparamanejarusuarios?AquesublenguajedeSQLpertenecen?
Hastaquenivelpuedoaplicarlaseguridad?
3. Crearunusuario"stokes"concontrasea"akl84hg"paraquesolopuedaconsultarlastablasde
lasclasesanteriores.Corroborarqueelusuarionopuedacrear,borrarnimodificartablas.
4. Queherramientautilizariaparahacerunacopiaderespaldodeunabasededatos?Justifiquesu
respuesta

Clase19IndiceseIntegridadReferencial
Aumentandolavelocidaddeacceso
Cuandoseestatrabajandocontablasqueposeenpocosregistros,noesposiblenotarsielsistematiene
onounabuenaperformance.Demovida,concadaSELECTqueseejecutasedeberbarrertodoslos
registrosdelatablaparaencontraraquellosqueconcuerdenconelcriteriopedido.Alaumentarla
cantidadderegistroselsistemacomienzaavolversemsymslento,anparalasconsultasms
sencillas.Estoocurreyaquepararealizarunabsqueda,elmotornecesariamentenecesitarecorrerse
todalatabla(FULLSCAN)paraverificarqueregistrosconcuerdan.
Estasituacinpuedeydebeserremediadahaciendousodendices.Unndiceesunaestructuraauxiliar
lacualayudaaencontrarregistrossinnecesidaddehacerunbarridocompletodelatabla.Existen
variostiposdendicesperoactualmente,MySQLsoportasolountipo:elArbolB.
Losndicessecreansobreunaomscolumnasdeunatabla.Estoimplicaquetodaesainformacin
estar"duplicada",osea,queelndiceocuparunespaciounpocomayoraltamaototaldelas
columnasseleccionadas.Alusarelndiceseaumentarlavelocidadaltratarderecuperarregistrosen
baseaesascolumnasperotendrelcostodeactualizarsecuandoseinsertaoborraunafila.Esporeso
quelosndicespuedenserbeneficiososperosiseusanenexcesopuedenllegaranoserlo.
UnArbolBesunaestructuraqueposeeformaderbolquecrecedelarazhacialahojas.Enunarbl
habrunnodorazelcultendrNhijos.AsuvezcadahijodelarazpuedetenerNhijosyas
sucesivamente.Acadacaminoquesevaformandoselollamarama.Aquellosnodosqueseencuentren
alfinaldecadaramaselosdenominahoja.
SisearmaunArbolBsobreunacolumna,porejemploCODIGOdelatablaCLIENTES,enpromedio
parabuscarunCODIGOenunatablade1.000.000deregistros,tomar20accesos.Estevalores
muchomenorabarrerseelmillnderegistros.
Losndicessecrearnsobrelascolumnasenlascualeshagamosconsultasfrecuentemente.Porlo
expuestoanteriormente,noesbeneficiosoponerndicesentodaslascolumnas.Porlotanto,habrque
analizarqueconsultasseharnyendondeconvienecrearlosndices.
Internamente,MySQL,aldeterminaruna(s)columna(s)comoclaveprimaria,generarunndicenico
sobredichascolumnas.Porlotanto,sobrelaclaveprimariasiempresetienebuenavelocidadde

CarreraLinux2008ProgramacionPHP117
acceso.Estosedebeaquelasrelacionessiempresehacensobrelasclavesprimariasporlotantosino
seposeedichacolumnaindexadatomarmuchotiemporelacionardostablas.
Losndicespuedenonoaceptarvaloresduplicados.Sicreamosunndicenico,entonceslosvalores
deesacolumnanuncaserepetirn.CuandoutilizabamoselUNIQUEenelCREATETABLE,loquese
creaberaunndicequeasegurabaesto.
UnavezcreadoelndiceMySQLseencargarautomaticamentededeterminarcuandoconviene
utilizarloycuandono.Porlotanto,noharfaltaencadaconsultaescribirexplicitamentequendice
debeusarnicomo.
EnMySQLparacrearunndiceseutilizarelcomando:
CREATE [UNIQUE] INDEX nombre_indice ON tabla ( campos )

Endonde,lapalabraUNIQUEesopcionalydeterminasielndiceaceptaronoaceptarduplicados.
nombre_indiceessimplementeelnombrequeseladaralindice(parapodereliminarloluegosihace
falta).
tablaeselnombredelatablasobrelacualsecrearelndice.
Ycampossontodosloscampos(1oms)quetomarelndice.Sisenecesitanmsdeuncamposelos
debesepararporcomas.
Unavezcreadoelndiceesposibleeliminarlosihacefalta.ParaelloseutlizarelcomandoDROP
INDEXdelasiguienteforma:
DROP INDEX nombre_indice ON tabla

Endonde,nombre_indiceeselnombrequeseledialindicecuandosecreoytablaeselnombredela
tablasobrelacualestaelndice.

IntegridadReferencial
Cuandocomenzamosahablardebasededatoshicimosmencindelaintegridadreferencial.La
integridadreferencialsignificapoderdecirlealmotorexplcitamentequecampohacereferenciaaque
claveprimariadequetabla.Porlotanto,tendriamoslasrelacionesmetidasdentrodelmotor(reglasde
integridad),locualnosaseguraquelabasesiempreestaenunestadoconsistente.Estosignificaque
nuncaencontraramosrelacionesmalhechasocdigosquenoexisten.
Lastablasestandar(MyISAM)nopuedenutilizarintegridadreferencial.Paraellohayquecrearlas
tablasdeltipoInnoDBcomohemosvistoenclasesanteriores(utilizandolaopcinTYPEenel
CREATE TABLE).Ademsexisteotrarestriccin:paracrearunarelacinambascolumnas,laclave
forneacomolaclavereferenciada,debentenerunndicecreado.Estosedebeaqueenelcaso
contrario,laperformancedisminuirasignificativamenteconcadaINSERT,DELETEyUPDATEya
quelasreglasdeintegridadsedebenverificarencadaunadeestasoperaciones.
ParadefinirunarelacinentredostablasutilizaremoslasentenciaALTER TABLEdelasiguiente
forma:

CarreraLinux2008ProgramacionPHP118
ALTER TABLE tabla
ADD [CONSTRAINT nombre_constraint] FOREIGN KEY (columnas_clave_foranea)
REFERENCES tabla_independiente (columnas_independiente
[ ON DELETE CASCADE | SET NULL | NO ACTION | RESTRICT ]
[ ON UPDATE CASCADE | SET NULL | NO ACTION | RESTRICT ]

Aqutablaeslatablaqueposeeunacolumnaqueesclavefornea.Estaeslacolumnaquehar
referenciaaotratabla.
nombre_constrainteselnombrequeseledaralarelacin.Estaalternativa(esopcional)existe
simplementepararespetarelestndaryaqueMySQLlaignora.
columnas_clave_foraneasonelnombredelaolascolumnas(separadasporcomas)quehacen
referenciaalatablaindependiente.
tabla_independienteeslatablalacualesreferenciadaycolumnas_independientessuclaveprimaria
(quedebernconcordarconlasdecolumnas_clave_foranea).
Antesdeverlasotrasopcionesveamosunejemplo:
CREATE TABLE CLIENTES (
CES_ID INT UNSIGNED NOT NULL,
CES_RAZON_SOCIAL VARCHAR(50) NOT NULL,
CES_DIRECCION VARCHAR(100) NOT NULL
) TYPE=InnoDB;
ALTER TABLE CLIENTES ADD PRIMARY KEY (CES_ID);
CREATE TABLE VENTAS (
VAS_NUMERO INT UNSIGNED NOT NULL,
VAS_CES_ID INT UNSIGNED NOT NULL,
VAS_FECHA DATETIME NOT NULL,
VAS_MONTO_TOTAL DECIMAL(13,2) NOT NULL,
) TYPE=InnoDB;
ALTER TABLE VENTAS ADD PRIMARY KEY (VAS_NUMERO);
CREATE INDEX NDX_CLIENTES ON VENTAS (VAS_CES_ID);
ALTER TABLE VENTAS ADD FOREIGN KEY (VAS_CES_ID) REFERENCES CLIENTES (CES_ID);

Enesteejemplo,CLIENTESeslatablaindependiente.Ademssuclaveprimariaestacompuestaporla
columnaCES_ID.Porlotanto,todatablaquehagareferenciaauncliente,debeponerelcdigode
estacolumna.VENTASeslatablaquehacereferenciaauncliente.Porlotantosedefiniunacolumna,
VAS_CES_ID,quecontendrelcdigodelclientequerealizlaoperacin.Comoserunaclave
forneasecreunndicesobrelamisma.Luego,elALTER TABLEcorrespondienterelacionala
columnaVAS_CES_IDdelatablaVENTASconlacolumnaCES_ID(claveprimaria)delatabla
CLIENTES.
Comorecomendacinprcticadiremosqueesmejor,dentrodelscriptquegenerlabasededatos,

CarreraLinux2008ProgramacionPHP119
definirprimerotodaslastablasyluegotodaslasrelaciones.Deestaformasiemprequesevayaa
definirunarelacinyaseposeenlastablasintervinientescreadasynohayqueestarmoviendo
definicionesportodoelarchivoparaquealmomentodedefinirlarelacinambastablasexistan.
PorltimoveamoslasopcionesrestantesON DELETEyON UPDATE.Estareglasledicenalmotor
quehacerencasoqueseborreoactualiceelvalordelaclavereferenciada(enelejemploCES_IDde
CLIENTES).Hay4accionesposibles:CASCADE,SET NULL,NO ACTIONyRESTRICT.Las
accionessonsimilaresparaDELETEyUPDATEconlanicadiferenciaqueDELETEborrary
UPDATEactualizar.
LaopcinCASCADEpropagarlaoperacinalastablasreferenciadas.Enelejemplo,siborramosun
clienteseborrarndelatablaVENTAStodoslosregistrosquecontenganaesecliente.
LaalternativaSETNULLpondrelvalorNULLenlacolumnadelaclavefornea(VAS_CES_ID)siy
solosilacolumnaaceptavaloresnulos.Sinolosaceptanosepodrrealizarlaoperacin(elDELETE
oUPDATEfallarn).
LaopcinNO ACTION(norecomendada)notomarningunaaccinylabasequedarenunestado
inconsistente.
Finalmente,laopcinRESTRICTprohibirlaejecucondelDELETEodelUPDATEynuncapodrser
eliminadaoactualizadalaclaveprimariadelatablaindependiente.

Ejercicios
1.
2.
3.
4.
5.

Paraqueseutilizanlosindices?
Queventajastraeutilizarindices?
Quedesventajastraeutilizarindices?
Sepideagregartodaslasreglasdeintegridadreferencialalaagendacreadaanteriormente.
Sepideagregartodaslasreglasdeintegridadreferencialalsistemageneradoavoluntad.

Clase20PHPyMySQL
Introduccin
ParautilizarMySQLdesdePHPhayqueconocersolounpardefuncionesquevieneincluidascon
PHP.
LaideaeslamismaquealutilizarelclientedeMySQL:primerosedebecrearunaconexinyelegir
sobrequebasededatossequieretrabajar.Luegoesposibleejecutarlassentencias.
Paraejecutarunsentencialospasossern:ejecutarlasentenciaeirrecuperandodeaunalasfilasdel
resultado.

Creandounaconexin
ParaconectarseaunservidorMySQLseutilizalafuncinmysql_connect.Estafuncinlleva

CarreraLinux2008ProgramacionPHP120
comoparmetrosladireccindelservidor,conqueusuariosevaaconectarycualessucontrasea.
RecordemosquealinstalarMySQLpordefectosoloestaelusuariorootysincontrasea,quesibien
noeslomssegurosirveparapoderpracticar.
Lafuncinmysql_connectdevolverunrecursoatravesdelcualpodremosutilizarelmotorensu
totalidad.Encasodequelaconexinhayafalladoporalgunmotivo,mysql_connectdevolver
falso.
Ejemplo:
$link = mysql_connect("127.0.0.1", "root", "");
if(!$link) {
echo mysql_error($link). "<br>";
exit;
}

NOTA:lafuncinmysql_errordevuelveunacadenaconelerrordelaltimaoperacinrealizada.
Lafuncinexitterminalaejecucindelscript.

SeleccionandounaBasedeDatos
Elsiguientepasoeselegirsobrequebasededatossedeseatrabajar.Paraelloseemplealafuncin
mysql_select_dbquellevacomoparmetroselnombredelabasededatosylaconexincreada
anteriormente(quedevuelvemysql_connect).
Estafuncindevolververdaderosisepudorealizarlaoperacinyfalsoencasocontrario.
Ejemplo:
$ok = mysql_select_db("aviones", $link);
if(!$ok) {
echo mysql_error($link). "<br>";
exit;
}

Elejemploessimilaralanterior.Sifallanoserposibleutilizarlabasededatosyseterminale
ejecucindelscript.

EnviandoSentencias
ParaenviarcualquiersentenciadeSQLsepuedeutilizarlafuncinmysql_query.Estafuncinlleva
comoparmetrounacadenaconlasentencia(aqunohacefaltaponerelcarcter;)ylaconexinal
motor.
Comoestasentenciaesmuyutilizada,esposible(ymuycomn)llamarlasinelparmetrodeconexin.
Siestenoseespecifica,seutilizareldelaltimaconexinhecha.Comolamayoradelasvecesse
trabajaconunasolaconexin,nosahorradeescribirsiemprelavariabledelaconexin,aumentando,
adems,laposibilidaddeerroresdetipeoytiempoendepurarloluego.Enrealidad,todaslasfuncines
quellevencomoparmetrolaconexin,puedenomitirseseguramenteesteparmetroaltrabajarcon
unasolaconexin.

CarreraLinux2008ProgramacionPHP121
Estafuncindevuelveunrecursoquerepresentaelresultado.Sihuboalgnerrordevolverfalsoyla
funcinmysql_errornosdircualfueelerror.
Ejemplo:
$consulta = "INSERT INTO AVIONES VALUES (1, 'AeroExplote', 'Z')";
$ok = mysql_query($consulta);
if(!$ok) {
echo mysql_error(). "<br>";
}

EnesteejemplohemosagregadounafilaalatablaAVIONES.

Recuperandolosresultados
Unavezejecutadaunasentenciasernecesario,enocasiones,recuperarlosresultados.Algunas
sentencias,comoINSERT,UPDATEoDELETE,nodevuelvenningnresultado,encambio,el
SELECTdevuelveceroomsfilascomoresultado.
Pararecuperarlosresultadostenemos,enprincipio,dosfunciones:mysql_fetch_rowy
mysql_fetch_array.
Lafuncinmysql_fetch_rowirdevolviendodeaunolosresultadosenformadeunarreglocon
indicesnumricos.Devolverfalsounavezquesetratedeleermsalladelaltimafiladelresultado.
Ejemplo:
$consulta = "SELECT AES_ID, AES_AEROLINEA, AES_TIPO FROM AVIONES ORDER BY TIPO";
$resultado = mysql_query($consulta);
if(!$resultado) {
echo mysql_error(). "<br>";
}
echo "<TABLE ALIGN=CENTER BORDER=1>";
echo "<TR ALIGN=CENTER>";
echo "<TH>ID</TH>";
echo "<TH>Aerolinea</TH>";
echo "<TH>Tipo</TH>";
echo "</TR>";
while($avion = mysql_fetch_row($resultado)) {
echo "<TR>";
echo "<TD>$avion[0]</TD>";
echo "<TD>$avion[1]</TD>";
echo "<TD ALIGN=CENTER>$avion[2]</TD>";
echo "</TR>";
}
echo "</TABLE>";

EsteejemplocrearunatablaenHTMLconlosresultadosdelaconsulta.Paracadaciclodelwhile,se
cargarenelarreglo$avionunafiladelresultado,deformaqueenlaposicin0seencuentreelvalor
delaprimercolumnaseleccionada,enla1elvalordelasegundacolumnaseleccionadayas
sucesivamente.
Estafuncintieneladesventajaquealmodificarelordendeloscampos(oalagregar)losindicesse

CarreraLinux2008ProgramacionPHP122
modificarnyhabraqueretocarelcdigoportodaspartes.
Parasolventarestadeficienciapodemosutilizarlafuncinmysql_fetch_array.Estafuncin
operadelamismaformaquelaanterior,perodevuelveunarregloasociativo,endondelasclavessern
losnombresdelascolumnasseleccionadas.
Modificandoelejemploanteriornosquedara:
$consulta = "SELECT AES_ID, AES_AEROLINEA, AES_TIPO FROM AVIONES ORDER BY TIPO";
$resultado = mysql_query($consulta);
if(!$resultado) {
echo mysql_error(). "<br>";
}
echo "<TABLE ALIGN=CENTER BORDER=1>";
echo "<TR ALIGN=CENTER>";
echo "<TH>ID</TH>";
echo "<TH>Aerolinea</TH>";
echo "<TH>Tipo</TH>";
echo "</TR>";
while($avion = mysql_fetch_row($resultado)) {
echo "<TR>";
echo "<TD>$avion[AES_ID]</TD>";
echo "<TD>$avion[AES_AEROLINEA]</TD>";
echo "<TD ALIGN=CENTER>$avion[AES_TIPO]</TD>";
echo "</TR>";
}
echo "</TABLE>";

Comosepuedeapreciar,paraaccederalID,porejemplo,seharatravesde$avion["AES_ID"]
envezde$avion[0].Estodemuestraquelaposicinnoesimportantealutilizar
mysql_fetch_array.

Cerrandolaconexin
Paracerrarlaconexinseutilizalafuncinmysql_closequellevacomoparmetrolaconexin.Por
logeneralnoseutilizamuchoestafuncinyaquealfinalizarelscriptsecierranautomticamentetodas
lasconexionesabiertas.
Ejemplo:
mysql_close($link);

Funcionesvarias
Veremosotrasdosfuncionesquepuedenserdeutilidad:mysql_num_rowsymysql_insert_id.
Laprimeradeellasdevuelvelacantidaddefilasqueprodujounresultadovlidodevueltopor
mysql_query.
Ejemplo:

CarreraLinux2008ProgramacionPHP123
$consulta = "SELECT ID, AEROLINEA FROM AVIONES WHERE TIPO='A'";
$r = mysql_query($consulta);
echo "La consulta devolvio ". mysql_num_rows($r) . "<br>";

Lafuncinmysql_insert_iddevuelveelltimoidgeneradoautomticamenteporunacolumna
conatributoAUTO_INCREMENT.
Ejemplo:
$consulta = "INSERT INTO AVIONES VALUES (NULL, 'VueleBajo VueleTierra', 'W')";
mysql_query($consulta);
$id = mysql_insert_id();
echo "Se genero el avion cuyo ID es $id<br>";

DeestaformaesposiblecrearelIDautomticamenteyluegoutilizarlopararelacionarloenotras
tablas.

Ejercicios
1. Comosehacepararecuperarelresultadodeunaconsulta?
2. Quediferenciaspresentanlosdistintosmetodos?
3. Hacerunsistemaquepermitacargarencuestasdentrodeunabasededatos.Luegosedebera
crearunapaginaquemuestrelaencuestaactual(marcadaenlabasededatoscomotal)y
permitaalosusuariosvotarenlamisma,registrandoelvoto.
Luegosedeberacreaotrapaginaquepermitaconsultarelestadodecualquierencuestaviendo
cuantegentevotoencadaopcionyqueporcentajerespresentaelmismo.
4. Primero,considerelabasededatosdefinidaanteriormente.
Luegosedeseagenerarunapginaquepermitaconsultarlosvuelosdisponiblesyasignarlos
pasajesparadichosvuelos.
Elprimerpasoesgenerarunapginaquepermiteencontrarsihayvuelosdisponibles
mencionandoelOrigenyelDestino.Elsitiodebeinformarsobrequevuelostieneesetrayecto,
enquefechasalen,losaeropuertosdesalida/llegadaycantidaddepasajeslibresporclase.
Luegosedebepoderir,presionandosobreelvuelo,aotrapginaquedelainformacin
detalladadelvueloyqueseaposibleasignar(vender)pasajes.Estapaginadebeinformartodo
sobreelvuelo:queavineselquelorealiza(ID+AEROLINEA+TIPO),todassusescalas
(contodalainformacindelAeropuerto)conloshorarioscorrespondientesyenorden,eltotal
recaudadoporClaseconlacantidaddeasientosocupadosyeltotaldeasientos,yeltotal
recaudado.
Contodaestainformacinenpantallaelusuariopodrdecidirsiviajaronoenesevuelo.Luego
deberapresentarunlinkparairalaasignacindepasajes.Aquisedebenmostrartodoslos
asientosquehayaenelavin.Aquellosqueyaestanocupadoslosmarcarcomoocupadosylos
queestenlibresdeberponeruncheckboxalcostadoparapoderseleccionarlos.Contodoslos
asientosqueelusuariohayamarcadoseasignarnluegolospasajes.
5. SedesearealizarunpequeosistemaparagenerarunGuestBook.UnGuestBook(oLibrode
Visitas)sirveparaquelosnavegantesdejensusmensajesenlapginayqueestospuedanser

CarreraLinux2008ProgramacionPHP124
vistosportodoelmundo.
Elsistemadebepermitir:
Quelosusuariosdejenmensajes.Paraelloelusuariodeberacompletar:nombre,email,
calificaciondelsitioyelmensaje.Luegoelsistemaregistrarademslafechayhoraenquese
dejdichomensaje.Permitirverlosmensajesporpginas.Oseaquesedebenverlosltimos
10mensajes,permitiendovolverhaciaatrsdea10mensajeshastaqueseacaben.
Generaruncuadrobasadoenlacalificacinconlasiguienteforma:
+--------------------------------------+
| Calificacion | Cantidad | Porcentaje |
|--------------+----------+------------|
|
Excelente |
60 |
30% |
|--------------+----------+------------|
|
Muy Bueno |
40 |
20% |
|--------------+----------+------------|
|
Bueno |
60 |
30% |
|--------------+----------+------------|
|
Regular |
20 |
10% |
|--------------+----------+------------|
|
Pesimo |
20 |
10% |
+--------------------------------------+

Lascalificacionesdebenestarenunatabla(puedenserlascincomencionadas,opuedenser
msopuedensermenos,elsistemadebefuncionarparacualquiercantidad)yalusuariosele
deberpresentarel<SELECT>correspondienteparaqueeliga.

Vous aimerez peut-être aussi