blog1 - anuncio

miércoles, 10 de abril de 2013

Creando mapas de google usando jQuery

3 comentarios:

Extensión jQuery para crear mapas de google basados en direcciones.

Esta es una extensión para jQuery que sirve para crear mapas de google basados en una dirección humanamente legible.

Es muy simple de implementar:

1. copia este script jquery en alguna parte:


  1. <script>
  2. $.fn.googlemap = function(){
  3.         // author: Christian Salazar <christiansalazarh@gmail.com>
  4.         var src='';
  5.         $(this).each(function(){
  6.         var z = $(this);
  7.         var address = jQuery.trim(z.attr('streetnumber'))
  8.                 +'+'+jQuery.trim(z.attr('streetname'))
  9.                 +'+'+jQuery.trim(z.attr('cityname'))
  10.                 +'+'+jQuery.trim(z.attr('statecode'))
  11.                 +'+'+jQuery.trim(z.attr('zipcode'))
  12.         ;
  13.         src="https://maps.google.com/maps?"
  14.                 +"client=safari"
  15.                 +"&q="+address
  16.                 +"&oe=UTF-8&ie=UTF8&hq="
  17.                 +"&hnear="+address
  18.                 +"&gl=us"
  19.                 +"&z="+z.attr('zoom')
  20.                 +"&output=embed";
  21.                 z.html("<iframe src='"+src+"' width="+z.attr('width')+" height="
  22.                 +z.attr('height')+"></iframe>");
  23.         });
  24.         return src;
  25. }
  26. </script>


2. en alguna parte donde quieras mostrar un Mapa de Google pones este script:


  1. <div id='mapa' streetnumber='946' streetname='LAKE+DESTINY+RD'
  2.         cityname='ALTAMONTE+SPRINGS' statecode='FL' zipcode='32714'
  3.         zoom=18 width=500 height=300>
  4. </div>


3. Puedes poner varios mapas, con distintas direcciones, es decir, repitiendo el paso 2 por cada dirección que quieras mostrar,  en este ejemplo usé solo una, pero pudiera ser una lista, ahora usamos jQuery de nuevo para convertir esa cosa en un mapa:

<script>$('#mapa').googlemap();</script>

4. El resultado será:



Múltiples Direcciones

Si fuesen varias direcciones, como este caso que muestro (debajo de este texto), notarás que no uso "id='mapa'", sino un identificador de clase: "class='mapas'", eso es con el objeto de que el script de jquery pueda ser usado asi:

$(".mapas").googlemap();   // notas el punto antes de "mapas"  ? es importante.

lo que hará será que a todos los elementos que tengan la clase "mapas" los convertira en un mapa de google independiente.


  1. <div class='mapas' streetnumber='946' streetname='LAKE+DESTINY+RD'
  2.         cityname='ALTAMONTE+SPRINGS' statecode='FL' zipcode='32714'
  3.         zoom=18 width=500 height=300>
  4. </div>

    <div class='mapas' streetnumber='946' streetname='LAKE+DESTINY+RD'....bla

    <div class='mapas' streetnumber='946' streetname='LAKE+DESTINY+RD'....bla


Otra forma es crear los mapas mediante un elemento UL:


  1. <ul id='mymaps'>
    <li streetnumber='946' streetname='LAKE+DESTINY+RD'
  2.         cityname='ALTAMONTE+SPRINGS' statecode='FL' zipcode='32714'
  3.         zoom=18 width=500 height=300>
  4. </li>
    <li streetnumber='1002' ....bla....</li>
    <li streetnumber='9005' ....bla....</li>

    </ul>

    SIMPLEMENTE:

    $('#mymaps li').googlemap();



Extensión jQuery

La función $.fn.googlemap() es una extensión para jQuery. se denomina así por el uso de "$.fn", lo cual hace que podamos pedirle a un DIV que se convierta en un google map al ser reconocida la extensión.

Extras

var url = $("#mapa").googlemap();   // retorna la URL generada

