Jun
08
2011
3

Portando OpenWRT a un Mikrotik RouterBoard RB133C



Hace unos días he conseguido ejecutar OpenWRT en un Mikrotik RouterBoard RB133C siguiendo las instrucciones que podemos leer en http://rb1xx.ozo.com/doku.php

Esto nos puede ser útil si hemos perdido la licencia porque hemos formateado la NAND y no hemos hecho copia de la misma, tal y como ha sido el caso, y pagar mas de 30€ por una licencia para esta placa hoy en dia ya no tiene sentido. Así que nos ponemos manos a la obra.

En mi caso he compilado todo desde cero con una version mas actualizada de OpenWRT de la que existe en la Web nombrada anteriormente, ya que necesitaba el driver ath5k del kernel y no lo encontraba en ningun paquete precompilado de OpenWRT ya que tiene que coincidir con la versión del kernel.

Guia rápida

Para los impacientes aqui tenemos una guía rapida. Conectamos el router por el puerto serie a nuestro PC a 115200, 8N1.

  • Actualiza la versión de firmware del RouterBOOT booter, el gestor de arranque de estos routers, con una versión 2.7 o mejor. En mi caso he llegado a probar con una 2.3 y funcionaba, pero puestos a actualizar actualizamos a la última version. Podemos bajarla desde aquí. Para actualizarla entramos en el setup de gestor de arranque y pulsamos la G para actualizar. En este momento podemos mandar la actualización del firmware en formato xmodem con la utilidad de Terminal que estemos utilizando. Una vez que se ha subido se auto-flashea y ya tenemos la nueva versión. Este proceso no tarda mas de un minuto.
  • Formateamos la NAND desde el RouterBOOT booter.
  • Descargamos la imagen netboot para arranque por red del RouterBoard. Necesitas un servidor DHCP y TFTP funcionales en la red donde especifiquemos en el DHCP quien es el servidor TFTP y cual es el archivo de arranque por red. Al final del documentos tendrás unos pasos muy básicos a seguir.
  • Selecciona en desde el menu del RouterBOOT booter que arranque por red y por DHCP en vez de BootP y reiniciamos. En este momento arrancará la imagen netboot y en pocos segundos tendremos OpenWRT en nuestro Mikrotik. En este punto es un arranque por red, asi que vamos a instalarlo.
  • Una vez arrancado necesitaras acceso a un servidor Web o conexion a Internet en el Mikrotik RB133C. Puedes configurarlo rapidamente con los siguientes comandos:
ifconfig eth0 172.16.0.10 netmask 255.255.255.0
route add default gw 172.16.0.1
echo "nameserver 8.8.8.8" > /etc/resolv.conf
  • mount /dev/mtdblock2 /mnt; cd /mnt; wget kernel
  • cd /; umount /mnt; mount /dev/mtdblock3 /mnt; cd /mnt; wget openwrt-adm5120-router_le-rootfs.tar.gz
  • tar zxvf openwrt-adm5120-router_le-rootfs.tar.gz; rm openwrt-adm5120-router_le-rootfs.tar.gz; cd /; umount /mnt; sync; reboot
  • Volvemos a entrar al setup del RouterBOOT y cambiamos el arranque de red a NAND y reiniciamos.
  • Ya tenemos nuestro RB133C funcionando con OpenWRT. Es una imagen muy básica, por lo que si te gusta y quieres mas tendras que compilarte tu una versión nueva.

 

Compilación desde el trunk de OpenWRT

En mi caso he utilizado Ubuntu 11.04 con el paquete basico de compilación (aptitude install build-essential). Una vez que tenemos todos los requisitos nos ponemos a bajar el fuente y a compilar.

En mi caso he utilizado la revisión 23709 de OpenWRT y un kernel 2.6.33.5 que cambie ya que la revisión que bajé por defecto usaba otro kernel.

cd /home/dev/rb133c
snv -r 23709 co svn://svn.openwrt.org/openwrt/trunk
cd trunk
svn co svn://svn.openwrt.org/openwrt/packages/
make pacakge/symlinks

