Mostrando entradas con la etiqueta PHP. Mostrar todas las entradas
Mostrando entradas con la etiqueta PHP. Mostrar todas las entradas

miércoles, 19 de septiembre de 2012

CakePHP: Plugin para subir imágenes

Al fin pude descifrar una manera de subir imágenes en CakePHP 2.0. Probé este plugin de Jose Gonzalez y me funcionó adecuadamente. Puedo subir imágenes que se guardan en una estructura de carpetas fácilmente consultable por el identificador del modelo que se guarda en la base de datos. A parte genera los thumbnails en los tamaños que uno le defina.

Estos fueron los pasos que seguí:

1. Bajar el plugin.Se puede descargar el zip o bajar el código del repositorio de GitHub.

2. Se copia el código en la carpeta /app/Plugin/Upload (dejar la carpeta renombrada con Upload u otro nombre más amigable).

3. Se edita el "bootstrap.php" (/app/Config/) agregando la línea para habilitar el plugin:
CakePlugin::load('Upload');

4. En la base de datos, en la tabla donde se guarda la referencia a la foto, agregamos dos columnas: una para el identificador de la foto, y otra para el identificador del directorio:

CREATE TABLE  `mi_db`.`anuncios` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `titulo` varchar(45) NOT NULL,
  `id_foto` varchar(15) DEFAULT NULL,
  `dir` varchar(250) DEFAULT NULL,
)

5. En el modelo se configura las opciones para la subida de la imagen:

class Anuncio extends AppModel {
     
    public $actsAs = array(
        'Upload.Upload' => array(
            'id_foto' => array(
                'fields' => array(
                    'dir' => 'dir'
                ),                
                'thumbnailSizes' => array(
      'big' = '200x200',
                    'small' =>'120x120',
                    'thumb' =>'80x80'
                ),
                'thumbnailMethod'=> 'php'
            )
        )
    );
}

Observese que se configura los nombre de las columnas que configuramos en la tabla de nuestra base de datos, los tamaños de los thumbnails, y el método para crear los thumbnails (aquí uso php pues es una extensión que viene ya instalado por defecto en la mayoría de los ambientes de desarrollo tipo WAMP).

 6. Agrego el código de la vista:

<?php
 echo $this->Form->create('Anuncio', array('type' => 'file'));
 echo $this->Form->input('id_foto', array('type' => 'file', 'label' => 'Foto'));
 echo $this->Form->input('dir', array('type' => 'hidden'));
 echo $this->Form->end('Guardar Anuncio');
?>

7. ¡Listo! Las imágenes son guardadas dentro de 'webroot/files' (la ruta se puede configurar).


lunes, 20 de agosto de 2012

Provincias, cantones y distritos para seleccionar

Basado en una entrada anterior donde puse a disposición un script para crear las tablas que representan la estructura de provincias, cantones y distritos, he creado un script PHP que genera unos arreglos en JavaScript para poder utilizarlos en selectores de manera que carguen dinámicamente según la selección anterior. Básicamente, si selecciona una provincia, cargue los cantones de esa provincia, y si selecciona un cantón, cargue los distritos de ese cantón.

El script en PHP sería este:

<?php
 mysql_connect("localhost","root","") or die("Unable to connect to SQL server");
 @mysql_select_db("data_base_name") or die("Unable to select database"); 
  
 $provincias_result = mysql_query("select * from PROVINCIA_CR");
  
 echo "var p=new Array();var c=new Array();var d=new Array();";
 while ($provincia_row = mysql_fetch_row($provincias_result)) {
   
  echo "p[" . $provincia_row[0] . "]='" . $provincia_row[1] . "';";
   
  $cantones_result = mysql_query("select * from CANTON_CR where codigo_provincia = "
   . $provincia_row[0]);
   $canton_line = "c[". $provincia_row[0] . "]='"; 
   $distrito_lines = "";
   while ($canton_row = mysql_fetch_row($cantones_result)) {
    $canton_line = $canton_line . $canton_row[2] ."@" .  $canton_row[1] . "~";
     
    $distritos_result = mysql_query("select * from DISTRITO_CR where codigo_canton = "
     . $canton_row[0]);
      
    $distrito_line = "d[". $canton_row[1] . "]='";   
    while ($distrito_row = mysql_fetch_row($distritos_result)) {
      $distrito_line .= $distrito_row[2] ."@" .  $distrito_row[1] . "~";
    }
    $distrito_line=substr_replace($distrito_line ,"",-1); // Remueve último caracter.
    $distrito_lines .= $distrito_line . "';";
   }
   $canton_line=substr_replace($canton_line ,"",-1); // Remueve último caracter.
   echo $canton_line . "';";
   echo $distrito_lines;   
 }
