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

lunes, 2 de junio de 2008

Problemas con find('list') y generateList deprecado en CakePHP 1.2

La verdad a la hora de crear un arreglo de opciones para una lista (select en HTML) tuve problemas ya que en la versión 1.2 de CakePHP la función generateList está deprecada.

Bueno la primera opción que ví fue la de utilizar la función find('list'), pero los resultados no fueron los más deseados. Buscando en los grupos de cake tratando de encontrar alguna sintaxis específica para esta función me encontré con otra solución, que aquí les dejo:

2.    $foo = $this->Usuario->TipoUsuario->find('all');
3. $tipo_usuarios = Set::combine($foo, '{n}.TipoUsuario.id', '{n}.TipoUsuario.nombre');
4. //Si ese objeto tiene una relacion por ejemplo de $belongsTo con el modelo
5. //actual, por ejmplo Usuario con TipoUsuario podemos setear directamente
6. //la lista con la siguiente funcion
7. $this->set(compact('tipo_usuarios'));

Actualización
Con el aporte que hizo José Lorenzo Rodrígues en sus comentarios la otra opción con la función find('list') quedaria así:

    $this->Usuario->TipoUsuario->displayField = 'nombre';
$tipo_usuarios = $this->Usuario->TipoUsuario->find('list');
//Si ese objeto tiene una relacion por ejemplo de $belongsTo con el modelo
//actual, por ejmplo Usuario con TipoUsuario podemos setear directamente
//la lista con la siguiente funcion
$this->set(compact('tipo_usuarios'));


Saludos ...

viernes, 30 de mayo de 2008

Funciones deprecadas o con otras opciones CakePHP 1.2

Estuve viendo un poco y leyendo la documentación y me encuentro con algunas funciones deprecadas o que cambiaron de la version 1.2 de CakePHP con respecto a la 1.1.

