Como poner Tooltips de ayuda en una forma de Zend_Form usando Dojo

Mayo 19th, 2009  |  Published in PHP, Zend Framework, Zend_Form

Existen situaciones en las que un label en una forma no es sucifiente para explicar lo que quieres que el usuario capture en el campo… hay que dar una mejor explicacion,

una idea es poner iconos de ayuda enseguida de los campos y sacar un tooltip con la explicacion del campo.

El tip original lo obtuve de un blog Aleman aqui: http://www.scriptblogger.de/dijit-tooltips-und-zend_form-213.html

Pero aqui va una version en español con algunas modificaciones.

Tengo mi forma en una clase que extiende a Zend_Form y en los elementos que quiero que tengan un icono de ayuda les pongo un label y una description de la siguiente forma (mas abajo explico de donde viene):

class Mi_Forma extends Zend_Form {
 
	public function __construct($options = null)
	{
		$view = Zend_Layout::getMvcInstance()->getView();
		parent::__construct($options);
		Zend_Dojo::enableForm($this);
 
		$this->addElement('text', 'nombre', array(
			'label'		=> $view->instructionTooltip('Nombre', 'nombreAyuda', 'label'),
			'description' => $view->instructionTooltip('Escribe tu nombre aqui', 'nombreAyuda', 'description')
		));
	}
 
}

Si se fijan, el label y la description estan mandando llamar a un Helper de la vista, el Helper es este:

class Mi_View_Helper_InstructionTooltip {
 
	public $view;
 
	public function setView(Zend_View_Interface $view)
	{
		$this->view = $view;
	}
 
	public function instructionTooltip($text, $id, $mode = 'label')
	{
		if ($mode == 'label') {
			return $text . '<span id="' . $id . '" class="formaAyuda">?</span>';
		}
		if ($mode == 'description') {
			return '<span dojoType="dijit.Tooltip" style="display:none;" connectId="' . $id . '" id="' . $id . '_tooltip">' . $text . '</span>';
		}
	}
 
}

Ahora, hay que poner unas clases en nuestro CSS

.formaAyuda {
	font-size:0.7em;
	font-weight:normal;
	color:#0000FF;
	border:1px solid #7EABCD;
	-moz-border-radius:15px;
	-webkit-border-radius:15px;
	margin-left:0.5em;
	margin-right:2em;
	padding-left:4px;
	padding-right:4px;
}

Como implementar un paginador usando Zend_Paginator en Zend Framework 1.6RC

Julio 27th, 2008  |  Published in Zend Framework

Una de las cosas nuevas que trae el Zend Framework 1.6RC es el Zend_Paginator, y una forma de implementarlo es la siguiente:

Model

Para este ejemplo, vamos a suponer que tenemos una tabla users con las columnas id y nombre en MySQL con el siguiente modelo simple.

class User extends Zend_Db_Table
{
	protected $_name = 'users';
	protected $_primary = 'id';
 
}

Controller

En nuestro controller, necesitamos obtener los datos del modelo, crear el paginador y la vista parcial de los controles del paginador.

class UsersController extends Zend_Controller_Action
{
 