?>
Este script genera un código como este (también dejo a disposición el script generado):
var p=new Array();var c=new Array();var d=new Array();p[1]='San José';c[1]='San José@1~Escazú@1~Desamparados@1~Puriscal@1~Tarrazú@1~Aserrí@1~Mora@1~Goicoechea@1~Santa Ana@1~Alajuelita@1~Vasquez de Coronado@1~Acosta@1~Tibás@1~Moravia@1~Montes de Oca@1~Turrubares@1~Dota@1~Curridabat@1~Pérez Zeledón@1~León Cortés@1';d[1]='Carmen@101~Merced@101~Hospital@101~Catedral@101~Zapote@101~San Francisco de Dos Ríos@101~Uruca@101~Mata Redonda@101~Pavas@101~Hatillo@101~San Sebastián@101';d[1]='Escazú@102~San Antonio@102~San Rafael@102';d[1]='Desamparados@103~San Miguel@103~San Juan de Dios@103~San Rafael Arriba@103~San Antonio@103~Frailes@103~Patarrá@103~San Cristóbal@103~Rosario@103~Damas@103~San Rafael Abajo@103~Gravilias@103~Los Guido@103';d[1]='Santiago@104~Mercedes Sur@104~Barbacoas@104~Grifo Alto@104~San Rafael@104~Candelaria@104~Desamparaditos@104~San Antonio@104~Chires@104';d[1]='San Marcos@105~San Lorenzo@105~San Carlos@105';d[1]='Aserrí@106~Tarbaca o Praga@106~Vuelta de Jorco@106~San Gabriel@106~La Legua@106~Monterrey@106~Salitrillos@106';d[1]='Colón@107~Guayabo@107~Tabarcia@107~Piedras Negras@107~Picagres@107';d[1]='Guadalupe@108~San Francisco@108~Calle Blancos@108~Mata de Plátano@108~Ipís@108~Rancho Redondo@108~Purral@108';d[1]='Santa Ana@109~Salitral@109~Pozos o Concepción@109~
...
Con ese código se puede agregar lógica JavaScript, sazonada con JQuery, para cargar las opciones dinámicamente:

Código en GitHub

<html>
<head>
 <script src="distritos.js" type="text/javascript"></script>
 <script src="jquery-1.7.1.min.js" type="text/javascript"></script> 
 <script type="text/javascript">  
  var separator1 = "~";
  var separator2 = "@";
  
  function cargarProvincias(provinciaId) {
   $("#" + provinciaId).append($("<option></option>")
    .attr("value", -1).text("Elija una provincia"));  
   for (var key in p) {
    $("#" + provinciaId).append($("<option></option>")
     .attr("value", key).text(p[key]));
   }
  }
  
  function cargarCantones(provincia, cantonId) {
   var provinciaSelectedValue =  $(provincia).val();
   $("#" + cantonId + " option").remove();
   
   if(provinciaSelectedValue != -1) {     
    $("#" + cantonId).append($("<option></option>")
     .attr("value", -1).text("Elija un cantón")); 
    
    var cantones = c[provinciaSelectedValue].split(separator1);
    
    for (var i=0; i < cantones.length; i++) {
     var cantonValuePair = cantones[i].split(separator2);
     $("#" + cantonId).append($("<option></option>")
     .attr("value", cantonValuePair[1]).text(cantonValuePair[0]));
    }    
   } else {
    $("#" + cantonId).append($("<option></option>")
     .attr("value", -2).text("Elija una provincia"));
   }
   cargarDistritos($("#" + cantonId), "distritos");
  }
  
  function cargarDistritos(canton, distritoId) {
   var cantonSelectedValue =  $(canton).val();
   $("#" + distritoId + " option").remove();
   
   if(cantonSelectedValue > 0) {      
    $("#" + distritoId).append($("<option></option>")
     .attr("value", -1).text("Elija un distrito")); 
    
    var distritos = d[cantonSelectedValue].split(separator1);
    
    for (var i=0; i < distritos.length; i++) {
     var distritoValuePair = distritos[i].split(separator2);
     $("#" + distritoId).append($("<option></option>")
     .attr("value", distritoValuePair[1]).text(distritoValuePair[0]));
    }    
   } else if(cantonSelectedValue == -1){
    $("#" + distritoId).append($("<option></option>")
     .attr("value", -1).text("Elija un cantón")); 
   } else if(cantonSelectedValue == -2){
    $("#" + distritoId).append($("<option></option>")
     .attr("value", -1).text("Elija una provincia")); 
   }
  }  
 </script> 