Salimos del menú que nos aparece y editamos el archivo target/linux/adm5120/Makefile y cambiamos la línea donde dice que utiliza el kernel 2.6.32.24 por 2.6.33.5

Ejecutamos «make menuconfig» desde el trunk configuramos el tipo de placa que tenemos y elegimos los paquetes que queremos tener en nuestro RB133C. Una vez que hemos elegido, salimos salvando los cambios.

  • Target System > Infineon / ADMtek ADM5120
  • Subtarget > Little Endian
  • Target Profile > Mikrotik RouterBoard RB1xx family
  • Target Images > tar.gz

Ahora es hora de configurar el kernel correctamente, para ello ejecutamos «make kernel_menuconfig» y seleccionamos lo siguiente:

  • Machine Selection > System Type > Infineon / ADMtek ADM5120 SoC based machines
  • Machine Selection > ADM5120 Board selection > Mikrotik RouterBoard 1xx (Las que queramos… todas)

Aseguraros que el kernel tambien tiene activas las siguientes opciones, aunque deberian estarlo al seleccionar el tipo de procesador.

CONFIG_YAFFS_FS=y
CONFIG_YAFFS_YAFFS1=y
CONFIG_YAFFS_YAFFS2=y
CONFIG_YAFFS_AUTO_YAFFS2=y
CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_ECC_SMC=y
CONFIG_MTD_NAND_RB100=y
CONFIG_MTD_NAND_IDS=y
CONFIG_MTD=y
CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_SPLIT_ROOTFS=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_MYLOADER_PARTS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
CONFIG_MTD_GEN_PROBE=y
CONFIG_MTD_MAP_BANK_WIDTH_1=y
CONFIG_MTD_MAP_BANK_WIDTH_2=y
CONFIG_MTD_MAP_BANK_WIDTH_4=y
CONFIG_MTD_CFI_I1=y
CONFIG_MTD_CFI_I2=y
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_CFI_AMDSTD_FORCE_BOTTOM_BOOT=y
CONFIG_MTD_CFI_UTIL=y
CONFIG_MTD_COMPLEX_MAPPINGS=y
CONFIG_MTD_ADM5120=y
CONFIG_MTD_BLOCK2MTD=y

Una vez hecho esto empezamos a compilar con «make V=99» y esperamos un rato (de 1 a 2 horas, depende de tu CPU) a que acabe para poder probar nuestra compilación.

Una vez que ha acabado podemos encontrar el kernel en bin/adm5120/openwrt-adm5120-router_le-rb1xx-kernel y en sistema de archivos en bin/adm5120/openwrt-adm5120-router_le-rootfs.tar.gz que utilizaremos como en la guía rápida que esta mas arriba, pero en este caso en vez de con mi compilación, es un OpenWRT compilado por nosotros a nuestro gusto. Formateamos NAND, arrancamos con el netboot image, y copiamos kernel a mtdblock2 y el rootfs a mtdblock3.

Y ahora llega la hora de la verdad, si arranca o no. Creo que no me he saltado ningun paso, si tenéis alguna duda poned un post y revisad antes la pagina Web mencionada anteriormente que viene todo mucho mas detallado.

 

Log de arranque

RouterBOOT booter 2.7
 
RouterBoard 133C3
 
CPU frequency: 175 MHz
Memory size:  16 MB
 