	public function indexAction() 
	{
		// Set pagination settings
		$page = $this->_getParam('page', 1);
		$itemCountPerPage = 10;
		$pageRange = 10;
 
		// Get data
		$user_model = new User();
		$users = $user_model->fetchAll()->toArray();
 
		// Create paginator
		$paginator = Zend_Paginator::factory($users);
		$paginator->setItemCountPerPage($itemCountPerPage)
				  ->setCurrentPageNumber($page)
				  ->setPageRange($pageRange);
 
		// Create paginator control partial view
		Zend_View_Helper_PaginationControl::setDefaultViewPartial('users/_partials/search_pagination_control.phtml');
 
		// Assign paginator to view
		$this->view->paginator = $paginator;
	}

View

Para este ejemplo, tenemos dos views, uno parcial en donde van los controles del paginador y el otro en donde va el paginador en si, empezamos con el view /views/users/index.phtml

<h1>Users</h1>
<?php if (count($this->paginator)) { ?>
	<?php foreach ($this->paginator as $item) { ?>
		<?php echo $item['nombre']; ?><br />
	<?php } ?>
<?php } ?>
<br />
<?php echo $this->paginationControl($this->paginator); ?>

La ultima función, es un Helper que renderea los controles del paginador, mandando llamar a la vista parcial que definimos en nuestro controlador, y va mas o menos asi:

<?php if ($this->pageCount): ?> 
<div id="paginationControl">
<!-- Previous page link --> 
<?php if (isset($this->previous)): ?> 
	<a href="<?= $this->url(array('page' => $this->previous)); ?>">&lt; Previous</a> | 
<?php else: ?> 
	<span class="disabled">&lt; Previous</span> | 
<?php endif; ?> 
 
<!-- Numbered page links -->
<?php foreach ($this->pagesInRange as $page): ?> 
	<?php if ($page != $this->current): ?>
		<a href="<?= $this->url(array('page' => $page)); ?>"><?= $page; ?></a> | 
	<?php else: ?>
		<?= $page; ?> | 
	<?php endif; ?>
<?php endforeach; ?>
 
<!-- Next page link --> 
<?php if (isset($this->next)): ?> 
	<a href="<?= $this->url(array('page' => $this->next)); ?>">Next &gt;</a>
	<?php else: ?> 
		<span class="disabled">Next &gt;</span>
	<?php endif; ?> 
</div> 
<?php endif; ?>

Nota: Este ejemplo fue tomado y adaptado del demo y source original del Zend_Paginator antes de su versión oficial

Como instalar, configurar y crear un bootstrap para Zend Framework 1.5

Julio 25th, 2008  |  Published in Zend Framework

Intro

Existen muchas formas y mejores de crear un archivo de bootstrap para Zend Framework 1.5 como cargar las librerias de forma dinámica en donde se necesitan etc, esta es una guia sencilla de como instalar y crear una forma de configurar el Zend Framework 1.5, algunos tips para esta guia fueron obtenidos de aqui.

Para esta guia, vamos a suponer que se esta utilizando Apache en Linux y estamos accesando al servidor en la dirección http://localhost/

Instalación

Para instalar el Zend Framework 1.5, solo hay que bajarlo de aqui y descomprimir el archivo. Notamos que hay un directorio que se llama library, lo vamos a copiar a donde va a estar nuestra aplicacion en un momento.

En donde va a estar nuestra aplicación, vamos a crear esta estructura de directorios:

application/
	config/
	controllers/
	models/
	views/
library/
public_html/
tmp/
	logs/

El directorio application/, va a tener todos los Models, Views y Controllers de la aplicación.

Dentro del folder library/, vamos a copiar el contenido del folder library/ que extrajimos del Zend Framework 1.5

El Apache debe de tener a public_html/ como directorio raíz.

tmp/

El directorio tmp/ y todos sus subdirectorios deben de tener permiso de escritura, se asigna con el siguiente comando:

# chmod -R 777 tmp

.htaccess

Ahora, dentro del directorio public_html/ vamos a hacer dos cosas, primero vamos a crear el archivo .htaccess en donde le vamos a decir al webserver que todas las solicitudes se enruten al archivo index.php de la siguiente forma:

RewriteEngine on 
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php

Nota: Es necesario tener habilitado el modulo mod_rewrite en Apache

index.php

Después creamos el archivo public_html/index.php con el siguiente contenido:

<?php 
require '../bootstrap.php';

Hasta este punto, todas las solicitudes a http://localhost/ serán enrutadas al archivo index.php. Como pueden ver, el archivo index.php solamente manda llamar al archivo bootstrap.php, que por razones de seguridad, se encuentra un directorio abajo, y fuera del directorio raíz del webserver. Mas adelante vamos a crear este archivo, primero vamos a crear un archivo en donde va a estar la configuración de la aplicación.

config.php

El archivo de configuración lo vamos a guardar en application/config/config.php:

$config = array(
				'environment'=>'development',
				'enable_database' => true,
				'enable_file_logger' => true,
				'enable_db_logger' => true
			   );
 
if ($config['enable_database']) {
	$config['database'] = array(
								'host' => 'localhost',
								'user' => 'db_username',
								'pass' => 'db_password',
								'name' => 'db_name'
							   );
 
	if ($config['enable_db_logger']) {
		$config['db_logger'] = array(
									 'log_table' => 'log_table',
									 'column_mapping' => array('priority' => 'priority', 'timestamp' => 'timestamp', 'priority_name' => 'priorityName', 'message' => 'message')
									);		
	}
}
 
if ($config['enable_file_logger']) {
	$config['file_logger'] = array(
								   'log_format' => '%timestamp% %priorityName% (%priority%): %message%' . PHP_EOL,
								   'file_name' => date("Y-m-d") . '.php'
								   );
}

Nota: El único proposito de este archivo es asignar los datos de configuración a la variable $config en forma de arreglo. La vamos a utilizar después en nuestro bootstrap.php

Los datos se explican por si solos, en $config['database'] va la información de la conexión a la base de datos.

En $config['db_logger'] ponemos el nombre de la tabla en la que se van a guardar los logs, y las columnas.
Nota: Es necesario que la tabla y las columnas existan en la base de datos para que funcione, las columnas deberan ser: priority, timestamp, priority_name y message.

En $config['file_logger'] va la información del formato del log, y del nombre del archivo, en este caso, estamos utilizando la funcion date() para crear un archivo de log para cada dia.

Los datos que estan dentro de la variable $config, van a poder ser accesibles en toda la aplicación gracias a que las guardaremos en el Zend_Registry en nuestro boostrap.php en la siguiente explicación.

bootstrap.php

El archivo bootstrap.php debe de estar en el directorio raíz (es decir, en donde esta el resto de la estructura de directorios application, config, ypublic_html y tmp):

$dirs = array(
	'app' => 'application',
	'web' => 'public_html',
	'lib' => 'library',
	'tmp' => 'tmp',
	'log' => 'tmp/logs'
);
 
define('APP_DIR', dirname(__FILE__) . DIRECTORY_SEPARATOR . $dirs['app'] . DIRECTORY_SEPARATOR);
define('WEB_DIR', dirname(__FILE__) . DIRECTORY_SEPARATOR . $dirs['web'] . DIRECTORY_SEPARATOR);
define('LIB_DIR', dirname(__FILE__) . DIRECTORY_SEPARATOR . $dirs['lib'] . DIRECTORY_SEPARATOR);
define('TMP_DIR', dirname(__FILE__) . DIRECTORY_SEPARATOR . $dirs['tmp'] . DIRECTORY_SEPARATOR);
define('LOG_DIR', dirname(__FILE__) . DIRECTORY_SEPARATOR . $dirs['log'] . DIRECTORY_SEPARATOR);
 
/* Report all errors directly to the screen for simple diagnostics in the dev environment */  
error_reporting(E_ALL | E_STRICT);  
ini_set('display_startup_errors', 1);  
ini_set('display_errors', 1); 
date_default_timezone_set('America/Mexico_City');
 
set_include_path(LIB_DIR . get_include_path());  
 
/* Set up autoload so we don't have to explicitely require each Zend Framework class */ 
require_once "Zend/Loader.php"; 
Zend_Loader::registerAutoload(); 
 
/* Load Configuration */
require_once(APP_DIR . 'config/config.php');
try {
	$config = new Zend_Config($config);
} catch (Zend_Exception $e) {
	echo "Error: " . $e->getMessage();
}
Zend_Registry::set("config", $config);
 
if ($config->enable_file_logger) {
	/* Create a log formatter */
	$formatter = new Zend_Log_Formatter_Simple($config->file_logger->log_format);
 
	/* Create a file logger */
	$stream = @fopen(LOG_DIR . $config->file_logger->file_name, 'a', false);
	if (!$stream) {
		throw new Exception('Failed to open stream');
	}
	try {
		$fileWriter = new Zend_Log_Writer_Stream($stream);
		$fileWriter->setFormatter($formatter);
		$fileLogger = new Zend_Log($fileWriter);
		Zend_Registry::set("fileLogger", $fileLogger);
	} catch (Zend_Log_Exception $e) {
		echo "Error: " . $e->getMessage();
	} catch (Zend_Exception $e) {
		echo "Error: " . $e->getMessage();
	}
}
 
if ($config->enable_database) {
	/* Load database */
	$options = array(
		Zend_Db::AUTO_QUOTE_IDENTIFIERS => true,
	);
	try {
		$db = new Zend_Db_Adapter_Pdo_Mysql(array(
			'host'     => $config->database->host,
			'username' => $config->database->user,
			'password' => $config->database->pass,
			'dbname'   => $config->database->name,
			'options'  => $options,
		));
		$db->getConnection();
		Zend_Db_Table::setDefaultAdapter($db);
		Zend_Registry::set("database", $db);
		} catch (Zend_Db_Adapter_Exception $e) {
			if ($config->enable_file_logger) {
				$fileLogger->log('Database Error: ' . $e->getMessage(), 1);
			}
		} catch (Zend_Exception $e) {
			if ($config->enable_file_logger) {
				$fileLogger->log('Error: ' . $e->getMessage(), 1);
			}
	}
 
	if ($config->enable_db_logger) {
		/* Create a database logger */
		try {
			$dbWriter = new Zend_Log_Writer_Db($db, $config->log_table, $config->column_mapping);
			$dbLogger = new Zend_Log($dbWriter);
			Zend_Registry::set("dbLogger", $dbLogger);
			} catch (Zend_Exception $e) {
				if ($config->enable_file_logger) {
					$fileLogger->log("Error: " . $e->getMessage() . " - " . $e->getFile() . " - Line: " .  $e->getLine(), 4);
				}
		}		
	}
}
 
/* Dispatcher */
try {
	$frontController = Zend_Controller_Front::getInstance(); 
	$frontController->setControllerDirectory(APP_DIR . "controllers"); 
	$frontController->dispatch();
} catch (Zend_Exception $e) {
	if ($config->enable_db_logger) {
		$dbLogger->log("Error: " . $e->getMessage() . " - " . $e->getFile() . " - Line: " .  $e->getLine(), 1);		
	}
	if ($config->enable_file_logger) {
		$fileLogger->log($e->getMessage(), 1);
	}
}

Nota: En este archivo solo hay que asignar los directorios y el timezone

Al final, te debió de haber quedado esta estructura de archivos y directorios:

application/
	config/
		config.php
	controllers/
	models/
	views/
library/
	Zend/
		...toda la libreria zend aqui.
public_html/
	.htaccess
	index.php
tmp/
	logs/

Recuerda que dentro del Zend_Registry guardamos varios elementos:

  • config: Que es un objeto de Zend_Config que contiene todos los datos que pusimos dentro del archivo config.php
  • fileLogger: Objeto de tipo Zend_Log con el que podemos loggear en archivos.
  • dbLogger: Objeto de tipo Zend_Log con el cual se loggea dentro de la base de datos.

Un tip extra, dentro de la aplicación, podemos utilizarlos haciendo llamadas como esta:

public function log_error($error) {
	$config = Zend_Registry::get('config');
	if ($config->enable_file_logger) {
		$fileLogger = Zend_Registry::get('fileLogger');
		$fileLogger->log($error, 3);
	}
	if ($config->enable_db_logger) {
		$dbLogger = Zend_Registry::get('dbLogger');
		$dbLogger->log($error, 3);
	}
}

Espero les haya servido de algo… comentarios bienvenidos.

Como verificar si un email en realidad existe usando PHP

Julio 16th, 2008  |  Published in PHP

Existen muchas formas de verificar si un email en realidad es válido, una de ellas es http://verify-email.org/ y de aqui surge la idea de este script, que aunque puede contener errores o no funcionar para todos los servidores de email, es una solucion rápida para verificar emails en PHP.

$email = "email@test.org"; // the email you want to verify
list($userName, $mailDomain) = split("@", $email);
$mxhosts = array();
if (getmxrr($mailDomain, $mxhosts)) {
	// it is a valid MX record...
	foreach ($mxhosts as $mxhost) { // checks for all mxhosts...
		$fp = fsockopen($mxhost, 25);
		if (!$fp) {
			// couldnt connect to mxhost...
			$verified = false;				
			continue;
		} else {
			// it was  connected to mxhost...
			$string = "HELO verify-email.org\r\n";
			fputs($fp, $string);
			$buffer = fgets($fp,4096);
			$string = "MAIL FROM: <check@verify-email.org>\r\n";
			fputs($fp, $string);
			$buffer = fgets($fp,4096);
			$string = "RCPT TO: <".$email.">\r\n";
			fputs($fp, $string);
			$buffer = fgets($fp,4096);
			if (substr($buffer,0,3)!='250') {
				$verified = false;
			} else {
				$verified = true;
			}
			break;
		}
		fclose($fp);
	}
} else {
	$verified = false;
}
 
if ($verified) {
	// this is a valid email...
} else {
	// this is an invalid email...
}

NOTA: Este script se conecta a los servidores de email del destinatario, no es recomendable utilizar el script dentro de un ciclo, ya que además de generar muchas conecciones, es posible que el servidor del destinatario bloquee tu dirección IP y el script deje de funcionar.

Como instalar PHP 5 en IIS 6.0

Junio 18th, 2007  |  Published in PHP

Esta guia rápida consiste en 3 pasos básicos:
1. Instalar PHP 5
2. Configurar PHP 5
3. Configurar IIS 6

1. Instalar PHP 5

1.1 Bajar y descomprimir PHP 5
Primero es necesario obtener la ultima versoin de PHP 5

2.3 5 de http://www.php.net/ (el zip no el instalador de windows), despues hay que descomprimirlo en cualquier directorio (suponemos C:\PHP5\ para esta guia)

1.2 Renombrar php.ini-recomended a php.ini
Dentro de la carpeta C:\PHP5\ hay que renombrar el archivo llamado php.ini-recomended a php.in.

2. Configurar PHP (php.ini)

2.1 cgi.force_redirect = 0
Dentro del archivo php.ini, hay que quitarle el comentario a la linea
cgi.force_redirect = 0
esto es muy importante, ya que instalaremos PHP 5 como ISAPI y no CGI dentro de IIS 6

2.2 session.save_path
No es absolutamente necesario, pero la mayoria de las aplicaciones en PHP utilizan sesiones, por lo que hay que poner un directorio dentro de esta variable, y asegurarnos de que IIS tenga los permisos de escritura/lectura dentro de ese directorio. Para esta guia utilizaremos:
session.save_path = C:\WINDOWS\TEMP\

Para darle permiso a IIS 6 de escritura/lectura en el directorio C:\WINDOWS\TEMP\ hay que abrir el Windows Explorer, encontrar el directorio, dar click derecho, click en Properties, iir al tab Security, luego en Add, despues para ocalizar el usuario, damos click en Advanced y despues en Find Now, agregamos el usuario/grupo (normalmente IIS_WGP o algo por el estilo), checamos los permisos y le damos click en OK.

2.3 Agregar C:\PHP5\ a la variable de entorno PATH
(o copiar los archivos que no son .dll a c:\windows\system32\ o algun otro folder que ya este incluido en PATH, pero para una mejor organizacion y orden, vamos a agregar C:\php5\)

Para agregar el directorio C:\PHP5\ a la variable de entorno PATH, hay que dar click derecho en My Computer, despues click en Properties, vamos al tab Advanced options, click en el boton Environment Variables, y bajo System Variables, buscamos la variable PATH y le damos doble click.

Ahora escribimos ya sea C:\PHP5\; al principio, o ;C:\PHP5 al final del string, despues damos aceptar, aceptar. Hay que reiniciar el servidor para que este cambio surta efecto.

2.4 Agregar la llave al registro de windows: HKEY_LOCAL_MACHINE\SOFTWARE\PHP\IniFilePath = C:\PHP5

Para agregar esta llave, creamos un nuevo archivo de texto en cualquier directorio, al que vamos a llamar llave.reg, dentro de este archivo escribimos:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\PHP]
“IniFilePath”=”C:\\PHP5″