</head>

<body onload="cargarProvincias('provincias')">
 <select id="provincias" onchange="cargarCantones(this, 'cantones');"></select>
 <select id="cantones" onchange="cargarDistritos(this, 'distritos');"><option value="-2">Elija una provincia</option></select>
 <select id="distritos"><option value="-2">Elija una provincia</option></select>
</body>
</html>

Resultado Final:

lunes, 23 de julio de 2012

CakePHP: Carga dinámica de select input con JSON

Continuando con mis experiencias en este aprendizaje del framework CakePHP, quiero poner a disposición una receta en la cual tardé bastante en encontrar y personalizar, de cómo preparar una carga dinámica de un select box a partir de una selección anterior.

En este ejemplo cargo las opciones de raza a partir de una selección previa de una especie.

Ingredientes:


1. Función en el controlador para listar las especies (primer select box):

public function add() {  
   if ($this->request->is('post')) {
       // Código para salvar el anuncio.
    } else {
        $especie = new Especie();         
        $especies = $especie->find('list', array(       
     'fields' => array('Especie.id', 'Especie.nombre')
 ));
        $this->set('especies', $especies);         
    }
}

2. Código del formulario:
Form->create('Anuncio');
 
 echo $this->Form->input('especie', array(
     'type'    => 'select',
     'options' => $especies,
     'empty'   => 'Elija una especie'
 ));
 echo $this->Form->input('raza', array(
     'type'    => 'select',
     'empty' => 'Elija una especie'
 ));    
 echo $this->Form->end('Guardar Anuncio');
?>

3. Función en el controlador para retornar un JSON con las razas pertenecientes a la especie:

    public function getRazasByEspecie() {
     if ($this->request->is('ajax')) { 
      $idEspecie = $this->params['data']['idEspecie'];
       
      $raza = new Raza();
      $razas = $raza->find('all',array(
       'fields' => array('Raza.id', 'Raza.nombre'), 
       'conditions'=>array('Raza.id_especie'=>$idEspecie)));
      
      $this->RequestHandler->respondAs('json');
      $this->autoRender = false;      
      echo json_encode ( $razas );      
     }
    }

Preparación:

Agregar el código JavaScript que una (binding) la siguente lógica al evento de modificación del primer select box. La función hace un llamado Ajax al controlador para pedir las razas. Estas son retornadas en formato JSON el cual es procesado para agregar las nuevas opciones del segundo select box.
$(document).ready(function(){

 $('#AnuncioEspecie').change(function(){
  var selected = $(this).val();
    
  $.ajax({
   type: "POST",
   url: '/Anuncios/getRazasByEspecie',
   data: "idEspecie="+selected,
   dataType: 'json',
   success: function(data){
    
    $('#AnuncioRaza option').remove();
    var $el = $("#AnuncioRaza");
    if (data.length > 1) {
     $el.append($("")
       .attr("value", -1).text("Elija una raza"));
    }
    $.each(data, function(i,items){
     $el.append($("")
       .attr("value", items.Raza.id).text(items.Raza.nombre));          
    });    
   }
  });
 });
});


Consumase al gusto :D!

miércoles, 27 de junio de 2012

CakePHP: Llenando un combo box

Aca estoy iniciando con mis primeros pasos en este framework que hasta el momento pinta muy bien. La documentación que existe en el sitio oficial donde exponen un caso de ejemplo desarrollando un blog es verdaderamente muy útil. Solamente me quedé un poco atascado en el desarrollo de mi propio ejemplo queriendo llenar un combo box.

