{"id":1650,"date":"2016-01-30T02:07:16","date_gmt":"2016-01-30T08:07:16","guid":{"rendered":"https:\/\/www.lastdragon.net\/?p=1650"},"modified":"2016-01-30T09:57:33","modified_gmt":"2016-01-30T15:57:33","slug":"redbeanphp-un-orm-facil-de-programar-en-php","status":"publish","type":"post","link":"https:\/\/www.lastdragon.net\/?p=1650","title":{"rendered":"RedBeanPHP un ORM f\u00e1cil de programar en PHP"},"content":{"rendered":"<p>Un ORM ( Object-Relational mapping ) o Mapeo objeto-relacional son unas clases usadas en los lenguajes orientados a objetos para controlar las bases de datos en el mejor de los casos con cero conocimiento SQL y en el peor de los casos teniendo que usar algo de SQL para subsanar las limitantes que pudiera tener el ORM<\/p>\n<p><strong>Ventajas<\/strong><\/p>\n<p>Al no escribirse c\u00f3digo SQL en ninguna parte no hay donde hacer una inyecci\u00f3n SQL , muchos de los sitios que son hackeados por inyecciones SQL no lo serian si tuvieran un ORM<\/p>\n<p>Puede migrarse de una DB a otra que este soportada por el ORM y el c\u00f3digo en el programa no cambia, esto significa que no tienes que preocuparte si te dicen que debes entregar tu proyecto en ORACLE, SQL SERVER, MySQL, SQLite, etc. El mismo c\u00f3digo es v\u00e1lido para todas las bases de datos, siempre y cuando el ORM soporte esas bases de datos.<\/p>\n<p><strong>Desventaja<\/strong><\/p>\n<p>Mientras m\u00e1s se le facilita la vida al programador, m\u00e1s recursos usa. Esto significa que es un poco m\u00e1s lento obtener los datos de una base de datos v\u00eda ORM que con SQL nativo, la mayor\u00eda de las veces esta desventaja queda justificada con la facilidad y la seguridad que proporciona un ORM<\/p>\n<p>Hay muchos ORM la mayor\u00eda son usados en frameworks como PHP con Laravel, Python con Django o en el caso de .NET C# que cuenta con ORMs como NHibernate o EntityFramework<\/p>\n<p>El problema es que para usar un ORM te tienes que bajar todo un framework ya que los framework traen ORM incorporados como \u201cventaja\u201d y a veces solo quieres un ORM para cuando la situaci\u00f3n lo necesita sin tener que programar en las reglas del framework<\/p>\n<p>Para PHP existen varios ORM pero hoy me centrare en RedBean es un sencillo ORM, incluso tal vez demasiado sencillo ya que el mapeo de las clases se hace al mismo tiempo ahorrando muchas l\u00edneas de c\u00f3digo.<\/p>\n<p><strong>RedBean lo hace todo por el programador.<\/strong><\/p>\n<p>Crea el esquema de tablas, creas las columnas y decide qu\u00e9 tipo es el m\u00e1s adecuado incluso en tiempo de desarrollo es capaz de evolucionar las columnas, si una columna inicia como int por que el primer valor almacenado es 20 y en el siguiente registro se le escribe veinte con letras, este ORM exporta el 20 a texto y cambia el tipo de la columna a varchar de forma transparente, por supuesto una vez en producci\u00f3n esa capacidad de cambiar cosas al vuelo se puede bloquear para que no haya cambios de tipos.<\/p>\n<p><strong>Como usar RedBean<\/strong><\/p>\n<p>En RedBeans los registros se llaman beans por lo que si en la documentaci\u00f3n lees beans en realidad se est\u00e1 refiriendo a un registro almacenado en una tabla. Para facilitar a mis lectores como adoptar este ORM har\u00e9 una comparaci\u00f3n de lenguaje SQL a las clases de PHP de RedBean que hacen exactamente el mismo movimiento.<\/p>\n<p><strong>Mapear<\/strong><\/p>\n<p>Significa que una clase con sus propiedades son traducidas por el ORM a la base de datos y a sus tipos para el esquema de las tablas, en varios ORM esto se hace en 2 pasos, se escribe una clase con sus propiedades y luego se mapea a la base de datos con otra clase que hereda de la primera en RedBean la clase y el mapeo se hacen en una sola clase todo controlado por RedBean ahorrando tener que escribir una de las clases que si es requerida en otros ORM<\/p>\n<p><strong>Conexi\u00f3n a la base de datos, aqu\u00ed usare MySQL en PHP nativo con PDO<\/strong><\/p>\n<p><em>Con PHP PDO<\/em><\/p>\n<p><code>$con = new PDO('mysql:host=localhost;dbname=dragon, usuario, clave);<br \/>\n$con-&gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);<\/code><\/p>\n<p><em>Con RedBean<\/em><\/p>\n<p><code>require \"rb.php\";<br \/>\n$db = new R();<br \/>\n$db-&gt;setup(\"mysql:host=localhost;dbname=rb\",\"usuaro\",\"clave\");<\/code><\/p>\n<p><strong>Crear tablas<\/strong><\/p>\n<p>Todas las tablas en los ORM tienen algo en com\u00fan, siempre traen la columna <strong>id<\/strong> como llave primaria ya que es la gu\u00eda de todo ORM, en el caso de RedBean si la tabla no existe la crea y si existe la mapea<\/p>\n<p><em>Con SQL<\/em><\/p>\n<p><code>create table perfil (id int not null auto_increment primary key);<\/code><\/p>\n<p><strong>con RedBean<\/strong><\/p>\n<p><code>$perfil = $db-&gt;dispense(\"perfil\");<\/code><\/p>\n<p>$perfil en este momento es una clase mapeada de la tabla perfil, si la tabla perfil tenia columnas o campos estos ya se encuentran disponibles para usarse en $perfil de lo contrario $perfil solo contiene la columna id que todo ORM requiere, al momento de escribirle nuevas propiedades a la clase $perfil estas se crearan autom\u00e1ticamente y RedBean escribir\u00e1 el tipo que en su l\u00f3gica crea m\u00e1s conveniente, por ejemplo<\/p>\n<p><code>$perfil-&gt;nombre = \u201cPedro\u201d;<\/code><\/p>\n<p>Esto creara una columna en la tabla perfil si no existe llamada nombre y como el valor pedro se le asigno es de tipo string entonces el tipo de la columna ser\u00e1 varchar otro ejemplo seria $perfil-&gt;edad = 20 , aqu\u00ed se crear\u00eda una columna llamada edad del tipo int<\/p>\n<p><strong>Creando el esquema de la base de datos<\/strong><\/p>\n<p>En el p\u00e1rrafo anterior describ\u00ed como se van creando los tipos en el esquema de la base de datos seg\u00fan la propiedad de la clase en PHP, ahora un ejemplo mas detallado compar\u00e1ndolo con SQL<\/p>\n<p><em>Con SQL<\/em><\/p>\n<p><code>alter table perfil ADD (nombre varchar(200), numero int);<br \/>\ninsert into perfil (nombre,numero) values (\"Last Dragon\",5554449990);<\/code><\/p>\n<p><em>Con RedBean<\/em><\/p>\n<p><code>$perfil-&gt;nombre = \"Last Dragon\";<br \/>\n$agenda-&gt;numero = 5554449990;<br \/>\n$db-&gt;store($perfil);<\/code><\/p>\n<p><strong>Traer un registro o bean y de ser necesario actualizarlo.<\/strong><\/p>\n<p>En RedBean como en otros ORM el eje es el ID por lo que se tiene que conocer el ID del registro que se quiere recuperar, si no se conoce entonces se tiene que buscar con otros m\u00e9todos como find<\/p>\n<p><em>Con SQL<\/em><\/p>\n<p><code>select * from perfil where id = 1;<\/code><\/p>\n<p><em>Con RedBean<\/em><\/p>\n<p><code>$perfil = $db-&gt;load(\u201cperfil\u201d,1);<\/code><\/p>\n<p>$perfil es una clase mapeada con los valores del bean o registro del ID 1 que ya puede ser mostrados, por ejemplo<\/p>\n<p><code>echo $perfil-&gt;nombre;<\/code><\/p>\n<p>en RedBean no existe un m\u00e9todo update, el store sirve para insertar nuevos registros o para actualizarlos, por ejemplo cuando en encuentra que hay una propiedad id con el valor 1 , store sabe que si es llamado lo que se requiere es actualizar lo valores en en registro con valor ID 1 en la DB seg\u00fan las que propiedades que tenga la clase.<\/p>\n<p><strong>Actualizar el n\u00famero es tan simple como asignarle otro valor<\/strong><\/p>\n<p><code>$perfil-&gt;numero = 999910293;<br \/>\n$db-&gt;store ($perfil);<\/code><\/p>\n<p><em>Esto equivale en SQL a:<\/em><\/p>\n<p><code>update perfil set numero=999910293 where id = 1;<\/code><\/p>\n<p><strong>Borrar un registro o bean<\/strong><\/p>\n<p>En RedBean como siempre el eje es el valor ID y el registro borrado es el que ID tenga como valor<\/p>\n<p><em>En SQL<\/em><\/p>\n<p><code>delete from perfil where id = 1;<\/code><\/p>\n<p><em>En RedBean<\/em><\/p>\n<p><code>$perfil = $db-&gt;load(\u201cperfil\u201d,1);<br \/>\n$db-&gt;trash($perfil);<\/code><\/p>\n<p><strong>Buscar el Bean o registro para obtener su ID<\/strong><\/p>\n<p><em>En SQL<\/em><\/p>\n<p><code>select * from perfil where nombre = 'Last Dragon' LIMIT 1;<\/code><\/p>\n<p><em>En RedBean<\/em><\/p>\n<p><code>$db-&gt;findOne( \u201cperfil\u201d, \u201c nombre = ? \u201c, [ \u201cLast Dragon\u201d ] );<\/code><\/p>\n<p>Los ejemplos anteriores solo trae la primera coincidencia de un nombre con valor Last Dragon, si hay mas registros con el valor de Last Dragon se va a ignorar, si se requiere encontrar todos los registros y buscar por c\u00f3digo en PHP<\/p>\n<p><em>En SQL<\/em><\/p>\n<p><code>select * from perfil;<\/code><\/p>\n<p><em>En RedBean<\/em><\/p>\n<p><code>$perfil = findAll( \u201cperfil\u201d );<\/code><\/p>\n<p>Ahora $perfil tiene un arreglo con todos los registros de la tabla perfil se puede ir buscando uno por uno con un foreach , ejemplo.<\/p>\n<p><code>Foreach ($perfil as $registro)<br \/>\n{<br \/>\nEcho $registro[\u201cnombre\u201d];<br \/>\nC\u00f3digo;c\u00f3digo;c\u00f3digo;<br \/>\n}<br \/>\n<\/code><\/p>\n<p><strong>M\u00e9todos muy usados en tiempo de desarrollo<\/strong><\/p>\n<p><em>$db-&gt;freeze(false);<\/em><\/p>\n<p>Mientras esta en falso permite que el ORM cambie el esquema de las tablas a voluntad, metiendo mas columnas o cambiando el tipo de las mismas, cuando esta en TRUE ya no permite ning\u00fan cambio en el esquema de la tabla, TRUE es para producci\u00f3n.<\/p>\n<p><em>$db-&gt;nuke();<\/em><\/p>\n<p>Nuke destruye toda la DB, cuando se est\u00e1 en desarrollo se usa para reiniciar a 0 tanto los datos como las tablas, nuke destruye todo sin miramiento, cuidado al invocarlo.<\/p>\n<p>Para mas informaci\u00f3n sobre este ORM en su sitio WEB <a href=\"http:\/\/www.redbeanphp.com\/\">http:\/\/www.redbeanphp.com\/<\/a> ah\u00ed se encuentra mas documentaci\u00f3n y otros ejemplos de uso.<\/p>\n<p>A continuaci\u00f3n un video que demuestra el funcionamiento de RedBeans con 2 tablas relacionadas con llaves foreaneas, ojo en el video solo guardo una tabla, No te confundas, esto es por que est\u00e1n relacionadas en esta l\u00ednea de c\u00f3digo <em>$agenda-&gt;perfil = $perfil;<\/em> la cual crea una llave for\u00e1nea, como agenda depende de perfil el ORM se da cuenta y entiende que debe guardar tambi\u00e9n perfil, de hecho se guarda primero perfil, los ORM son tecnolog\u00edas muy inteligentes que rara vez fallan en su l\u00f3gica para realizar las funciones de guardado.<\/p>\n<p>Notaras que no hay una sola l\u00ednea de c\u00f3digo SQL en este c\u00f3digo y aun as\u00ed se crea tabla con su esquema correcto y se almacena un valor en ella.<\/p>\n<p><iframe loading=\"lazy\" src=\"https:\/\/www.youtube.com\/embed\/xU3rnNnKDe8\" width=\"420\" height=\"315\" frameborder=\"0\" allowfullscreen=\"allowfullscreen\"><\/iframe><\/p>\n<p><strong>C\u00f3digo del v\u00eddeo<\/strong><\/p>\n<p><code>&lt;?php<\/p>\n<p>require \"rb.php\";<br \/>\n$db = new R();<br \/>\n$db-&gt;setup(\"mysql:host=localhost;dbname=rb\",\"root\",\"\");<br \/>\n$db-&gt;freeze(false);<br \/>\n\/\/ $db-&gt;nuke();<br \/>\n$perfil = $db-&gt;dispense(\"perfil\");<br \/>\n$agenda = $db-&gt;dispense(\"agenda\");<\/p>\n<p>$perfil-&gt;nombre = \"Last Dragon\";<\/p>\n<p>$agenda-&gt;numero = 5554449990;<br \/>\n$agenda-&gt;correo = \"daniel@lastdragon.net\";<br \/>\n$agenda-&gt;nacimiento = \"1995-06-10\";<br \/>\n$agenda-&gt;perfil = $perfil;<\/p>\n<p>$db-&gt;store($agenda);<\/p>\n<p>$agenda = $db-&gt;load(\"agenda\",1);<br \/>\n$perfil = $db-&gt;load(\"perfil\",$agenda-&gt;perfil_id);<\/p>\n<p>echo $perfil-&gt;nombre;<\/p>\n<p>?&gt;<\/code><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Un ORM ( Object-Relational mapping ) o Mapeo objeto-relacional son unas clases usadas en los lenguajes orientados a objetos para controlar las bases de datos en el mejor de los casos con cero conocimiento SQL y en el peor de los casos teniendo que usar algo de SQL para subsanar las limitantes que pudiera tener&#8230;<\/p>\n","protected":false},"author":1,"featured_media":1651,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-1650","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-programacion"],"_links":{"self":[{"href":"https:\/\/www.lastdragon.net\/index.php?rest_route=\/wp\/v2\/posts\/1650","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lastdragon.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.lastdragon.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.lastdragon.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lastdragon.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1650"}],"version-history":[{"count":3,"href":"https:\/\/www.lastdragon.net\/index.php?rest_route=\/wp\/v2\/posts\/1650\/revisions"}],"predecessor-version":[{"id":1654,"href":"https:\/\/www.lastdragon.net\/index.php?rest_route=\/wp\/v2\/posts\/1650\/revisions\/1654"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.lastdragon.net\/index.php?rest_route=\/wp\/v2\/media\/1651"}],"wp:attachment":[{"href":"https:\/\/www.lastdragon.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1650"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.lastdragon.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1650"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lastdragon.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1650"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}