September 12th, 2011 Category: Curso php5 Programacion Zend Framework
23 Comments »
Llego la hora de hacer algo util, hoy vamos a ver como configurar nuestra aplicacion para trabajar con una base de datos mysql, para eso vamos a usar Zend_Form para crear formularios y vamos a crear modelos para poder traer datos de nuestras tablas y poder escribir en ellas.
Si te perdiste el video anterior podes verlo aca
Es recomendable ver el video en 720p de resolucion y en pantalla completa.
Los que quieran descargarse el codigo fuente pueden hacerlo desde github en http://github.com/pablofmorales/News123
Capitulos Anteriores
Capitulo 1 < Configuracion y creacion del proyecto
Capitulo 2 < Estructura de directorios, MVC y layouts
Capitulo 3 < Objeto view, y contenido estatico
Proximo capitulo > Edicion, y Paginado.
Gracias Maestrosdelweb por darme un espacio en su cuenta de youtube
February 12th, 2010 Category: base de datos mysql Programacion Zend Framework
5 Comments »
Una transacción es un conjunto de operaciones en la base que se
ejecutan por separadas pero están relacionadas la una con la otra y
necesitamos que si se ejecuta una operación se asegure que también lo
haga en las operaciones siguientes.
En los tipos de tablas transaccionales (InnoDb y DBD ) de MySql,
tenemos la opción de determinar cuando hacer un commit, esto nos
permite hacer un rollback en el caso de que no estemos felices con el
resultado de nuestra transacción.
En las tablas del tipo no transaccional (MyIsam) esta opción no
existen porque están seteadas para que se haga un auto commit, esto
significa que no vamos a poder usar transacciones para tablas de Tipo
MyIsam, solo para InnoDb.
Con las tablas InnoDb nosotros podemos controlar cuando hacer el
commit. Podemos revisar que todas las operaciones se hayan realizado
de forma correcta y recién ahí hacer un commit de la transacción.
Con esta forma nosotros nos aseguramos que una operación se ejecute en
su totalidad, e informar al usuario o a quien sea necesario el
resultado de la misma.
La gente de Doctrine en su blog comentan que su ORM aumenta la
velocidad de mysql, ya que ellos manejan transacciones de forma nativa
en todas sus operaciones,
http://www.doctrine-project.org/blog/transactions-and-performance .
Les recomiendo que lean el articulo, aunque esta en ingles es bastante
claro. Quizás el articulo los entusiasme y se metan un poco en el
mundo de los ORM.
Zend Framework como no podía de ser de otra forma tiene soporte para
transacciones. Si tenemos ZF en un sistema con MVC, y tenemos que
hacer una transacción que involucre mas de un modelo, la transacción
la podemos abrir en cualquiera de ellos, y comitearla.
La forma correcta es conseguir el adapter. El cual nos brinda la
interfaz con la conexion a la base de datos. El mismo lo podemos
conseguir llamando al metodo getAdapter de cualquiera de nuestros
modelos.
class TestController extends Zend_Controller_Action
{
public function createAction()
{
$params = $this->_getAllParams();
$model1 = new MyFirstModel();
$model2 = new MySecondModel();
//Conseguimos el Adapter de nuestra conexion
$db = $model1->getAdapter();
// Iniciamos la transaccion
$db->beginTransacction();
try{
$model1->insert( $params );
$model1->insert( $params );
// Sino hubo ningun inconveniente hacemos un commit
$db->commit();
} catch( Exception $e ) {
// Si hubo problemas. Enviamos todo marcha atras
$db->rollBack;
}
}
}
En el código de ejemplo podemos ver como recibimos ciertos datos por
POST/GET y los datos los guardamos en dos modelos diferentes, esas
acciones están dentro de un try/catch, el que nos permite atrapar las
excepciones que podrían ser enviada por alguna de las operaciones que
tenemos dentro de la transacción en cuyo caso ejecutamos el rollback.
Si todo salio bien llamamos al metodo commit.
Si nosotros queremos forzar dentro de nuestros modelos un rollback lo
mas transparente es tirar una excepcion, y desde el controller se
ejecuta el rollback. La forma de generar una excepcion es la
siguiente.
Para saber mas de transacciones nada mejor que ir a las fuentes originals.
MySql http://dev.mysql.com/doc/refman/5.0/es/ansi-diff-transactions.html
Zend Framework http://framework.zend.com/manual/1.10/en/zend.db.adapter.html#zend.db.adapter.transactions
December 3rd, 2009 Category: Programacion Zend Framework
7 Comments »
Cron para Backup y Optimizacion de tablas con PHP + Zend Framework
Hace mucho no escribía un post, y quiero volver a retomar el habito con este pequeño scripts realizado con Zend Framework para optimizar todas las tablas de una base de datos mysql y además generar un dump por cada tabla, los resultados los vamos a comprimir para que no ocupe espacio innecesario.
Mantener un backup de nuestras tablas es mas que recomendable, uno nunca sabe cuando lo va a necesitar, sobre todo porque es muy fácil implementar un sistema automatico para generar backups como vamos a ver a continuacion.
En este post aunque es corto quiero demostrar que es posible realizar lo siguientes puntos:
1- Correr php desde la consola de linux
2- Correr Zend Framework desde la consola ( si es posible! ) y usar componentes de Zend Framework sin la necesidad de usar MVC, Zend_Application.
3- Realizar backups diarios de sus base de datos.
1- Correr php desde la consola de linux.
Esto espero que no sea una ciencia para ninguno, realmente es muy fácil. Creamos un scripts antes de los tags <?php ?> agregamos #!ruta_de_php en mi caso seria #!/usr/bin/php con esta linea le decimos a quien llamar para ejecutar el código que viene a continuación.
Un ejemplo simple seria el siguiente.
#!/usr/bin/php
echo "Estoy imprimiendo directamente en la consola";
Guardamos el archivo como test.php, y le damos permisos de ejecución con el comando
$ chmod a+x test.php
Ahora lo ejecutamos
$ ./test.php
El resultado es el siguiente
2- Correr Zend Framework desde la consola ( si es posible! ).
Zend Framework mas allá de un montón de herramientas que nos brinda y formas de trabajo. Así como Zend_Application, Estructura de directorios organizadas, MVC, etc tambien nos permite usar sus componentes individualmente.
Si nosotros quisieramos usar Zend_Db, y todos los beneficios que este trae, solo necesitamos una configuracion mínima y listo. Podemos usar Zend_Db sin usar MVC o Zend_Application y mantener nuestra estructura de directorios.
En este caso voy a usar Zend_Db para conectarme a una base y conseguir un listado de tablas.
El código es el siguiente.
#!/usr/bin/php
set_include_path( implode( PATH_SEPARATOR, array(
realpath( 'library' ),
get_include_path(),
)));
require_once( "library/Zend/Db.php" );
/** Conectamos a la base de datos con ZF */
$db = Zend_Db::factory( 'Pdo_Mysql',
array(
'adapterNamespace' => Zend_Db_Adapter,
'dbname' => 'mysql',
'host' => 'localhost',
'username' => 'test',
'password' => 'qwerty'
)
);
$db->getConnection();
$rowset = $db->fetchAll( "SHOW TABLES" );
print_r( serialize( $rowset ));
Para el ejemplo yo use Pdo_Mysql pero puden usar el adapter que quieran. Yo serialize el array $rowset para que sea mas claro en la imagen que se ve a continuacion que muestra todas las tablas que tiene la base de datos mysql.
3- Incentivar a realizar backups diarios de sus base de datos.
Es muy comun que una tabla se rompa o alguien cometa algun error y se pierdan datos o dañe una tabla o toda una base. Hay mil factores que pueden hacer que necesitemos un backup reciente de nuestra base. Si creamos un dump entero de nuestra base cuando queramos recuperar una tabla se nos va a complicar un poco realizar esta tarea sin tener que abrir un archivo que vaya a saber cuando miles de mega ocupe. Por eso es conveniente hacer backup de las tablas individualmente, asi en el caso que tengamos problemas con una sola tabla recuperar esa tabla se hace una tarea facil .
Hacer un script que genere este backup diariamente no es complicado, creamos el scripts, y configuramos el cron para que se ejecute a la hora que tengamos la menor cantidad de visitas.
Este script esta en PHP, en realidad la manera mas optima seria hacerlo en shell scripting pero tambien queria demostrar los 2 puntos anteriores.
Mi script es muy sencillo y es facil de entender. Primero trae todas las tablas de la base que estamos usando. Ejecutamos un optimize para cada tabla, inmediatamente generamos un backup de esa tabla en una carpeta temporal, cuando terminamos de hacer estas acciones con todas las tablas comprimimos la carpeta y borramos la carpeta orginal, para que no ocupe espacio.
Para ejecutar los comandos de linux use noFollow y no me preocupe mucho en validarlo, cada uno puede buscar la forma de optimizar el codigo.
El script cuenta con dos archvios. Un application.ini donde guardo toda la info de la base de datos
config/application.ini
[db]
adapter = Pdo_Mysql
params.adapterNamespace = Zend_Db_Adapter
params.host = localhost
params.username = test
params.password = “qwerty”
params.dbname = mibase
params.port = 3306
params.options.autoQuoteIdentifiers = 0
Y el script completo
#!/usr/bin/php
set_time_limit( 0 );
set_include_path( implode( PATH_SEPARATOR, array(
realpath( 'library' ),
get_include_path(),
)));
require_once( "library/Zend/Config/Ini.php" );
require_once( "library/Zend/Db.php" );
/** Conectamos a la base de datos con ZF */
$applicationConfig = new Zend_Config_Ini( 'config/application.ini' );
$db = Zend_Db::factory(
$applicationConfig->db
);
$db->getConnection();
$rootPath = "/home/backup/db/";
$destination = $rootPath . date("Y.m.d") ;
mkdir ( $destination );
$config = $db->getConfig();
$rowset = $db->fetchAll( "SHOW TABLES" );
foreach ( $rowset as $row ){
/** Optimizamos la tabla */
$query = "OPTIMIZE TABLE " . $row['Tables_in_' . $config['dbname'] ] ;
$db->query( $query );
$path = $destination . "/{$row['Tables_in_' . $config['dbname'] ]}." . date("Y.m.d") . ".sql" ;
/** Generamos un dump de la tabla */
system( "mysqldump --opt -u {$config['username']} -p{$config['password']} -h {$config['host']} {$config['dbname']} {$row['Tables_in_' . $config['dbname'] ]} > $path " );
}
/** Comprimimos la carpeta con los dump de la fecha y borramos la carpeta */
system( "tar zcf {$destination}.tar.gz {$destination}" );
system( "rm -rf $destination" );
$db->closeConnection();
echo "ndone!nn";
Antes de ejecutar el script tienen que crear la carpeta /home/backup/db y darle permisos de escritura
$ sudo mkdir -p /home/backup/db
$ sudo chmod -R a+rw /home/backup/db
lo agregamos al crontab y listo.
$ sudo vim /var/spool/cron/crontabs/root
Agregamos la siguiente linea para que se ejecute todos los dias a las 2:20 am
20 2 * * * /var/www/html/scripts/cronOptimize.php > /dev/null 2> /dev/null
Y listo
Recuerden que tienen que tener instalado php5-cli
$ sudo aptitude install php5-cli
December 4th, 2008 Category: Zend Framework
6 Comments »
- Modularizar el sistema.
Uno de los problemas que me encuentro habitualmente en los foros o las listas de Zend Framework es como tener en un mismo sistema
frontend y Backoffice (backend) compartiendo la misma estructura. Este problema se puede resolver de varias formas, pero la manera correcta es crear módulos. En nuestro sistema actual teníamos el modulo default cargado, que no necesita mas configuracion, que declarar cual es el path de nuestros controllers, con el método setControllerDirectory(), y como parámetro le pasamos un string con el path correspondiente. Con esta acción, le estamos diciendo que el modulo default esta en esa ruta.Si nosotros quisieramos agregar un modulo mas que en este caso vamos a llamarlo admin, en vez de pasarle un string vamos a pasarle un array, donde el índice va a ser el nombre del modulo, y el valor el path donde encontrar el controller.
Nuestra ruta actual es applications/controller/, esta es la ruta para el default, pero ahora que vamos a agregar un admin necesitamos ubicarlo en otro lugar. Ese lugar lo puede establecer ustedes, yo voy a elegir para guardarlo en applications/admin/controller. Ahora siguiendo esto en la carpeta application nos va a quedar la siguiente estructura.
Esto tiene una particularidad, los controllers de nuestro modulo admin, tienen que tener el prefijo de la carpeta, pero en Mayúscula no en minúscula como lo indica la lógica, ya que la carpeta admin esta en minúscula.
Ahora cuando queramos crear un controller el nombre seria algo así
Pero ya me estoy llendo por otro lado, ahora vamos a ver cual es la forma correcta de agregar los módulos en nuestro bootstrap.
setParam( 'config', 'config.default.ini' )
->setControllerDirectory( array(
'default'=> '../application/controller',
'admin'=> '../application/admin/controller'))
->throwExceptions(true)
->dispatch();
Si o si tenemos que crear un modulo con el key default, y el otro es el que queremos agregar. Si quisieramos podríamos agregar muchos mas módulos, pero no es algo que veamos en este proyecto, pero se puede
Si hacen un svn update del proyecto, van a encontrar algunas lineas mas en este código, que son las que levantan los plugins. Pero esto lo dejamos para otra entrega.
- Leyendo una base de datos
Todo blog necesita de una base de datos para almacenar los post, ahora vamos a crear una nueva base de datos llamada blogzf.
Vamos a crear la tabla 'posts', donde vamos a guardar todo el contenido de nuestro blog.
La tabla es la siguiente.
CREATE TABLE `blogzf`.`posts` (
`post_id` MEDIUMINT( 10 ) NOT NULL AUTO_INCREMENT ,
`user_id` MEDIUMINT( 10 ) NOT NULL ,
`title` TEXT NOT NULL ,
`content` LONGTEXT NOT NULL ,
`comment` TINYINT( 1 ) NOT NULL ,
`created_date` DATETIME NOT NULL ,
`modified_date` DATETIME NOT NULL ,
`status` CHAR( 10 ) NOT NULL ,
PRIMARY KEY ( `post_id` )
) ENGINE = MYISAM;
Y la tabla users.
CREATE TABLE `blogzf`.`users` (
`user_id` MEDIUMINT( 10 ) NOT NULL AUTO_INCREMENT ,
`username` CHAR( 50 ) NOT NULL ,
`password` CHAR( 50 ) NOT NULL ,
`display_name` CHAR( 100 ) NOT NULL ,
`status` CHAR( 10 ) NOT NULL ,
PRIMARY KEY ( `user_id` )
) ENGINE = MYISAM;
Ahora vamos a tener que crear un ABML o CRUD (CREATE, READ, UPDATE, DELETE) para estos modulos.
En esta parte no vamos a darle funcionalidad a este modulo, vamos a dejarlo para la proxima, asi podemos extendernos un poco y ver Zend_Paginator, Zend_Form, entre otros.
Lo primero que tenemos que hacer es crear el controller, model, y vista de users, vamos a empezar con el mas facil.
Creamos los actions para nuestro CRUD.
El modelo va a ser bastante simple
Y las vistas.
Un buen ejemplo de como crear un CRUD con Zend Framework lo tenemos en el blog de Zsamer.
Lo primero que tenemos que hacer es configurar la conexion a la base de datos, los datos de esta lo vamos a poner en nuestro archivo de configuracion, config.default.ini.
[database]
db.adapter = PDO_MYSQL
db.config.host = localhost
db.config.username = blogzf
db.config.password = "password"
db.config.dbname = blogzf
Supongamos que tenemos una base de datos en localhost llamada blogzf, y un usuario blogzf con la clave "password". esta seria la forma de representarlo en el ini.
Cuando levantamos esta configuracion tenemos que crear una conexion a la base de datos, esto lo vamos a hacer desde el preDispatch, la conexion la vamos a guardar en una variable privada llamada _db, para usarla en todo el modulo.
$this->_db = Zend_Db::factory(
$config->database->db->adapter,
$config->database->db->config
->toArray() );
Asi como paso con el bootstrap, el config no les va andar porque tienen que crear un archivo config.local.ini, con solo crearlo y dejarlo en blanco es suficiente, la idea de esto es generar un archivo con toda la configuracion generica, y uno que sea configurable para cada ambiente, desarrollo, qa, y Produccion. Pero eso lo vemos mas adelante.
En esta parte vimos
Zend_Config
Zend_Db
November 17th, 2008 Category: Zend Framework
2 Comments »
Cada vez que instanciamos un Zend_Db_Table, ZF hace un describe de la/las tablas que vamos a usar en nuestros query, recolectar esta info consume tiempo y recurso. ZF nos da la posibilidad de Cachear estos datos, usando Zend_Cache. Esto si bien podria estar como default, para reducir bastante los tiempos, no lo esta debido a que si cambiamos el nombre o datos de nuestra tabla, deberiamos limpiar el cache, y para evitar problemas que pueda llegar a generar esto no viene activo por default.
Si queremos hacerlo en nuestro sistema usando Sqllite la forma es muy simple. Basta habilitar sqllite en nuestro php.ini y crear una carpeta para que guarde este cache, podemos elegir la misma ruta que usamos para guardar nuestras paginas con Zend_Cache, todo esto es totalmente personalizable.
El codigo para que guarde la metada lo tenemos que aplicar antes de instanciar cualquier modelo, esto lo podemos hacer desde el bootstrap, pero tambien hay otras formas, cada uno puede implementar la forma que mas le convenga.
Los datos a continuacion tenemos que guardarlos en nuestro archivo de configuracion, yo uso los .ini en el ejemplo
config.ini
[metadata_cache]
frontend.automatic_serialization = true
frontend.lifetime = 3600
; Lugar donde vamos a guardar el cache
backend.cache_db_complete_path= “/tmp/zend_cache_db”
Y este es el codigo que deberia ir en nuestro bootstrap
bootstrap.php
frontend, $config->metadata_cache->backend );
$cache->clean( Zend_Cache::CLEANING_MODE_ALL );
Zend_Db_Table_Abstract::setDefaultMetadataCache( $cache );
?>
Enlaces
Documentacion oficial de Zend_Db_Table
Documentacion de webinar sobre acceso a la base de datos con Zend Db
October 29th, 2008 Category: Programacion Zend Framework
1 Comment »
Encontre varios links interesantes para compartir. Es muy bueno el video que hay en el blog para webmasters de google, sobre los sitemap, para los que no tienen muy en claro para que sirve, o como usarlo es ideal, ademas esta explicado muy claro.
Tambien hay un ejemplo de uso Zend_Captcha.
Hace unas semanas en la lista de Zend Framework hispano surgio una discusion sobre si era bueno o no empezar a programar en PHP con Zend Framework, tambien encontre un link donde tocan el tema.
Zend Framework
- Zend Framework good for beginners or no? – Code Utopia
- Scraping websites with Zend_Dom_Query – raphael.on.php
- A Zend_Captcha exaple – Robert Basic
- Zend framework and the twitter api – Dave Development
- Profiling queries with Zend_Db and optimizing them by hand – Tech Founder
SEO
- La importancia de la arquitectura de enlaces – Google para webmasters
- Los sitemap al descubierto – Google para webmasters
Programacion en general
August 14th, 2008 Category: Zend Framework
12 Comments »
Cuando hacemos una consulta a la base de datos con Zend_Db, nos devuelve un objeto, con mucha info que pocas veces usamos. Generalmente nosotros queremos que nuestro metodo devuelva un array o un objeto, con las columnas de la consultas, y no mas que eso.
Si queremos que solo devuelva los resultados, en un array, tenemos una propiedad que nos soluciona esto.
El objeto que devulve fetchRow, y fetchAll, tiene una propiedad llamada toArray, que te devuelve solo las columnas del objeto en un array.
De esta manera, si nosotros quisieramos por ejemplo en nuestro modelo, el resultado de un fetchRow guardarlo en un Json, podriamos hacer lo siguiente.
select()
->where('usuario_id = ?', $id);
return $this->fetchRow($select)
->toArray();
}
}
?>
Los que nos devuelve este ejemplo es un array con todas las columnas de nuestra tabla usuarios, donde el id del registro es igual al que le pasamos como parametro.