En mi caso quería tener una pantalla para agregar una mascota seleccionando la raza a la que pertenece.  Para ello necesito poder mostrar las razas que se encuentran en una tabla aparte de la de mascotas.

Al final la solución que encontré fue la de importar la clase modelo "Raza" para poder hacer un "find" y mandar los resultados a la vista utilizando una notación especial para que se ajuste bien a un combo box.

Controlador

<?php
App::import('Model', 'Raza');

class MascotasController extends AppController {
    public $helpers = array('Html', 'Form');
    
    public function add() {  
        if ($this->request->is('post')) {
           // Código para salvar la mascota.
        } else {
            $raza = new Raza();          
            $razas = $raza->find('list', array(       
                  'fields' => array('Raza.id', 'Raza.nombre')
            ));
            $this->set('razas', $razas);         
        }
    }
}

Vista

<h1>Agregar Mascota</h1>
<?php
echo $this->Form->create('Mascota');
echo $this->Form->input('nombre');
echo $this->Form->input('raza', array(
    'type'    => 'select',
    'options' => $razas,
    'empty'   => false
));
echo $this->Form->end('Guardar Mascota');
?>

lunes, 19 de marzo de 2012

PHP: Probar conexión a base de datos

Script sencillo para probar que hay conexión a la base de datos:


<?php
$host = '<TYPE_HOST>';
$user = '<TYPE_USER>';
$pass = '[TYPE_PASS>';
$db = '<TYPE_DB>';

mysql_connect($host,$user,$pass) or die('error connection');
mysql_select_db($db) or die('error database selection');

echo "Connection successful!";
?>

jueves, 25 de agosto de 2011

PHP Cache

Una estrategia de cache es siempre una de las primeras opciones a tomar cuando se requiere mejorar el desempeño de una aplicación. Recientemente tuve que buscar una opción disponible para una aplicación web que estabamos trabajando en PHP, y de las que consulté por Internet, me quedé con la que ofrece este amigo en este artículo.

Esta clase PHPCache utiliza una tabla en base de datos con tres columnas como mecanismo de almacenamiento del cache:
  • PHPCache_key: la llave del objeto a guardar
  • PHPCache_value: el valor a guardar
  • PHPCache_expires: cuando expira el objeto en cache
Nuestro amigo ofrece un código que ejemplifica muy bien el uso de la clase:

require_once 'phpcache.class.php'; // Se incluye la clase de PHPCache.

// Parametros de conexión de la Base de datos.
$database = array(
'type' => 'mysql',
'name' => 'YOUR DATABASE NAME',
'table' => 'PHPCache',
'user' => 'YOUR DATABASE USERNAME',
'pass' => 'YOUR DATABASE USERNAME\'S PASSWORD',
'host' => 'localhost' /* Or maybe IP address of your database server */
);

// Llamado de configuración de la base de datos.
PHPCache::configure($database);
// Se obtiene una única instancia (patrón Singleton).
$cache = PHPCache::instance();

// Se pregunta primero si los resultados ya están en cache.
if( ($results = $cache->get('result_of_some_nasty_code')) !== false ) {
$tpl->assign($results);
/* Or maybe return $results or whatever depending on where you use this */
} else {
// Los datos todavía no estan en cache. Hay que obtenerlos de la manera lenta.
/***********************
* Your slow code here
***********************/
// Inmediatamente se guardan en cache. La siguiente vez no se hará de la forma lenta.
$cache->store('result_of_some_nasty_code', $results_of_your_slow_code, PHPCACHE_1_HOUR * 5); /* Cache for 5 hours */
}

miércoles, 10 de agosto de 2011

PHP: Cálculo de semana laboral actual

Dejo a disposición un código que permite obtener la semana laboral actual (lunes a viernes tomando domingo como inicio de semana).

Salida del código:

From: 08-08-2011 To: 08-12-2011


<?php