Grabamos el archivo, y le damos doble click y Si a la confirmación.

Para verificar si se agrego la llave, hacemos click en Start, despues Run, escribimos “regedit” y damos OK, despues buscamos dentro del arbol de directorios, la llave que acabamos de crear (HKEY_LOCAL_MACHINE\SOFTWARE\PHP).

3. Configurar IIS 6

3.1 Agregar la extension C:\PHP5\php5isapi.dll a Web Service Extensions
Abrimos el IIS Manager, vamos a Web Service Extensions, damos click en Add new Web service extension. En donde dice Extension name, escribimos PHP ISAPI Extension, damos click en Add y buscamos el archivo C:\PHP5\php5isapi.dll, despues checamos Set extension status to Allowed y damos OK

3.2 Agregar la extension de los archivos al sitio web (.php)
Dentro del IIS Manager, vamos a Web Sites, damos click derecho en nuestro sitio, despues Properties, nos vamos al tab Home Directories, despues click en Configuration, al tab Mappings y click en Add. Escribimos C:\PHP5\php5isapi.dll en donde dice Executable en Extension, escribimos “.php”.

Damos click en el boton radial Limit to, y escribimos “GET, POST, HEAD”, despues click OK hasta salir.

3.3 Habilitar permiso de ejecución de script
De vuelta en Web Sites, Properties, Home Directories, cambiamos Execute Permissions a Scripts only

3.4 Reiniciamos IIS Manager
Start, Ejecutar, escribimos “iisreset” y damos OK.

Básicamente estos son los pasos a realizar para instalar PHP 5 en IIS 6, no es una guia muy extensa ni tampoco muy a fondo, solo te lleva de la mano pero creo que es fácil de captar.