Press any key within 2 seconds to enter setup..
loading kernel from nand... OK
setting up elf image... OK
jumping to kernel code
Linux version 2.6.33.5 (javier@gedeon) (gcc version 4.3.3 (GCC) ) #2 Sun May 8 12:40:09 CEST 2011
bootconsole [early0] enabled
CPU revision is: 0001800b (MIPS 4Kc)
SoC      : ADM5120 rev 8, running at 175.000 MHz
Bootdev  : NAND flash
Prom     : RouterBOOT
Determined physical RAM map:
memory: 01000000 @ 00000000 (usable)
Initrd not found or empty - disabling initrd
Zone PFN ranges:
Normal   0x00000000 -> 0x00001000
Movable zone start PFN for each node
early_node_map[1] active PFN ranges
0: 0x00000000 -> 0x00001000
Built 1 zonelists in Zone order, mobility grouping off.  Total pages: 4064
Kernel command line:  console=ttyS0,115200 rootfstype=squashfs,yaffs2,jffs2
PID hash table entries: 64 (order: -4, 256 bytes)
Dentry cache hash table entries: 2048 (order: 1, 8192 bytes)
Inode-cache hash table entries: 1024 (order: 0, 4096 bytes)
Primary instruction cache 8kB, VIPT, 2-way, linesize 16 bytes.
Primary data cache 8kB, 2-way, VIPT, no aliases, linesize 16 bytes
Memory: 13588k/16384k available (2034k kernel code, 2796k reserved, 354k data, 152k init, 0k highmem)
NR_IRQS:24
Calibrating delay loop... 173.56 BogoMIPS (lpj=347136)
Mount-cache hash table entries: 512
NET: Registered protocol family 16
MIPS: machine is Mikrotik RouterBOARD 133C
registering PCI controller with io_map_base unset
bio: create slab <bio-0> at 0
pci 0000:00:01.0: BAR 0: assigned [mem 0x11400000-0x1140ffff]
pci 0000:00:01.0: BAR 0: set to [mem 0x11400000-0x1140ffff] (PCI address [0x11400000-0x1140ffff]
PCI: mapping irq for 0000:00:01.0 pin:1, irq:14
Switching to clocksource MIPS
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 512 (order: 0, 4096 bytes)
TCP bind hash table entries: 512 (order: -1, 2048 bytes)
TCP: Hash tables configured (established 512 bind 512)
TCP reno registered
UDP hash table entries: 256 (order: 0, 4096 bytes)
UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
NET: Registered protocol family 1
squashfs: version 4.0 (2009/01/31) Phillip Lougher
Registering mini_fo version $Id$
JFFS2 version 2.2 (NAND) (SUMMARY) (LZMA) (RTIME) (CMODE_PRIORITY) (c) 2001-2006 Red Hat, Inc.
yaffs May  7 2011 22:10:22 Installing.
msgmni has been set to 26
io scheduler noop registered
io scheduler deadline registered (default)
Serial: AMBA driver
apb:uart0: ttyS0 at MMIO 0x12600000 (irq = 9) is a AMBA
console [ttyS0] enabled, bootconsole disabled
console [ttyS0] enabled, bootconsole disabled
apb:uart1: ttyS1 at MMIO 0x12800000 (irq = 10) is a AMBA
adm5120-flash.0: probing at 0x1FC00000, size:128KiB, width:8 bits
Found: PMC Pm39LV010
adm5120-flash.0: Found 1 x8 devices at 0x0 in 8-bit bank
CFI mfr 0x0000009d
CFI id  0x0000001c
number of JEDEC chips: 1
adm5120-flash.0: found at 0x1FC00000, size:128KiB, width:8 bits
adm5120-flash.0: adding static partitions
Creating 2 MTD partitions on "adm5120-flash.0":
0x000000000000-0x000000010000 : "booter"
0x000000010000-0x000000020000 : "firmware"
NAND device: Manufacturer ID: 0xad, Chip ID: 0x76 (Hynix NAND 64MiB 3,3V 8-bit)
Scanning device for bad blocks
Creating 2 MTD partitions on "gen_nand":
0x000000000000-0x000000400000 : "kernel"
0x000000400000-0x000004000000 : "rootfs"
mtd: partition "rootfs" set to be root filesystem
split_squashfs: no squashfs found in "gen_nand"
ADM5120 built-in ethernet switch driver version 0.1.1
adm5120_wdt: Watchdog Timer version 0.1
TCP westwood registered
NET: Registered protocol family 17
802.1Q VLAN Support v1.8 Ben Greear <greearb@candelatech.com>
All bugs added by David S. Miller <davem@redhat.com>
trxsplit: searching TRX header in 'booter'
trxsplit: searching TRX header in 'firmware'
trxsplit: 'kernel' is not a NOR flash, skipped
trxsplit: 'rootfs' is not a NOR flash, skipped
yaffs: dev is 32505859 name is "mtdblock3"
yaffs: passed flags ""
yaffs: Attempting MTD mount on 31.3, "mtdblock3"
yaffs: auto selecting yaffs1
yaffs_read_super: isCheckpointed 0
VFS: Mounted root (yaffs2 filesystem) readonly on device 31:3.
Freeing unused kernel memory: 152k freed
Please be patient, while OpenWrt loads ...
gpio-buttons driver version 0.1.2
input: gpio-buttons as /devices/platform/gpio-buttons/input/input0
Button Hotplug driver version 0.4.1
- preinit -
Registered led device: power
Registered led device: user
Registered led device: lan1_speed
Registered led device: lan1_lnkact
Press the [f] key and hit [enter] to enter failsafe mode
- regular preinit -
- init -
 
Please press Enter to activate this console. device eth0 entered promiscuous mode
br-lan: port 1(eth0) entering forwarding state
Compat-wireless backport release: compat-wireless-2010-10-14-7-gab01eca
Backport based on wireless-testing.git master-2010-10-19
cfg80211: Calling CRDA to update world regulatory domain
cfg80211: World regulatory domain updated:
(start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
(2402000 KHz - 2472000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
(2457000 KHz - 2482000 KHz @ 20000 KHz), (300 mBi, 2000 mBm)
(2474000 KHz - 2494000 KHz @ 20000 KHz), (300 mBi, 2000 mBm)
(5170000 KHz - 5250000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
(5735000 KHz - 5835000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
PCI: Enabling device 0000:00:01.0 (0000 -> 0002)
ath5k 0000:00:01.0: registered as 'phy0'
Registered led device: ath5k-phy0::rx
Registered led device: ath5k-phy0::tx
ath5k phy0: Atheros AR5211 chip found (MAC: 0x42, PHY: 0x30)
ath5k phy0: RF5111 5GHz radio found (0x17)
ath5k phy0: RF2111 2GHz radio found (0x23)
Broadcom 43xx driver loaded [ Features: PL, GPIO LED Mask: 0x000f, Firmware-ID: FW13 ]
tun: Universal TUN/TAP device driver, 1.6
tun: (C) 1999-2004 Max Krasnyansky <maxk@qualcomm.com>
ip_tables: (C) 2000-2006 Netfilter Core Team
nf_conntrack version 0.5.0 (214 buckets, 856 max)
CONFIG_NF_CT_ACCT is deprecated and will be removed soon. Please use
nf_conntrack.acct=1 kernel parameter, acct=1 nf_conntrack module option or
sysctl net.netfilter.nf_conntrack_acct=1 to enable it.
xt_time: kernel timezone is -0000
IMQ driver loaded successfully.
Hooking IMQ before NAT on PREROUTING.
Hooking IMQ after NAT on POSTROUTING.
ath_hal: module license 'Proprietary' taints kernel.
Disabling lock debugging due to kernel taint
ath_hal: 2009-05-08 (AR5210, AR5211, AR5212, AR5416, RF5111, RF5112, RF2413, RF5
413, RF2133, RF2425, REGOPS_FUNC, XR)
ath_pci: trunk
wlan: trunk
wlan: mac acl policy registered
ath_rate_minstrel: Minstrel automatic rate control algorithm 1.2 (trunk)
ath_rate_minstrel: look around rate set to 10%
ath_rate_minstrel: EWMA rolloff level set to 75%
ath_rate_minstrel: max segment size in the mrr set to 6000 us
adm5120_wdt: enabling watchdog timer
 
BusyBox v1.17.3 (2011-05-07 21:55:18 CEST) built-in shell (ash)
Enter 'help' for a list of built-in commands.
 
_______                     ________        __
|       |.-----.-----.-----.|  |  |  |.----.|  |_
|   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
|_______||   __|_____|__|__||________||__|  |____|
|__| W I R E L E S S   F R E E D O M
KAMIKAZE (bleeding edge, r23709) ------------------
* 10 oz Vodka       Shake well with ice and strain
* 10 oz Triple sec  mixture into 10 shot glasses.
* 10 oz lime juice  Salute!
---------------------------------------------------
root@rb133c:/#

 

Configuración rapida del DHCP para arrancar la imagen netboot

Si estas interesado en hacer esto, quiere decir que estas a una altura de compresión alto en estos temas, asi que no me voy a detener a explicar paso a paso como instalar un servidor DHCP y TFTP.

En mi caso he utilizado el propio DHCP y TFTP de un Mikrotik RB750G.

En Windows tienes una aplicación llamada Tftpd32 by Ph. Jounin que ya tiene servidor TFTP y DHCP incluido todo en uno. Configurandolo correctamente debería valerte.

En Linux, supondre que utilizas un servidor DHCP y TFTP estándar. Googleando hay mucha información de como configurar un servidor TFTP, es mas, puede que con instalarlo ya este funcionando, todo depende de la distro que poseas y demas.

En DHCP, los parámetros básicos serian los siguientes:

default-lease-time 21600;
max-lease-time 2100;
host rb133 {
  hardware ethernet 1A:2B:3C:4D:5E:6F;
  filename "/openwrt-adm5120-2.6-vmlinux.elf";  // Archivo de imagen netboot
  fixed-address 172.16.0.10;
  }
subnet 172.16.0.0 netmask 255.255.255.0 {
  option subnet-mask 255.255.255.0;
  next-server 172.16.0.2;  // Servidor TFTP donde ubiques el archivo de imagen netboot
  option broadcast-address 172.16.0.255;
  option routers 172.16.0.1;
  }

 

Share
Written by Javier Rodriguez in: Mikrotik,Programacion,Redes | Etiquetas: , , , ,
Mar
31
2008
0

Script para optimizar tablas de MySQL


A veces es necesario optimizar las tablas de MySQL para ahorrar un poco de espacio en disco y para que, generalmente, las consultas sean respondidas con mas rapided. Para ello podemos utilizar este script para que realice toda la tarea sin necesidad de utilizar aplicaciones como PhpMyAdmin.


for i in `mysql -B -e "show databases"|grep -v Database`; do
for j in `mysql $i -B -e "show tables;"|grep -v Tables_`; do
mysql $i -e "optimize table $j";
done;
done;

Share
Written by Javier Rodriguez in: BBDD,Programacion | Etiquetas: ,
Dic
27
2006
0

PHP Orientado a objetos


La mayoría de los lenguajes de programación modernos son orientados a objetos (abreviado OO) o en su defecto se aproximan mucho a éstos permitiendo algunas de sus características como es el caso de PHP.

La programación OO principalmente hace uso de clases, objetos, relaciones, instancias, propiedades y métodos.

Objetos y clases
Cuando hablamos de software OO los objetos casi siempre son elementos físicos, como puede ser un cliente, proveedor, etc. o elementos conceptuales que existen en el entorno software, por ejemplo un objeto encargado del mantenimiento de archivos. El objetivo es representar a éstos elementos de la vida real y a los conceptuales como unidades de software.

La programación OO esta pensada para construir objetos que contienen atributos y operaciones de manera que cubran nuestras necesidades. Los atributos son variables que contienen información del estado de un objeto. Y las operaciones también conocidas como métodos, funciones y acciones realizan modificaciones del propio objeto o realizan alguna acción externa a éste.

Una de las principales ventajas de la programación OO es el concepto de encapsulación, conocido también como protección de datos, mediante el cual solo se pueden modificar los datos de un objeto accediendo a través de sus métodos u operaciones (interfaz del objeto). Nunca se pueden modificar directamente desde la aplicación principal.

La funcionalidad de un objeto esta sujeta a los datos que este maneja, una ventaja de usar objetos es que podemos modificar la funcionalidad de éste, añadir mejoras o corregir errores sin necesidad de cambiar su interfaz. Ya que en caso contrario un proyecto estaría sujeto a un mayor número de fallos y los cambios serían más costosos.

En algunas áreas de la programación de aplicaciones Web el uso de la programación OO está desestimada, usándose una metodología estructurada basada en funciones, esto es debido a que determinados proyectos no son lo suficientemente extensos como para aplicarles una metodología OO.

En la programación OO los objetos son únicos y son instancias a una clase determinada. En principio se define la clase con los atributos y métodos correspondientes y luego se crea el objeto que esta basado en una determinada clase (esto se conoce como instancia). Se puede comparar a un objeto con una variable y la clase sería un tipo de dato definido por nosotros.

Cómo crear clases, atributos y operaciones
Hasta ahora hemos hablado de las clases de una forma conceptual, a continuación veremos como se crean, para crear una clase en PHP usaremos la palabra reservada class.
La estructura mínima de una clase es la siguiente:

class NombreClase {

   }

Para que una clase sea útil, necesita atributos y operaciones. Podemos crear atributos como si de variables se trataran, con la palabra reservada var

class NombreClase {
   var $atributo1;
   var $atributo2;
   }

Podemos crear métodos declarando funciones dentro de la definición de la clase, el siguiente código crea una clase llamada NombreClase con dos operaciones que no hacen nada. A metodo1 no le pasamos ningún parámetro y a metodo2 le pasamos dos parámetros.

class NombreClase {
   function metodo1() {
      }
   function metodo2($param1, $param2) {
      }
   }

Qué es el constructor de una clase
Las clases soportan un tipo de función especial que se conoce como constructor. El constructor es llamado cuando se crea el objeto. Normalmente utiliza para inicializar tareas como: asignación de valores a determinados atributos, crear nuevos objetos necesarios para el correcto funcionamiento de el objeto, etc.

El constructor se declara de la misma forma que los métodos, lo único que debemos tener en cuenta es que debe tener el mismo nombre que la clase. A pesar de que nosotros podemos llamar a el constructor, su principal propósito es ser llamado automáticamente cuando un objeto es creado. A continuación veremos como se declara el constructor de una clase:

class NombreClase {
   function NombreClase($param) {
      echo «Constructor llamado con el parámetro $param»;
      }
   }

Cómo usar objetos, instanciar una clase
Después de haber declarado una clase, ya podemos usarla creando un objeto que es una instancia a esa clase como ya se ha mencionado anteriormente. Es muy importante que esto quede claro, los objetos son instancias a una clase, por lo tanto cada objeto es único.

En php creamos un objeto usando la palabra reservada new. También debemos indicar a que clase va a instanciar el objeto que creemos y pasarle los parámetros (si los requiere) al constructor, en el siguiente código vamos a ver un ejemplo de esto, para ello tomamos como referencia la clase anterior NombreClase:

$a = new NombreClase(«Primero»);
$b = new NombreClase(«Segundo»);
$c = new NombreClase();

Como resultado de este código vemos que el constructor es llamado cada vez que se crea el objeto, y vemos que los objetos son únicos aunque sean instancias de la misma clase.

Cómo usar los atributos de una clase
Una clase, tiene un puntero especial al que podemos referenciar como $this. Si nuestra clase tiene un atributo llamado $atributo, podemos hacer referencia a este desde nuestra clase (métodos) de la siguiente forma $this->atributo, a continuación podemos ver el código de ejemplo del acceso a un atributo de clase desde un método de la propia clase.

class NombreClase {
   var $atributo;
   function metodo($param) {
      $this->atributo = $param;
      echo $this->atributo;     
      }
   }

Algunos lenguajes permiten limitar el acceso desde fuera a los atributos de una clase declarándolos como privados o protegidos («private», «protected»). PHP no soporta esta característica y todos atributos y métodos pueden ser vistos desde fuera de la clase, lo que quiere decir que siempre son públicos.

Podemos realizar la misma acción que anteriormente desde fuera de la clase, usando esta sintaxis.

NombreClase {
   var $atributo;
   }

$a = new NombreClase();
$a->atributo = «valor»;
echo $a->atributo;

Las sentencias anteriores están permitidas en PHP, pero no es una práctica recomendable acceder directamente a los atributos de una clase desde fuera de ésta. Como se ha comentado anteriormente una de las ventajas de la POO es que permite realizar encapsulación por esta razón aunque PHP no permita ocultar los atributos o métodos de una clase, nosotros deberíamos no acceder directamente a ellos, para diferenciarlos de los públicos es conveniente también poner «m_» (de miembro lo cual significa que solo serán usados dentro de la clase) delante de los nombres de métodos y atributos a los cuales no se quiera acceder directamente desde fuera de la clase.

Para los atributos que queramos acceder directamente desde fuera de la clase, deberíamos escribir funciones de acceso, tanto para establecer como para coger valores. Deberíamos tener un código como el siguiente:

class NombreClase {
   var $atributo;
  
   function get_atributo() { //devuelve el valor de atributo
      return $this->atributo;
      }  
   function set_atributo($valor_nuevo) { //pone el valor de atributo
      $this->atributo = $valor_nuevo;
      }
   }

La finalidad de hacer esto, es clarificar el código y tener una sección de código encargada de acceder a los atributos para mantener la encapsulación, y que no sean accedidos directamente. Además si seguimos estas prácticas aumentará la calidad de nuestro software ya que podremos introducir comprobaciones de datos, como rangos, valores permitidos, etc. Veamos un ejemplo de validación de datos a la hora de asignar un valor a atributo mediante el método set_atributo:

function set_atributo($valor_nuevo) {
   if ($valor_nuevo > 100) {
      $this->atributo = $valor_nuevo;
      }
   }

En el código superior vemos que cuando queremos asignar a atributo valores inferiores a 100 no nos deja, y atributo seguirá manteniendo su valor.

Cómo usar los métodos de una clase
Los métodos de una clase se pueden llamar de la misma forma que se llaman a los atributos, supongamos que tenemos la siguiente clase:

class nombreClase {
   function metodoa() {
      return «Has llamado al método A»;
      }
   function metodob($parametro1) {
      return «Método B llamado con parámetro: «.$parametro1;
      }
   }

Creamos un objeto de la case nombreClase con el nombre $obj de la siguiente forma:

$obj = new nombreClase();

Los métodos de un objeto, son llamados de la misma forma que se llaman a funciones normales, pasándoles como es el caso de metodob el parámetro que necesiten. Como los métodos son funciones que pertenecen a un objeto, deberemos indicar en la llamada el objeto que los incluye, la forma de llamar a un método es idéntica a como llamamos a los atributos de un objeto.

$obj->metodoa();
$obj->metodob(«parámetro que pasamos»);

Si nuestras operaciones, devuelven algún valor, lo capturamos asignándoselo a una variable, podemos ver el siguiente ejemplo

$txt_retorno = $obj->metodob(«Hola»);

$txt_retorno contendrá el texto: «Metodo B llamado con parámetro: Hola»

Qué es la Herencia y como implementarla
Como su nombre indica el concepto de herencia se aplica cuando creamos una clase, que va a heredar los métodos y atributos de una ya definida, entonces la clase que hemos creado es una subclase. Para que una clase sea subclase de otra ya creada deberemos usar la palabra reservada extends en el siguiente código podremos ver como creamos una clase llamada SubClaseA que heredará los métodos y atributos de una clase definida con anterioridad llamada ClaseA.

class SubClaseA extends ClaseA {
   var $atributo2;
   function operacion2() {
      }
   }

Tenemos la clase ClaseA que es definida de la siguiente forma:

Class ClaseA {
   var $atributo1;
   function operacion1(){
      }
   }

Si creamos un objeto de la clase SubClaseA este heredará todos los métodos de la clase ClaseA, por lo tanto el siguiente código es válido:

$x = new SubClaseA();
$x->operacion1();
$x->atributo1 = 100;
$x->operacion2();
$x->atributo2 = 200;

Como podemos observar aunque declaremos un objeto de la clase SubClaseA, al ser una clase extendida de ClaseA podemos hacer uso de todos los métodos y atributos definidos en ClaseA como si estuvieran contenidos en SubClaseA.

Debemos tener en cuenta que la herencia solo trabaja en una dirección, la subclase o clase hija hereda las características de su clase padre o superclase, pero la clase padre no posee las características de la hija. Para el caso anterior ClaseA no tendría atributo2 ni metodo2();

Como sobrescribir métodos y atributos
Como hemos visto anteriormente, una subclase declara atributos nuevos y operaciones sobre una superclase. Es posible y en muchos casos útil sobrescribir las mismas operaciones o atributos declarados en la superclase. Esto se hace para dar a un atributo un valor diferente en la subclase que el que tiene en la superclase o en el caso de las operaciones para cambiar la funcionalidad de estas. Veamos un ejemplo, por ejemplo si tenemos la clase A:

class A {
   var $atributo = ‘valor inicial’
   function operación() {
      echo ‘Clase A:’;
      echo ‘El valor de \$atributo es $this->atributo’;
      }
   }

Queremos crear una subclase B y alterar el valor de atributo y la funcionalidad de operación de la clase A, entonces escribimos:

Class B extends A {
   var  $atributo = ‘valor cambiado’;
   function operación() {
      echo ‘Clase B:’;
      echo ‘El valor de \$atributo ahora es $this->atributo’;
      }
   }

Como podemos observar hemos definido una variable y una operación en B con el mismo nombre que tenían en A.

Como se ha comentado anteriormente aunque declaremos B no afecta a la definición de A, y si creamos un objeto de la superclase A esté mantendrá sus valores originales. Solo sobrescribiremos los valores y funcionalidad de A cuando creemos un objeto de la clase B.
A diferencia de otros lenguajes OO, PHP no nos permitirá sobrescribir una función o atributo y poder llamar a los valores de la clase padre.

La herencia puede tener muchas capas de profundidad, por ejemplo podemos tener una clase C que es subclase de B y está última ser subclase de A, la subclase C heredará y sobrescribirá aquellos atributos y métodos de sus clases padres, en este caso A y B.

¿Soporta PHP la herencia múltiple?
Algunos lenguajes OO soportan herencia múltiple, esto significa que una subclase puede heredar de varias clases padres. PHP no permite esto y una subclase solo puede heredar de una clase padre, sin embargo en PHP no hay ningún tipo de restricción en cuanto a el número de subclases que pueden heredar de una misma clase padre o superclase.

Qué es el polimorfismo y como implementarlo
Cualquier lenguaje de programación orientado a objetos debe soportar el polimorfismo, esto significa que clases diferentes tendrán un comportamiento distinto para la misma operación. Esto lo veremos más claro con el siguiente ejemplo.

Supongamos que tenemos dos clases distintas coche y ciclomotor. Ambas tienen sus propios métodos de movimiento, éstos tienen diferentes comportamientos, pero su nombre es el mismo

class coche {
   function avanza() {
      }  
   function para() {
      }
   function girar_derecha() {
      }
   }

class ciclomotor {
   function avanza() {
      }  
   function para() {
      }
   function girar_derecha() {
      }
   }

Como podemos observar, ambas clases tienen los mismos métodos, supongamos ahora que tenemos otra clase que controla el movimiento de todos los vehículos, es aquí donde entra en juego el polimorfismo, que dependiendo del objeto que tratemos actuará de una forma u otra el método al que llamamos.

class movimiento {
   function mover_adelante($obj) {
      $obj->avanza();
      }
   }

Supongamos que queremos mover cualquier vehículo hacia adelante entonces haríamos:

$obj_coche = new coche();
$obj_ciclomotor = new ciclomotor();

$obj_movimiento = new movimiento();

// con esta sentencia el coche avanzaria hacia adelante.
$obj_movimiento->mover_adelante($obj_coche);

// con esta sentencia el ciclomotor avanzaría hacia adelante.
$obj_movimiento->mover_adelante($obj_ciclomotor);

Como podemos ver el mismo método del objeto movimiento actúa de dos formas diferentes dependiendo del objeto que le pasamos como parámetro.

Share
Written by Javier Rodriguez in: Programacion |

Theme: TheBuckmaker.com Blog Themes | Hostpapa customer, Berlin