Les dejo la lista:
  • Todas las que manejaban forms con el helper html se pasaron al helper form. Pueden ver los cambios en este blog de La Torta en PHP en donde lo explican bien.
  • También la función que utilizabamos para generar listas para los campos select en html llamada generateList() está deprecada. Ahora se utiliza find('list').
    $this->Post->Categoria->find("list")
  • Otra es la función findCount que no estoy seguro si está deprecada pero ahora podemos utilizar find('count')
    $this->Post->find('count', array('conditions' => array('Post.comments_count' => '<>));
  • La función findAll ahora podemos utilizar find('all') para suplantar esta función.
    $this->Post->find('all', array('limit' => 15);
Bueno estas son una pequeña lista que encontré en diferentes blogs y también en algunos proyectos que estoy haciendo.

Saludos ...

jueves, 29 de mayo de 2008

Nuevo Sitio CakePHP-es

El domingo 1 de junio se llevará a cabo una discusión en el irc de cakephp-es. Los temas a discutir serán orientados al nuevo sitio de cakephp-es.

Esperamos que estén presentes la mayoría de los seguidores de este gran framework que nos ayuda cada día en nuestras labores.

La Reunión se llevará a cabo desde las 20 horas (UTC/GMT -5, hora de Panamá).

Para ingresar al irc tienes que ir al servidor freenode.net y el canal es #cakephp-es


Saludos ...

lunes, 26 de mayo de 2008

Nueva versión Ajax Webmail DIMP y Horde 3.2

Después de 30 meses de desarrollo, la gente de Horde Projects ha lanzado la última versión de sus productos Horde 3.2, DIMP 1.0, Horde Groupware 1.1, y otras aplicaciones.

Esta versión incluye varios cambios, dentro de lo que se encuentran:
  • Mejora en el perfomance a travéz de todas las aplicaciones, espcialmente a nivel de base de datos y sobre IMAP.
  • Soporte para sincronización estable a travéz de SyncML.
  • Javascript no obstrusivo, mejorando la interfaz.
  • Soporte WebDAV.
  • Notes encyption.
  • Subtareas y estimación del tiempo en tareas
La verdad me complace mucho saber que este proyecto halla actualizado su webmail. Mi universidad en particular usa este webmail, y a pesar de que se comporta bien, la interfaz de usuario se quedaba corta a nivel de los últimos webmail que están en el mercado.
También podrán encontrar algunos screenshots de la aplicación.

Fuente en inglés: http://janschneider.de/news/35/322

Saludos ...

viernes, 23 de mayo de 2008

Proyecto CakePHP Extensions

Estuve pensando en estos días en crear un proyecto en el cual se hiciera una recopilación de las extensiones que la comunidad ha creado para cakephp. Actualmente cree un proyecto (http://www.assembla.com/wiki/show/cake_extensions) en el cual se tiene un repositorio svn para guardar todas las extensiones.

La persona que desee colaborar en esta iniciativo me puede escribir a mi email danilo.dope at gmail dot com o en el irc freenode canal #cakephp-es.

Actualmente estaba trabajando en un helper para mootools y estaba empezando un componente para picasa.

Bueno espero les guste la idea, y ya saben, el que quiera participar solo me avisa.

Saludos ...

lunes, 19 de mayo de 2008

Código estándar en PHP

El siguiente post que encontré nos muestra algunas reglas para escribir código estándar en php según los estándares que propone PEAR. Pueden ver esta información http://dotpress.wordpress.com/2007/03/29/pear-estandares-de-desarrollo-para-php/

Saludos ...

viernes, 9 de mayo de 2008

Función en Drupal 5.x para setear mensaje

Para setear un mensaje general la api de drupal nos ofrece una función. Esta función es drupal_set_message. Puede ser utilizada dentro de nuestros módulos para efectuar un mensaje al sistema.

Sintáxis
array drupal_set_message($message = null, $type = 'status', $repeat = true)

Parámetros
  • $message: mensaje que vamos a mandar para que la función lo coloque.
  • $type: es el tipo de mensaje. Tiene las siguientes opciones:
    • 'status'
    • 'warning'
    • 'error' --> normalmente color rojo
  • $repeat: si es false el mensaje no se repetirá.
Código

1.    
2.
function drupal_set_message($message = NULL, $type = 'status', $repeat = TRUE) {
3. if ($message) {
4. if (!isset($_SESSION['messages'])) {
5. $_SESSION['messages'] = array();
6. }
7.
8.
if (!isset($_SESSION['messages'][$type])) {
9. $_SESSION['messages'][$type] = array();
10. }
11.
12.
if ($repeat || !in_array($message, $_SESSION['messages'][$type])) {
13. $_SESSION['messages'][$type][] = $message;
14. }
15. }
16.
17.
// messages not set when DB connection fails
18. return isset($_SESSION['messages']) ? $_SESSION['messages'] : NULL;
19. }
20. ?>


Fuente: http://api.drupal.org/api/function/drupal_set_message

Saludos ...

jueves, 8 de mayo de 2008

Función hook_access Drupal 5.x

El hook access dentro del api drupal 5.x para el desarrollo de módulos nos ayuda a definir los permisos de acceso (por ejemplo para crear un tipo de nodo). La cuenta administrativa (con id #1 en la tabla) no tendrá problema para pasar por los permisos de acceso de cualquier módulo. Si no se define este hook para un módulo que defina un tipo de dato, todos los controles de acceso fallarán y sólo el administrador o los usuarios que tengan el permiso "administrar nodos" podrán verlos.

Parámetros:
$op: es la operación a realizar. Por ejemplo:
  • create
  • delete
  • update
  • delete
  • view
Valor de return
Se retorna true si la acción se puede realizar, de lo contrario, se retorna false.

Ej.
1.    
2.
function hook_access($op, $node) {
3. global $user;
4.
5.
if ($op == 'create') {
6. return user_access('create stories');
7. }
8.
9.
if ($op == 'update' || $op == 'delete') {
10. if (user_access('edit own stories') && ($user->uid == $node->uid)) {
11. return TRUE;
12. }
13. }
14. }
15. ?>
Fuente: http://drupa.org/api/function/hook_access/5

Saludos ...

Presentación sobre Programación Orientada a Objetos - Conceptos y su uso en php

Aquí les dejo una presentación que realizé para mi curso de php. Más adelante agrego los ejemplos.



Saludos ...

Custom URL's en Drupal 5.x

Para cambiar el estilo las url's de nuestro sitio en drupal (por ejemplo www.example.com/node/14 a www.example.com/articulo/14) tenemos una función que nos puede ayudar.

Esta función es custom_url_rewrite. A continuación les dejo un ejemplo de modificar la url con node por articulo.


1.
2.
function custom_url_rewrite($op, $result, $path) {
3. if ($op == 'alias') {
4. if (preg_match('|^node/(.*)|', $path, $matches)) {
5. return 'articulo/'. $matches[1];
6. }
7.
8.
}
9. if ($op == 'source') {
10. if (preg_match('|^articulo(/.*)|', $path, $matches)) {
11. return 'node'. $matches[1];
12. }
13.
14.
}
15. return $result;
16. }
17. ?>

Donde si el parámetro $op es 'source' quiere decir que hay que traducirla para el código y si es 'alias' se hace la traducción para la url.

Esta función se guarda en el archivo settings.php de nuestro sitio (por ejemplo ejemplo/sites/default/settings.php)

Saludos ...

martes, 22 de abril de 2008

mysql_num_rows vs. SQl - SELECT COUNT(*)

Haciendo una paginación para un proyecto me dió la curiosidad de verificar cuál método es más efectivo para contar el total de registros. Bueno a pesar de ser obvio que con sql count(*) sería más rápido, me propuse hacer las pruebas y estos fueron los resultados:

  • Prueba con SELECT COUNT(*) FROM tabla
    Fecha: 22/04/2008 11:35:17 am

    Test con count(*) - registros = 44069
    Tiempo 0.00441598892212 segundos
  • Prueba mysql_num_rows
    Fecha: 22/04/2008 11:35:21 am
    Test con mysql_affected_rows - registros = 44069
    Tiempo 59.3658621311 segundos
Código fuente de la prueba:
1.    
2.
require('../benchmark.php');
3. $caso = 'mysql';
4. $file = '../var/bench_databasecount.txt';
5. try{
6. Benchmark::startBenchmark($file);
7. $conn = mysql_connect('localhost', 'root', 'pannet1');
8. mysql_select_db('test', $conn);
9. switch($caso){
10. case 'count':
11. $sql = "SELECT COUNT(*) as contador FROM tabla";
12. $rs = mysql_query($sql, $conn);
13. $count = mysql_fetch_array($rs);
14. Benchmark::pushLog('Test con count - registros = '.$count['contador']."\n", $file);
15. break;
16. case 'mysql':
17. $sql = "SELECT * FROM tabla";
18. $rs = mysql_query($sql, $conn);
19. $count = mysql_num_rows($rs);
20. Benchmark::pushLog('Test con mysql_affected_rows - registros = '.$count ."\n", $file);
21. break;
22.
23.
}
24. Benchmark::endBenchmark($file);
25. echo 'Termino';
26. }catch(Exception $e){
27. echo $e->getMessage();
28. }
29. ?>
30.
31.

Conclusión

A las personas que todavía realizan las paginaciones con mysql_num_rows, preferiblemente usen sql (función COUNT(*)).

Saludos ...

martes, 15 de abril de 2008

Patrón Singleton en PHP

Les dejo un ejemplo del patrón singleton aplicado en php. Es bien útil para manejar las conexiones a la base de datos.

1.  <?php  
2.
class DB {
3. private static $_singleton;
4. private $_connection;
5. private function __construct()
6. {
7. $this->_connection = mysql_connect();
8. }
9. public static function getInstance()
10. {
11. if (is_null (self::$_singleton)) {
12. self::$_singleton = new DB();
13. }
14. return self::$_singleton;
15. }
16. }
17. $db = DB::getInstance();
18.
19. ?>

Saludos ...

martes, 11 de marzo de 2008

Benchmark a tu sitios con ApacheBench en Linux

Si tu sitio u aplicación está alojada en un servidor que corre sobre apache, entonces podemos hacer un Benchmark para verificar el tiempo de respuesta de nuestra aplicación, gracias a la aplicación ApacheBench.

Este aplicación nos ayuda para hacer benchmark de aplicaciones hechas en php por ejemplo u otro tipo de aplicaciones, ya que podemos medir el tiempo de respuesta de nuestra app.

Ahora les coloco un ejemplo de su uso:
  • Entramos a la consola y colocamos:
    #: ab -c 10 -t 60 http://example.org/productos.php
  • Para llamar a la aplicación utilizamos el comando ab; explico los parámetros:
    • -c: este parámetro indica el número de clientes con el cual se va a llevar a cabo el test.
    • -t: indica el tiempo durante el cual se va a llevar a cabo el test. Este tiempo es en segundos.
Además de esos parámetros que pueden ser de utilidad para nuestras benchmark a servidores apache. Compruebe introduciendo ab man para obtener más información.

Espero puedan mejorar los procesos de sus aplicaciones utilizando esta herramienta para medir su rendimiento.

Saludos ...

jueves, 6 de marzo de 2008

Problemas con bindable y paginate en CakePHP

Últimamente tuve un poco de problemas con los binds y la función paginate de la nueva versión de el marco de trabajo cakephp, la 1.2.

Mi problema surgía cuando quería buscar todos los posts que estuvieran asociados a un tag específico, pero sólo quería traer la relación que el post tenía con Usuario y no la relación con Comentarios. Buscando por ahí me encuentra con una respuesta del Sr. Mariano Iglesias, que dice que la función paginate rehace las relaciones (por esta razón cualquiera unbindModel no funcionaría). En este enlace se puede encontrar información sobre el behavior Bindable. En mi caso la solución fue la siguiente:
  • Creo app_model.php y le agrego:
    var $actsAs = array('Bindable');
  • El método en el controlador post quedó así:
    function tag($id = null){
    if (!$id) {
    $this->Session->setFlash(__('Invalid Tag.', true));
    $this->redirect(array('action'=>'index'));
    }
    $this->layout = 'blog';
    // $this->Post->unbindModel(array('hasMany' => array('TrackPost', 'Comentario'), 'hasAndBelongsToMany' => array('Tag')));
    $this->Post->restrict(false, 'Usuario');
    /*$this->Post->bindModel(array('hasAndBelongsToMany' => array('Tag' => array(
    'joinTable' => 'posts_tags',
    'foreignKey' => 'post_id',
    'associationForeignKey' => 'tag_id',
    'unique' => false,
    'conditions' => 'Tag.id = '.$id)
    )
    ));*/
    $this->Post->Tag->recursive = 2;
    $this->set('existSession', $this->existSession());
    //$this->set('posts', $this->Post->Tag->find(array('Tag.id' => $id)));
    $this->set('posts', $this->paginate('Tag', array('Tag.id' => $id)));
    $this->Post->resetBindable(true);
    }
  • Lo interesante está en las siguientes líneas:
    • $this->Post->restrict(false, 'Usuario'); : esta línea restringe a que Post solo tengo relación con Usuario y el parámetro false hace que todos los cambios que haz hecho de relaciones sean permanentes.
    • $this->Post->resetBindable(true); : reseteo las relaciones para que funcionen como estaban.
Bueno con esto resolví mi problema. Saludos ...

lunes, 3 de marzo de 2008

Cakephp relación HBTM personalizada

Trabajando con CakePHP me encuentro en el manual el típico ejemplo de una relación de muchos a muchos (ejemplo de la relación de posts y tags).

Según la documentación se debe crear un campo select multiple para colocar los tags aquí. Este método no me gustó mucho y decidí hacerlo al estilo de el bloguer de Google, o sea, separar los tags por compas en un campo tipo text.

Mi solución consiste en buscar en la base de datos si los tags que el usuario introdujo existen, de no existir los inserto y obtengo su id. En el modelo post agregué el método beforeSave. Aquí les dejo el código:
public function beforeSave(){
if ($this->data['Tag']['tags'] != ''){ //Campo $form->input('Tag/tags')
$tags = explode(',', $this->data['Tag']['tags']);
foreach($tags as $tag){
$tag = trim($tag);
$tag_find = $this->Tag->findByTagname($tag);
if ($tag_find){
$tag_id = $tag_find['Tag']['id'];
}else{
$tag_ins = array('Tag' => array('tagname' => $tag));
$this->Tag->save($tag_ins);
$tag_id = $this->Tag->getLastInsertID();
}
$this->data['Tag']['Tag'][] = (string) $tag_id;
}
}
unset($this->data['Tag']['tags']);
return true;
}


Para el caso de la acción de editar, coloqué este código en el método:
if (empty($this->data)) {
$this->data = $this->Post->read(null, $id);
foreach($this->data['Tag'] as $tag){
$tags[] = $tag['tagname'];
}
$tags = implode(', ', $tags);
$this->set('tags', $tags);
}

Y en la vista
echo $form->input('Tag/tags', array('label' => 'Tags separados por coma', 'type' => 'text', 'value' => $tags));

Listo, de esta manera utilizamos la relación de muchos a muchos en cakephp, pero a nuestra manera.

Saludos ...

viernes, 15 de febrero de 2008

setFlash de CakePHP con ZendFramework

Por estos días estoy en training total de Zend Framework, la verdad un framework muy flexible, con una gama de clases bastante buenas que permiten agilizar nuestro tiempo de desarrollo (ojo eso si dominamos dicho framework, no demora mucho tiempo dominarlo).

En fin anteriormente he utilizado CakePHP, otro framework que me gusta bastante, pero que aunque más fácil de usar, diría a mi concepto es menos flexible que el framework de Zend.

Para ir al asunto, hay varias funciones de cakephp que me gustan mucho, entre ellas la que utilizamos en el controlador para guardar mensajes y mostrarlos aunque se haga un redirect ($this->Session->setFlash). Por ejemplo si tenemos un módulo de noticias y guardamos una noticias, pero redirigimos a la página donde se listan las noticias y no al formulario para agregarla, tenemos que hacer un redirect ($this->_redirect('/')), o sea, que si queremos mostrar un mensaje no podríamos hacerlo (que yo cepa, me imagino que alguna otra forma habrá).

Para eso cree un controlador base (BaseController.ph) que hereda de Zend_Controller_Action. En el agregúe dos funciones, setFlash para setear el mensaje y getFlash para obtener dicho mensaje (Si quieres que funcione para cualquier controlador entonces debes heredar de esta clase los controladores). Estas funciones utilizan una variable de sesión por lo que en el bootstrap (index.php) debemos abrir la sesión así:

Zend_Loader::loadClass('Zend_Session');
Zend_Loader::loadClass('Zend_Session_Namespace');

/**
* Abro la sesión
*/
Zend_Session::start();

---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------

Ahora les dejo con el código del controlador base (BaseController.php)

/**
* BaseController
*
* @author
* @version
*/

require_once 'Zend/Controller/Action.php';

class BaseController extends Zend_Controller_Action {
/**
* The default action - show the home page
*/

public function init() {
$this->initView();
$this->view->siteInfo = Zend_Registry::get('siteInfo');
$translate = Zend_Registry::get('translate');
$this->view->declareVars(array('t' => $translate));
}

public function postDispatch(){
$this->view->danmessage = $this->getFlash();
}

public function baseUrl()
{
$fc = Zend_Controller_Front::getInstance();
$request = $fc->getRequest();
return $request->getBaseUrl();
}


public function setFlash($msg = ''){
$danmsg = new Zend_Session_Namespace('dan.message');
$danmsg->mensaje = $msg;
}


public function getFlash(){
$r = new Zend_Session_Namespace('dan.message');
$return = $r->mensaje;
$r->mensaje = null;
return $return;
}
}

---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------

Ahora en mi caso estoy usando la clase Zend_Layout, por lo que uso un template. Para colocar este mensaje en tu template solo debes imprimirlo donde desees. Solo debes utilizar esto:

<?=$this->danmessage ?>

martes, 29 de enero de 2008

Diferentes themes para diferentes contenidos en Drupal

Si tenemos la necesidad de colocar diferentes themes para diferentes categorías de contenidos en drupal tenemos un módulo bastante bueno para solucionar este problema. Se trata de Taxonomy Theme. Este módulo permite asignar diferentes templates a cada término dentro de una categoría de contenido.

Cuando vamos a agregar un término dentro de una categoría debe aparecer un campo extra llamado theme. Aquí vamos a escoger cual tema asignaremos a este contenido.

viernes, 11 de enero de 2008

CakePHP y Foxpro

Hace un tiempo me hice la pregunta si podía conectar Visual Foxpro con CakePHP. Había investigado un poco pero no había dado con la solución. Buscando un poco me di cuenta que cake maneja conexiones con adodb (librerías para manejo de base de datos en php). Con estas librerías encontré la solución. Lo lamentable es que hasta ahora solo lo puedo hacer en windows.
Solución:
  • Descarga el paquete adoddb
  • Descomprimelo en la carpeta de vendors.
  • Asegurate de descargar los drivers de odbc para foxpro (enlace).
  • Debemos crear un dns para la base de datos foxpro. Es sumamente sencillo. Solo hay que ir a Panel de Control -> Herramientas Administrativas -> Orígenes de datos ODBC.
  • En la pestaña DNS de usuario daz clic en el botón Agregar y escoges Driver para o Microsoft Visual FoxPro.
  • Te debe salir una nueva ventana en donde debes llenar unos datos:
    • Data Source Name: nombre del dns. Ojo este nombre lo vas a usar en la conexión.
    • Description: la que quieras.
    • Database type: si en el campo path vas a colocar una carpeta donde se encuentran los dbf, entonces colcoas Free Table directory.
    • Listo ya haz creado el DNS.
  • Ahora nos toca modificar el archivo de configuración de la base de datos, database.php así:
    var $default = array('driver' => 'adodb',
    'connect' => 'dnsname', //Esto es el nombre que colocaste en Data Source Name
    'login' => '',
    'password' => '',
    'database' => '',
    'prefix' => ''
    );
  • Con esto ya tenemos una conexión establecida con una base de datos foxpro.
Saludos ...

jueves, 15 de noviembre de 2007

Modulo dbase para php5 (sin tener que recompilar)

El otro día me encontré con un problema con el módulo de php dbase. Cuando lo fui a instalar por el administrador de paquetes (aptitude), este no lo pudo encontrar.

Solución:
  • Descargar el paquete de php (en php.net)
  • Descargar el paquete php5-dev
  • Desempaquetar php y entrar a la carpeta ext/dbase
  • Ejecutar el comando phpize
  • Ejecutar el comando ./configure
  • Ejecutar el comando make
  • Copiar el archivo compilado a la carpeta de librerías de php5 en mi caso (usr/lib/php5/20060613+lfs) #cp ./.libs/dbase.so usr/lib/php5/20060613+lfs/
  • Cambiarle los permisos #chmod 644 usr/lib/php5/20060613+lfs/dbase.so
  • Agregar la extensión a php.ini
    extension_dir = "usr/lib/php5/20060613+lfs"
    extension=dbase.so
  • Reiniciar el servidor web
Con esto tendremos el módulo de dbase para php5

Saludos ....

Rewrite rule y programación modular

Cuando tenemos una aplicación modular desarrollada en php y queremos esconder la url completa y sustituirla por una url limpia podemos hacer uso del module rewrite de apache.

Para eso tenemos que crear un archivo .htaccess dentro del root de nuestra aplicación. Si nuestro front controller está o es llamado desde index.php podemos hacer lo siguiente:
Si la cadena original es:
index.php?modulo=noticias&act=index
Nuestro archivo htaccess tendría lo siguiente:

RewriteEngine On
RewriteRule ^(.+)/(.[^/]+)(/?)$ index.php?modulo=$1&act=$2


Con esto si teníamos un sistema al que llamabamos así:
http://example.com/test/index.php?modulo=noticias&act=index
Ahora lo llamamos así
http://example.com/test/noticias/index ó
http://example.com/test/noticias/index/

Eso es todo por este minitutorial.

Saludos ...