class DateUtils {

public static function get_current_date() {
return substr(DateUtils::get_current_date_time(), 0, 10);
}

public static function get_current_date_time() {
return date('Y-m-d H:i:s');
}

public static function get_day_of_current_week_as_number() {
return date("w",mktime());
}

public static function get_day_of_week_as_number($date_as_string) {
return date("w", strtotime($date_as_string));
}

public static function substract_days_to_current_date($days) {
$operation = "-";

if ($days < 0) {
$operation = "+";
$days = abs($days);
}
$newdate = strtotime ( $operation. $days .' day' ,strtotime ( date('Y-m-d') )) ;
return date ( 'm-d-Y' , $newdate );
}

public static function substract_days_to_date($date_as_string, $days) {

$operation = "-";

if ($days < 0) {
$operation = "+";
$days = abs($days);
}
$newdate = strtotime ( $operation . $days .' day' , strtotime ( $date_as_string) ) ;
$newdate = date ( 'm-d-Y' , $newdate );
return $newdate;
}

public static function get_start_day_of_current_work_week() {
$monday_delta = 0;
$current_day_of_week = DateUtils::get_day_of_current_week_as_number();

if($current_day_of_week > 1) {
$monday_delta = $current_day_of_week-1;
} else if($current_day_of_week == 0){
$monday_delta = -1;
}
return DateUtils::substract_days_to_current_date($monday_delta);
}

public static function get_start_day_of_work_week($date_as_string) {
$monday_delta = 0;
$day_of_week = DateUtils::get_day_of_week_as_number($date_as_string);

if($day_of_week > 1) {
$monday_delta = $day_of_week-1;
} else if($day_of_week == 0){
$monday_delta = -1;
}
return DateUtils::substract_days_to_date($date_as_string, $monday_delta);
}

public static function get_delta_for_end_day_of_work_week($current_day_of_week) {
$friday_delta = 0;

switch ($current_day_of_week) {
case 0: // Sunday.
$friday_delta=-5;
break;
case 1: // Monday.
$friday_delta=-4;
break;
case 2: // Tuesday.
$friday_delta=-3;
break;
case 3: // Wednesday.
$friday_delta=-2;
break;
case 4: // Thursday.
$friday_delta=-1;
break;
case 5: // Friday.
$friday_delta=0;
break;
case 6: // Saturday.
$friday_delta=1;
break;
}
return $friday_delta;
}

public static function get_end_day_of_current_work_week() {
$friday_delta = 0;
$current_day_of_week = DateUtils::get_day_of_current_week_as_number();

return DateUtils::
substract_days_to_current_date(DateUtils::
get_delta_for_end_day_of_work_week($current_day_of_week ));
}

public static function get_end_day_of_work_week($date_as_string) {
$friday_delta = 0;
$current_day_of_week = DateUtils::get_day_of_week_as_number($date_as_string);

return DateUtils::
substract_days_to_date($date_as_string, DateUtils::
get_delta_for_end_day_of_work_week($current_day_of_week ));
}

public static function get_current_work_week_range() {
return "From: " . DateUtils::get_start_day_of_current_work_week() . " To: "
. DateUtils::get_end_day_of_current_work_week();
}

}
echo "<h1>" . DateUtils::get_current_work_week_range() . "</h1>";
?>


viernes, 17 de junio de 2011

PHP: Leer un XML usando DOMDocument

Dejo a disposición un ejemplo sencillo de como leer un XML con la clase DOMDocument.

XML:

<catalog>
<catalog-name>My Favorite Music</catalog-name>
<cd id="cd-001">
<title value="Empire Burlesque" />
<artist value="Bob Dylan" />
<country value="USA" />
<company value="Columbia" />
<price value="10.90" />
<year value="1985" />
</cd>
<cd id="cd-002">
<title value="Hide your heart" />
<artist value="Bonnie Tyler" />
<country value="UK" />
<company value="CBS Records" />
<price value="9.90" />
<year value="1988" />
</cd>
<cd id="cd-003">
<title value="Greatest Hits" />
<artist value="Dolly Parton" />
<country value="USA" />
<company value="RCA" />
<price value="9.90" />
<year value="1982" />
</cd>
</catalog>

Código:

<?php
$cdCatalogXMLReader = new CDCatalogXMLReader();
$cdCatalogXMLReader->showCatalogAsTable('cd-catalog.xml');