podria ser usada para crear un vinculo de agrandamiento de mapa:

$("#mapa").parent().append("<a href="+url+">agrandar este mapa</a>");




    lunes, 8 de abril de 2013

    El Issue y el Commit

    No hay comentarios:
    (Orientado a quienes usan a diario o no tanto al sistema de "Issues" de git, o mercurial, etc.)

    "Issues" no significa BUG.  "Issues" hace referencia a un "asunto a resolver". Un asunto puede ser: un bug, una tarea pendiente, una mejora. Cuando se hace un sistema, no es sano hacer un "commit" con 300 modificaciones, se pierde la escencia del uso de GIT.

    Descripción del Issue y clarificación del asunto (issue) a ser resuelto:

    Es sano analizar primero "cual es la falla, o mejora o tarea a realizar".  Una vez clara y firme la idea es, entonces: (lo que siempre insisto) escribirla en texto simple:  "mejora que resuelve el problema xyz".

    Solo al intentar hacer esto (describir el issue) se aclaran ideas internas de uno mismo, se fuerza a discernir entre que es lo objetivo y que es basura. Reto a cualquiera a que lo haga, cuando lo logran han logrado el paso #1 de la ley de UML: "palabras simples que describan un asunto".  Parece simple, pero no lo es. Tras esto, todo lo que sigue es simple...

    Una vez descrito el problema en palabras simples, veran que el problema se resuelve solo: se sabe de antemano que hacer, donde tocar y donde no..y, si hay equipos de desarrolladores involucrados se sabe de antemano a quién se le debe dar la responsabilidad de tal "issue", incluso, a veces se quien debe hacer exactamente qué cosa.  Normalmente, una sola persona es la encargada de tal issue. Síntoma: cuando dos personas son responsables de un mismo issue estamos posiblemente ante la presencia de dos issues distintos.

    Finalmente, el trabajo sucio: El issue se crea, se detalla y se procede a resolverlo (cambios en código), se aplican los cambios que afectan exclusivamente "al issue" y no a toda la sarta de asuntos que nos econtramos en el camino, estos requerirán de su propio análisis, si es que no afectan o contribuyen al issue.

    "Ruido de Commit" (commit-noise)

    Ruido de Commit es toda aquella sarta de basura que quedo en el camino de resolución, que solo produce ruido, no resuelve y solo agranda el commit.

    Por ejemplo, resolviendo un problema "XYZ" hemos hallado que hay un error ortográfico: es un issue independiente, por qué ? porque al reparar ese error ni afectamos ni resolvemos el issue. Quiza hayan 10 errores (no vas a hacer un issue por cada error) simplemente haces un nuevo issue que refleje que tu estás "reparando errores ortograficos" y en éste commit haces "solo correcciones ortograficas"...no correcciones "de paso".

    Qué sucede si hemos resuelto un issue y mas tarde detectamos que quedó mal hecho ?

    No vas a hacer otro issue...porque entonces tendrás un mismo issue en dos partes, lo que si habrá obviamente será un nuevo commit, con los cambios que resuelven el BUG. Al hacer el commit entonces lo etiquetas asi:
    git commit -a -m "FIX ISSUE #77 (reopened)"
    Luego, vas al issue #77, lo reabres y anotas en él al commit nuevo que se ha generado, con su respectiva documentación.

    Qué sucede si hemos resuelto un issue, y dejamos tareas pendientes (TODO: xxx)

    Es un nuevo issue. Tipo TASK o ENHANCEMENT. Detallarás en ese nuevo issue el asunto que quieres mejorar.

    Los comandos "git diff", "git checkout"

    Al hacer el "commit" que resuelve a un determinado "issue", se hace así, en este orden militar:

    "git diff"  
    previamente una revisión. Descartar con "git checkout" a todo aquel archivo que contiene cambios que no tienen nada que ver con el issue, esto es para limpiar el commit de "ruido de commit".
    Por ejemplo, si resolviendo un issue determinado modificamos un archivo "libro.php" que no tenia pito que tocar, pero que en el proceso de resolución del issue ha sido modificado por la razón que fuere, pues simplemente lo descartamos:
    "git checkout ruta/abc/libro.php"
    se han descartado todos los cambios en "libro.php", quedando el commit libre de: "ruido de commit"

    "git commit -a -m 'FIX ISSUE #99' "si, el issue 99 previamente creado y descrito.

    "git push"

    hemos enviado la criatura al repositorio.

    Es limpio. ayuda a quienes tengan que lidiar con el codigo que hemos creado y nos ayuda a nosotros mismos a hacer buen software.

    viernes, 15 de febrero de 2013

    Clases y Tablas - Por qué no son lo mismo.

    No hay comentarios:
    Clases y Tablas, Por qué no son lo mismo.


    Siempre le insistido a quienes me leen en el Blog (o grupo de Yii en Español) que no es lo mismo "Tabla" que "Clase", sin embargo a veces recibo respuestas de algunas personas que se molestan y defienden a ciegas aquella idea de que "son lo mismo".

    Normalmente siempre empiezo por insistir que: "No es lo mismo crear una Arquitectura de Clases, que crear Una Clase con 500 métodos", en este último caso, luciendose de haber hecho un programa de 20.000 lineas que solo él y dios sabrán como funciona.  Por contraparte, la Arquitectura de Clases es delicada, es toda una dama.

    Es incorrecto pensar que una Clase, por el hecho de tener atributos igual que una Tabla es entonces inmediatamente "emparejable con una tabla de base de datos". Es un terrible concepto arraigado por la falta de análisis y por el hecho de programar a ciegas.

    La Clase es la "idea" maestra, el concepto, mientras que la "tablita de base de datos" es solo una artimaña tosca para guardar la información de la clase.  De aqui que siempre digo que es un error diseñar un sistema pensando en el modelo de base de datos (el diagrama de tablas, el diagrama de entidad-relación).


    No siempre una clase es almacenada en una "tabla"

    No siempre una "tabla" representa a la Clase, No siempre una tabla representa a una Relación y finalmente no siempre una tabla representa a una Entidad.

    Cuales son las diferencias entre Clases de Asociación y Entidades. Concepto.

    Caso de Ejemplo de Diseño UML:
    Antes de explicar mas abajo necesito que tengas claro este ejemplo de caso de negocio, para que comprendas mejor el diagrama que está mas abajo y los conceptos de Clase-Entidad y Clase-de-Asociación.

    "Una persona quiere laborar como agente de ventas para una empresa de RealtyRentals, se le denomina El Agente (primer sustantivo detectado en la conversación). Para poder laborar en la empresa, este Agente necesita adquirir un Plan (segundo sustantivo), este Plan se le cobra mensualmente y le permite realizar ciertas operaciones de acuerdo a su pago (no detallaré qué y cómo, no viene al caso, sino enredamos el ejemplo).  Adicionalmente, este Agente querrá publicar información en su propio website privado, por lo tanto le daremos una LLave de Acceso (tercer sustantivo) para que a través de ella pueda leer recursos web en su propio website.  Esta Llave de Acceso se paga también mensualmente pero separado del pago del Plan de membresía"

    Una Clase-Entidad representa a una Entidad, a un objeto Real
    Se reconocen por ser un SUSTANTIVO en las conversación con el cliente. De ahí el hecho de que el análisis UML haga énfasis en anotar cuales sustantivos usa el cliente durante su conversación contigo como analista. Por ejemplo: El Agente. Es una clase-entidad porque representa a un ser humano operando como agente de ventas en un negocio. El arte de UML está en saber oir: cuales sustantivos son una real basura y cuales son valiosos.

    Una Clase de Asociación. 
    Es también una clase, pero enfocada a relacionar dos Clases-Entidad.  Representa la forma en cómo dos objetos se relacionan. Por ejemplo, informa de la relación que ocurrirá cuando el Agente seleccione un Plan.  Ambos Agente y Plan son Clases-Entidades, mientras que La Relación sería: "La historia de Planes adquiridos por El Agente en el Tiempo y Soportados por un Pago"....no adivinaste? "EL INVOICE".

    Una Clase de Asociación tiene un diagrama UML específico.
    Se representa así como muestro aca abajo: una linea punteada terminando en  flecha que apunta a la linea recta entre las dos entidades a ser relacionadas, indicando que: "La factura guarda la relacion entre las entiadades: el Plan y el Pago".



    La relación XY

    Siempre hago referencia a que un diagrama XY (la relación XY) que incluye clases-entidad y clases-de-asociación se llama: "Relación XY", porque XY representa la asociación entre la clase X y la Y.

    Explicando el Diagrama de Clases



    La clase-entidad "AgentPayment" se relaciona con otra clase-entidad "AgentPlan" mediante la clase de asociación: "AgentPlanInvoice".  AgentPayment es independiente es un pago, es único, igual que AgentPlan, son clases simples, que representan una entidad.

    AgentPlanInvoice informa cómo estas dos se relacionan (el pago a un plan), no es un objeto "físico" como las primeras, sino es un paso en el tiempo.  AgentPlanInvoice es una Factura que le damos al Agente por querer contratar el AgentPlan seleccionado, esa factura le da acceso por tiempo limitado a usar el sistema.

    Verás que también tenemos ResourceKeyInvoice, que según el requisto del cliente (arriba) le da derecho al agente de tener una "llave de recursos web" para que pueda insertar contenido web en el propio website del Agente.

    Extensión de Clases

    El objeto de mostrar esta extensión aquí es demostrar que no siempre una "Clase" se almacena igual que una  "Tabla".

    La extensión aquí se requiere porque AgentPlanInvoice y ResourceKeyInvoice derivan o extienden su funcionalidad de una clase abstracta llamada Invoice que agrupa cosas comunes entre estas, es abstracta porque no puede usarse así "a rin pelao"...(yo soy un invoice !!!,  de quien ? de que tipo ?).

    El Invoice (La Factura) le provee a sus clases extendidas la funcionalidad e incluso atributos, podriamos tener en esta clase base (Invoice) un método llamado: "sendByEmail()" el cual enviará este invoice al Agente por correo, sea "de clase" ResourceKey o "de clase" AgentPlan. El símbolo UML para denotar la extensión es la flecha con cabeza blanca sólida.

    ¿ Cómo almacenar las clases en un modelo de datos ?

    He aquí el guiso. Y He aquí porqué siempre digo que hacer el sistema empezando el diagrama de datos es siempre un error que viene de vieja escuela y de fundamentos teóricos oxidados y mal formados, en su mayoría hecho asi por comodidad y por el hecho de no profundizar en el Análisis de Sistemas.

    AgentPlanInvoice y ResourcePlanInvoice estan diagramados en dos clases distintas, eso lleva a pensar al diseñador de software que deben ir en dos "tablas" separadas.....de nuevo...esta malo. Una cosa es: Diagramado UML, diagramado de Negocio, otra "diagramado de datos".

    En este ejemplo no se requieren dos "tablas" separadas para almacenar a AgentPlanInvoice y ResourceKeyInvoice, sino solo una.  Esto demuestra la razón de mi insistencia. Podrias almacenar AMBAS CLASES en una sola tabla asi:

    "AgentInvoice" { agentId, invoiceType,  invoiceNumber, invoiceTotal, expirationDate, creationDate }

    Ahora, será tarea de la clase base Invoice, leer un registro de LA TABLA "AgentInvoice" y entregar en consecuencia un objeto de clase AgentPlanInvoice o de ResourceKeyInvoice, según indique el registro de base de datos.

    Ahora te habrás dado cuenta que aunque el diagrama UML habla de tres clases (Invoice, AgentPlanInvoice y ResourceKeyInvoice) estas se almacenan en una sola, y no las tres, sino solo dos, ya que Invoice es abstracta.

    "El análisis produndo de software es el camino al buen software"


    viernes, 1 de febrero de 2013

    tutorial mínimo de yii

    2 comentarios:



    En el pasado...

    En tu antigua app hecha en PHP tu seguramente habras tenido piezas de codigo, funciones y demas cosas accesibles directamente asi:

    http://miapp/cosa/mas/otra/crearorden.php

    Eso es totalmente inseguro, a menos que tengas muchas reglas internas y mucha protección, pero si no es asi, estaras dispuesto a aceptar que cualquier que analice uno de tus form sepa cual es la accion a donde ese form va a enviar un POST y te bombardearán.

    Yii framework te da una CAPA DE PROTECCION para que la única manera de acceder a ese mismo recurso "crearorden" se haga solo mediante una URL y pasando previamente por un punto de control: EL CONTROLADOR.

    Aqui entramos a hablar de MVC. Model, View y Controller.

    En tu antiguo sistema, tu guardabas tu informacion en tu base de datos, seguramente desde una consulta SQL horrorosamente igual a esta:
    "insert into orden(...campos...) values(...y valores aqui...)";
    Eso tambien es inseguro, propenso a inyección SQL, y peor aun inmanejable y dificilmente exportable.

    El MODELO

    Yii Framework te provee el MODELO para gestionar facilmente objetos persistentes (cosas que se guardan en una "tabla"), el modelo es una representacion de una TABLA (Orden.php), el modelo es algo mucho mas avanzado en términos de modelado UML, pero para no enredar el papagallo aqui vamos a simplificarlo solo a una "tabla", que en realidad no se llama "tabla" sino "relacion".

    Supon que tienes:


    Código:
    $orden = new Orden();
    $orden->idorden = '123-ABC';
    $orden->total = 1000;
    $orden->cliente = "nombre del cliente";
    // ok..simplemente usando las clases base
    // que Yii te provee podrás hacer:
    $orden->insert();
    y listo...la cosa se guardo en la base de datos. Simple. 

    Esto se llama: 
    CActiveRecord. Conseguiras muchos ejemplos en el foro y en la documentacion de Yii.
    Dónde guarda Yii los modelos ? En protected/models.
    Cómo se accede a ese modelo ? Directamente no....sigue leyendo tigre...

    LA VISTA

    La vista es la forma de presentar información, no hay lógica de negocios en las vistas, la lógica se la das a UN COMPONENTE o a ciertos ACTIONS (lee mas adelante), pero nunca a las vistas.

    Mi papa siempre decía: "cuando se calcula..se calcula, cuando se imprime..se imprime". Eso significa que "o cantas o silbas"....y traduciendo a codigo: O muestras o calculas...pero no ambas.

    La vista se aloja en /protected/views/<controllername>/nombrevista.php

    Porque dentro de un <controllername> ? Para ordenar, nada mas, desde cualquier parte puedes acceder a cualquier vista, pero este esquema ayuda a ordenar.

    Cómo accedo a una vista ? 
    Desde un ACTION, el cual explico mas abajo.

    Qué hago en una vista ?
    Mostrar el modelo, mostrar tablas, imprimir html. Podria recomendarte esta extension para escribir en una vista:
    http://christiansalazar.github.com/jamboree/

    EL "CONTROLLER" y EL ACTION

    Por fin aqui no ? Bueno, esta es la "pega" que une el modelo con la vista. Es tambien el punto de entrada, en programacion orientada a EVENTOS (como lo es YII) esto se considera un ENTRYPOINT (del viejo esquema C en donde una funcion main() es la encargada de iniciar el programa).

    Si ya creaste un modelo Orden.php y ya tienes una vista "protected/views/orden/ver.php" entonces ahora querras acceder a esta vista para ver el modelo (cual modelo ? el que seleccionaremos en el controller en base a los argumentos de la URL).
    Código:
    http://www.miapp.com/tuapp/index.php?r=orden/ver&idorden=123

    Explico la forma de esa URL para Yii Framework:


    "r=orden/ver" es la forma de decirle a Yii que vaya a la controladora "ordenController.php" localizada por defecto en "protected/controllers", y que en esa clase busque el ACTION "ver". Habrás pensado que cuando puse "ver" en la url haya sido respecto a la vista "/protected/views/orden/ver.php" pues no, es el action dentro de ordenController.php.


    ¿ Cómo se pone ese action en ordenController.php ?


    asi: Editas /protected/controller/ordenController.php y dentro escribes:

    Código:
    <?php
    public function OrdenController extends CController {
        public function actionVer($idorden){
            $model = Orden::model()->findByPk($idorden);
            if($model != null){
               $this->render("ver", array('laorden'=>$model));
            }else{
               throw new CHttpException(404, "orden no hallada");
            }
        }
    }
    ?>

    Fíjate que es dentro de actionVer en donde se invoca al modelo segun el argumento de la URL, para entonces finalmente pedirle al controller que haga una presentacion de la vista "
    ver.php" ( render('ver') ), la cual "se asume que" estara localizada en:
    protected/views/orden/ver.php. Pestale cuidado a por qué puse la palabra "ver" en color rojo.

    El layout

    Es importante, es quien da el marco html para que dentro de el se presenten las vistas, habras asumido que no tendrás que poner en cada vista el cintillo...el banner..el sidebar...estas en lo cierto. Eso lo hace el layout, veras que cada controller puede tener un atributo llamado "layout", que por defecto puede ser:
    public $layout = '\layouts\main'; eso le dice a Yii que para renderizar las vistas del controller lo haga usando el layout localizado en protected/views/layouts/main.php, el cual a su vez veras que incluye otros mas, pero eso es tema mas avanzado, aqui quiero que conozcas la base sin muchos detalles.

    Muy Importante:  Dónde se presenta la vista en un Layout ?

    En Yii hay una variable clave llamada $content.   En donde esa variable se ponga será allí en donde la vista se dibuje.

    Fíjate este ejemplo, podria estar perfectamente ubicado en:  tuapp/protected/views/layouts/prueba.php, y para que Yii lo use para renderizar una vista hay que mencionarlo en el controller en el atributo $layout.

    <html>
       <body>
             <span>Aqui va el cuerpo: </span>
             <div><?php echo $content; ?></div>
       </body>
    </html>

    Lo que hará será incrustar allí (donde este $content) el contenido de aquella vista que en un controller qusimos "renderizar" usando una llamada a $this->render('ver');

    Cómo funciona YII

    1) Tu usuario pone en el browser:  http://website.com/cosa/index.php?r=site/prueba

    2) El archivo index.php recibe el request (siempre lo hace, jamas otro script recibe el foco).

    3) El core de Yii levanta tu archivo de config indicado en index.php y de éste se incializa.

    4) Levanta a:  protected/controllers/siteController.php.  (sensible a mayusculas minusculas).

    5) Busca el método: "public function actionPrueba" y lo ejecuta.

    6) Si la URL incluye argumentos como: &cedula=123&nombre=christian, se los pasará como argumentos al método actionPrueba, por tanto si esperas esos argumentos, ponlos en el método asi:
    public function actionPrueba($cedula="", $nombre="").
    (nota el ="" detras de cada argumento, eso dice que son opcionales, si no lo pones así entonces ocurrirá una excepción si el usuario no los indica en la URL).

    7) En el método actionPrueba es donde tu actuas.  Podrias levantar un modelo cualquiera asi:
    public function actionPrueba($idproducto){
       $p = Producto::model()->findByPk($idproducto);
       if($p != null){
          $this->render('producto', array('cosa'=>$p));
       }
    }

    8) Siguiendo el ejemplo del paso 7, has indicado que quieres renderizar la vista "producto":
    "/protected/views/prueba/producto.php", eso es debido a que en el paso 7 solo pusiste "producto" sin ruta, (si quisieras indicar la ruta de otra vista pondrias:
    "applications.views.otrolado.detalle", eso usaría la vista: "protected/views/otrolado/detalle.php")

    9) La vista "producto.php" es levantada del disco, y se le entregan variables PHP, cuales variables ? las que le diste en el paso7 mediante un array, por tanto dentro de la vista producto.php puedes escribir esto:
    <?php
       echo "has invocado a la vista. el objeto entregado por el controller es: "
          .$cosa->idproducto.", ".$cosa->nombreProducto;
    ?>

    10) Cuando en el paso 7 llamaste a render, Yii le dio a tu vista unas variables, las has usado para crear la vista y ahora sera insertada en el Layout.  Yii va a levantar el Layout indicado en el controller, según la variable indicada:

    public function siteController extends CController {
        public $layout = "mi-layout";
        ...
    }

    Se usara al achivo:  protected/views/layouts/mi-layout.php,  Yii cargará toda la vista recien renderizada en el paso 9 en una variable especial llamada: $content la cual tu vas a poner en algun lado del layout: literalmente donde te de la gana:

    <!-- contenido del archivo: protected/views/layouts/prueba.php -->
    <html>

       <body>
             <span>Aqui va el cuerpo: </span>
             <div>
    <?php echo $content; ?></div>
       </body>
    </html>

    (el texto de color "verde" es lo que se repetirá siempre, no importa cual vista estes renderizando, siempre que incluyas este layout en tu controladora)

    11) El resultado del paso 10 será entregado al browser del cliente, el cual dirá:

    <html>
       <body>
             <span>Aqui va el cuerpo: </span>
             <div>has invocado a la vista. el objeto entregado por el controller es: 123, Arroz</div>
       </body>
    </html>





    EL COMPONENTE

    Cómo hacer un componente. Lee eso.

    basicamente un componente aloja la lógica de negocios, yo le llamo un "API" porque es la libreria de funciones core de tu aplicacion. Hay cosas que necesitas en varias partes de la aplicacion, esas "cosas que van en varias partes" que son "reutilizables" son parte del "core" de tu aplicacion, y deben estar localizadas en un punto de comun acceso para toda la app, no abuses del componente, lo hagas un desastre, úsalo pero sin abuso.
    Se usa asi:
    Código:
    Yii::app()->micomponente->calcularNomina($idempleado);

    Esa funcion de negocios puede ser llamada desde cualquier parte de tu app, va a centralizar el proceso de calculo de de nomina de un empleado.


    Y por qué no va en la clase Empleado Christian..??!! (me lo han gritado), Porque este tipo de funciones de negocio involucra muchas otras clases y no solo al Empleado, invoulcra además a la Nomina, al HoarioLaboral, al TurnoQueCumple, a muchas otras clases, entonces para no adivinar en cual de esas otras debe ir...va afuera, en un API.

    Dejare el tema hasta aqui. Creo ser suficientemente claro para darte un inicio en Yii.
    Suerte

    martes, 29 de enero de 2013

    OpenProj error “Your Java vendor is Oracle Corporation”

    2 comentarios:
    OpenProj es un sistema que funciona con Java Runtime, esta hecho para gestionar Proyectos.

    La url para obtenerlo es:
    http://sourceforge.net/projects/openproj/?source=dlp

    La instalación es bien simple, desde Linux, solo descomprimir el contenido del paquete descargado en el directorio /usr , requiere superusuario, obviamente.

    Para ejecutarlo simplemente correr este comando:  openproj

    El problema es:

    Require Java Runtime del "vendor" SUN, y desde que Oracle tomo el control de la cosa ahora Java ya no es de SUN sino de Oracle y eso no le gusta a OpenProj porque para la fecha de su creación era Sun el vendor y no Oracle como ahora.

    Solución:

    Se debe editar el archivo de configuracion local localizado en el directorio:
    /home/tu-usuario/.openproj/run.conf

    y poner lo siguiente en la línea de JAVA_OPTS:

    JAVA_OPTS="-Djava.vendor=Sun -Xms128m -Xmx768m"

    listo, con eso la cosa funciona.