class CDCatalogXMLReader {
public function showCatalogAsTable($xmlPath) {
// Loads XML.
$doc = new DOMDocument();
$doc->load($xmlPath);

// Reading tag's value.
$title = $doc->getElementsByTagName("catalog-name")
->item(0)->nodeValue;

echo "<h1>$title</h1>";

// Reading all elements with tag name="cd".
$cds = $doc->getElementsByTagName( "cd" );
echo '<table border="1">';
echo '<tr><th>ID</th><th>Title</th><th>Artist</th><th>Country</th><th>Company</th><th>Price</th><th>Year</th></tr>';

foreach ($cds as $cd) {
echo '<tr>';
// Reading attributes.
echo '<td>' . $cd->getAttribute('id') . '</td>';
echo '<td>' . $cd->getElementsByTagName("title")->item(0)->getAttribute('value') . '</td>';
echo '<td>' . $cd->getElementsByTagName("artist")->item(0)->getAttribute('value') . '</td>';
echo '<td>' . $cd->getElementsByTagName("country")->item(0)->getAttribute('value') . '</td>';
echo '<td>' . $cd->getElementsByTagName("company")->item(0)->getAttribute('value') . '</td>';
echo '<td>' . $cd->getElementsByTagName("price")->item(0)->getAttribute('value') . '</td>';
echo '<td>' . $cd->getElementsByTagName("year")->item(0)->getAttribute('value') . '</td>';
echo '</tr>';
}
echo '</table>';
}
}
?>

Salida:

My Favorite Music

IDTitleArtistCountryCompanyPriceYear
cd-001Empire BurlesqueBob DylanUSAColumbia10.901985
cd-002Hide your heartBonnie TylerUKCBS Records9.901988
cd-003Greatest HitsDolly PartonUSARCA9.901982

lunes, 16 de mayo de 2011

PHP: Desplegar datos de cualquier tabla MySQL


Si alguna vez necesitan hacer una página rápida de prueba para desplegar los datos de cualquier tabla MySQL, aquí les dejo esté código que encontré en este post. Solamente hay que cambiar los datos de conexión y la tabla que desean desplegar.

<?php

//MyDB represents the name of your database.
//MyTable represents the name of your table inside the database.

mysql_connect("localhost","my_user","my_pass") or die("Unable to connect to SQL server");
@mysql_select_db("my_database") or die("Unable to select database");


$result = mysql_query("select * from MY_TABLE limit 500");
?>
<table border="1">
<tr>
<?php


while ($field=mysql_fetch_field($result)) {
echo "<th>";
echo "$field->name";
echo "</th>";
}
echo "</tr>";

while ($row = mysql_fetch_row($result)) {
echo "<tr>";
for ($i=0; $i<mysql_num_fields($result); $i++) {
echo "<td>";
if (isset($row[$i]))
echo "$row[$i]";
else
echo "-";
echo "</td>";
}
echo "</tr>\n";
}

echo "</table>";

?>

lunes, 11 de abril de 2011

PHP: Configurando bien el path para tus galletas

Recientemente me di cuenta que el parámetro ´path ´ es necesario a la hora de configurar una galleta (cookie en inglés) si se quiere que otra página en un path diferente (no en un subdominio diferente) pueda accesarla. Me tomó rato descubrir esta verdad elemental de las galletas.

Si se desea que cualquier path del mismo subdominio pueda leer la galleta, entonces el path se pone con la típica barra inclinada que representa el directorio raíz.

setcookie("cookieName", "cookieValue", time() * 3600 * 24 * 30 /*30 days*/, "/");

miércoles, 6 de abril de 2011

Diccionario Java-PHP

Dado que recientemente he tenido que meterme a codificar un poco en PHP, he decidido mantener una entrada de post para ir traduciendo sentencias de lenguaje Java a PHP. Esto dado que se puede decir que Java es mi "lenguaje nativo". Me resulta más fácil imaginarme como lo haría en Java y luego simplemente buscar su traducción a PHP.


Pare revisar que una cadena no es nula y no viene vacía

Java
if (someString != null && someString != "") { // Do something.}
PHP
if (isset(someString) && ! empty(someString)) { // Do something. }

Pare revisar si una cadena está contenida en otra

Java
if (plainString.contains("foo!")) { // Do something. }
PHP
if (strpos($plainString, "foo!") !== false) { // Do something. }

Reemplazar una secuencia de caracteres por otra

Java
myString = myString.replace("x", "y");

PHP
str_replace("x", "y", myString);



Obtener el tamaño de un arreglo


Java
int size= array.length;

PHP
$size = count($array);