Curso gratis Yii2: Día 0, primeros pasos

Ahora que ya tenemos instalado y correctamente configurado nuestro entorno de desarrollo local con Dockers, vamos a comenzar a escribir una pequeña aplicación Yii2.

Para ello primero vamos a familiarizarnos con el Framework.

Creación de “hello world” en Yii2

Todas las peticiones que se reciben en Yii son recibidas por web/index.php.

En la carpeta controllers vemos los distintos controladores. Partiendo del ejemplo del post anterior, vemos que existe el fichero controllers/SiteController.php. Aqui añadiremos nuestra función. Los nombres de las funciones deben comenzar con action. Por ejemplo vamos a definir una ruta nueva en nuestra aplicación, que sea /di-algo y muestre un mensaje.

Nuestro primer controlador

Para ello editamos controllers/SiteController.php y añadimos nuestra nueva ruta:

    /**
     *
     * @return string
     */
    public function actionDiAlgo($message = 'Hola')
    {
        return $this->render('diAlgo', ['message' => $message]);
    }

Le hemos dicho que renderice usando la plantilla diAlgo y que le pase el mensaje indicado en $message (o, si no le digo nada, por defecto pondrá “Hola”).

Nuestra primera plantilla

Vamos a crear la plantilla a la que estamos llamando. Para ello creamos un nuevo fichero diAlgo.php en views/site/diAlgo.php con este contenido:

<?php
use yii\helpers\Html;
?>

<?= Html::encode($message) ?>

Para evitar un posible ataque XSS no nos limitamos a mostrar el valor de $message, sino que lo pasamos por el helper Html::encode primero (que está definido en yii\helpers\Html).

Ahora podemos acceder a http://unizaryii.docker.localhost:8000/index.php?r=site%2Fdi-algo&message=Hola+mundo y veremos nuestro Hello World en acción.

Hola Mundo en Yii2

Añadiendo un nuevo enlace en la barra de menús

Vamos a añadir un nuevo enlace en nuestra barra de menú superior.

El layout del menú se controla en views/layout/main.php. Modificamos el código para añadir al array el nuevo link, que quedará así…

...
echo Nav::widget([
        'options' => ['class' => 'navbar-nav navbar-right'],
        'items' => [
            ['label' => 'Home', 'url' => ['/site/index']],
            ['label' => 'About', 'url' => ['/site/about']],
            ['label' => 'Contact', 'url' => ['/site/contact']],
            ['label' => 'Hola Mundo', 'url' => ['/site/di-algo']],
            Yii::$app->user->isGuest ? (
                ['label' => 'Login', 'url' => ['/site/login']]
            ) : (
                '

Y ya se muestra y funciona correctamente.

añadir item de menú yii2

Haciendo URLs pretty en Yii2

En la ruta del ejemplo que hemos construido (http://unizaryii.docker.localhost:8000/index.php?r=site%2Fdi-algo&message=Hola+mundo o, lo que es lo mismo, http://unizaryii.docker.localhost:8000/index.php?r=site/di-algo&message=Hola+mundo) vemos que la URL tiene el sufijo /index.php?r=site/di-algo

Esto se corresponde con el fichero que atiende las peticiones (index.php) seguido del nombre del controlador (site) y después la ruta definida en ese controlador (di-algo) y sus parámetros (&message=Hola+Mundo).

Veamos cómo hacerla más bonita. Para ello tu servidor Apache deberá tener habilitado mod_rewrite. Esto ya viene así por defecto en el entorno que creamos con Docker.

Creamos un archivo .htaccess en el webroot (osea, dentro de la carpeta web) con el siguiente contenido:

RewriteEngine on
# If a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Otherwise forward it to index.php
RewriteRule . index.php

Y además modificamos config/web.php. La parte del urlManager quedará así:

'urlManager' => [
            'enablePrettyUrl' => true, // usar url's bonitas
            'showScriptName' => false, // ocultar index.php
            'rules' => [
                '<action:(.*)>' => 'site/',,
            ],
        ],

Y ahora ya podemos visitar la URL http://unizaryii.docker.localhost:8000/di-algo que es mucho más bonita:

pretty urls en yii2

Docker para desarrollo Yii2 en MacOS

En el post anterior vimos cómo crear un entorno de desarrollo para Drupal8 usando Docker.

Pero, ¿y si quiero usar otro framework de PHP, por ejemplo Yii2, en mi OSX? Es muy sencillo.

Instalación del DOCKER stack (docker4php)

docker4php miguelm$ cd Sites/testyii2
docker4php miguelm$ git clone https://github.com/wodby/docker4php
docker4php miguelm$ cd docker4php

Editar .env y dejarlo como sigue:

### Documentation available at https://docs.wodby.com/stacks/php/local
### Changelog can be found at https://github.com/wodby/docker4php/releases
### Images tags format explained at https://github.com/wodby/docker4php#images-tags

### PROJECT SETTINGS

PROJECT_NAME=unizaryii
PROJECT_BASE_URL=unizaryii.docker.localhost

DB_NAME=php
DB_USER=php
DB_PASSWORD=php
DB_ROOT_PASSWORD=password
DB_HOST=mariadb
DB_DRIVER=mysql

### --- PHP ----

#PHP_TAG=7.2-dev-4.8.2
#PHP_TAG=7.1-dev-4.8.2
#PHP_TAG=5.6-dev-4.8.2
PHP_TAG=7.2-dev-macos-4.8.2
#PHP_TAG=7.1-dev-macos-4.8.2
#PHP_TAG=5.6-dev-macos-4.8.2

### --- NGINX ----

NGINX_TAG=1.15-5.0.17
#NGINX_TAG=1.14-5.0.17

### --- NODE ---

NODE_TAG=10-0.9.0
#NODE_TAG=8-0.9.0
#NODE_TAG=6-0.9.0

### --- MARIADB ----

MARIADB_TAG=10.1-3.3.11
#MARIADB_TAG=10.2-3.3.11
#MARIADB_TAG=10.3-3.3.11

### --- POSTGRESQL ----

POSTGRES_TAG=11-1.5.0
#POSTGRES_TAG=10-1.5.0
#POSTGRES_TAG=9.6-1.5.0
#POSTGRES_TAG=9.5-1.5.0
#POSTGRES_TAG=9.4-1.5.0
#POSTGRES_TAG=9.3-1.5.0

### --- REDIS ---

REDIS_TAG=4-3.0.2
#REDIS_TAG=5-3.0.2

### --- ELASTICSEARCH ---

ELASTICSEARCH_TAG=6.3-3.0.2
#ELASTICSEARCH_TAG=6.2-3.0.2
#ELASTICSEARCH_TAG=6.1-3.0.2
#ELASTICSEARCH_TAG=6.0-3.0.2
#ELASTICSEARCH_TAG=5.6-3.0.2
#ELASTICSEARCH_TAG=5.5-3.0.2
#ELASTICSEARCH_TAG=5.4-3.0.2

### --- KIBANA ---

KIBANA_TAG=6.3-3.0.2
#KIBANA_TAG=6.2-3.0.2
#KIBANA_TAG=6.1-3.0.2
#KIBANA_TAG=6.0-3.0.2
#KIBANA_TAG=5.6-3.0.2
#KIBANA_TAG=5.5-3.0.2
#KIBANA_TAG=5.4-3.0.2

### --- SOLR ---

SOLR_TAG=7.4-3.0.6
#SOLR_TAG=7.3-3.0.6
#SOLR_TAG=7.2-3.0.6
#SOLR_TAG=7.1-3.0.6
#SOLR_TAG=6.6-3.0.6
#SOLR_TAG=5.5-3.0.6

### OTHERS

ADMINER_TAG=4.6-3.2.0
APACHE_TAG=2.4-4.0.2
ATHENAPDF_TAG=2.10.0
MEMCACHED_TAG=1-2.2.1
RSYSLOG_TAG=latest
VARNISH_TAG=4.1-3.0.10
WEBGRIND_TAG=1.5-1.6.2
OPENSMTPD_TAG=6.0-1.4.0
XHPROF_TAG=1.0.2

Compilamos y levantamos…

docker4php miguelm$ docker-compose up -d

En el fichero docker-compose.yml la variable NGINX_SERVER_ROOT tiene el valor /var/www/html/public
Así que creamos el directorio public y un fichero index.php para probar si todo ha ido bien…

docker4php miguelm$ mkdir public
docker4php miguelm$ echo "" > public/index.php

Lo siguiente será editar (como root) el fichero /etc/hosts de la máquina anfitrión y añadir algunas entradas que nos serán útiles:

127.0.0.1 unizaryii.docker.localhost
127.0.0.1 pma.unizaryii.docker.localhost

Y ya podemos ir a nuestro navegador en la máquina anfitrión: http://unizaryii.docker.localhost:8000/ y comprobar que todo funciona.

Instalación de Yii2 y creación de proyecto

Ahora que ya hemos comprobado que el setup funciona, vamos a instalar Yii2.

docker4php miguelm$ git clone https://github.com/yiisoft/yii2 _host-volumes/yii2
docker4php miguelm$ mv _host-volumes/yii2 .
docker4php miguelm$ rm -Rf _host-volumes

Y vamos a crear nuestro primer proyecto Yii2:

# eliminamos el directorio "public" completo
docker4php miguelm$ rm -Rf public
# creamos un nuevo proyecto en la carpeta "demo" 
docker4php miguelm$ composer create-project yiisoft/yii2-app-basic demo

Lo siguiente será editar el fichero docker-compose.yml para indicar el nuevo valor de NGINX_SERVER_ROOT, que deberá ser:

NGINX_SERVER_ROOT: /var/www/html/demo/web

Paramos y arrancamos los dockers con la nueva configuración:

docker4php miguelm$ docker-compose stop
docker4php miguelm$ docker-compose up -d

Ya tenemos nuestro proyecto Yii2 listo…

¿Y si en lugar de NGINX quiero utilizar Apache como servidor web?

Muy sencillo. Editamos el archivo docker-compose.yml y comentamos la sección de NGINX y descomentamos la sección de Apache. El fichero docker-compose.yml quedaría así:

version: "3"

services:
  mariadb:
    image: wodby/mariadb:$MARIADB_TAG
    container_name: "${PROJECT_NAME}_mariadb"
    stop_grace_period: 30s
    environment:
      MYSQL_ROOT_PASSWORD: $DB_ROOT_PASSWORD
      MYSQL_DATABASE: $DB_NAME
      MYSQL_USER: $DB_USER
      MYSQL_PASSWORD: $DB_PASSWORD
#    volumes:
#      - ./mariadb-init:/docker-entrypoint-initdb.d # Place init .sql file(s) here.
#      - /path/to/mariadb/data/on/host:/var/lib/mysql # I want to manage volumes manually.

#  postgres:
#    image: wodby/postgres:$POSTGRES_TAG
#    container_name: "${PROJECT_NAME}_postgres"
#    stop_grace_period: 30s
#    environment:
#      POSTGRES_PASSWORD: $DB_PASSWORD
#      POSTGRES_DB: $DB_NAME
#      POSTGRES_USER: $DB_USER
#    volumes:
#      - ./postgres-init:/docker-entrypoint-initdb.d # Place init file(s) here.
#      - /path/to/postgres/data/on/host:/var/lib/postgresql/data # I want to manage volumes manually.

  php:
    image: wodby/php:$PHP_TAG
    container_name: "${PROJECT_NAME}_php"
    environment:
      PHP_SENDMAIL_PATH: /usr/sbin/sendmail -t -i -S mailhog:1025
      DB_HOST: $DB_HOST
      DB_USER: $DB_USER
      DB_PASSWORD: $DB_PASSWORD
      DB_NAME: $DB_NAME
## Read instructions at https://wodby.com/stacks/php/docs/local/xdebug/
#      PHP_XDEBUG: 1
#      PHP_XDEBUG_DEFAULT_ENABLE: 1
#      PHP_XDEBUG_REMOTE_CONNECT_BACK: 0
#      PHP_IDE_CONFIG: serverName=my-ide
#      PHP_XDEBUG_REMOTE_HOST: 172.17.0.1 # Linux
#      PHP_XDEBUG_REMOTE_HOST: 10.254.254.254 # macOS
#      PHP_XDEBUG_REMOTE_HOST: 10.0.75.1 # Windows
    volumes:
      - ./:/var/www/html
## For macOS users (https://wodby.com/stacks/php/docs/local/docker-for-mac/)
#      - ./:/var/www/html:cached # User-guided caching
#      - docker-sync:/var/www/html # Docker-sync
## For XHProf and Xdebug profiler traces
#      - files:/mnt/files

#  nginx:
#    image: wodby/nginx:$NGINX_TAG
#    container_name: "${PROJECT_NAME}_nginx"
#    depends_on:
#      - php
#    environment:
#      NGINX_STATIC_OPEN_FILE_CACHE: "off"
#      NGINX_ERROR_LOG_LEVEL: debug
#      NGINX_BACKEND_HOST: php
#      NGINX_VHOST_PRESET: php
#      NGINX_SERVER_ROOT: /var/www/html/demo/web
#    volumes:
#      - ./:/var/www/html
# Options for macOS users (https://wodby.com/stacks/php/docs/local/docker-for-mac/)
#      - ./:/var/www/html:cached # User-guided caching
#      - docker-sync:/var/www/html # Docker-sync
#    labels:
#      - 'traefik.backend=${PROJECT_NAME}_nginx'
#      - 'traefik.port=80'
#      - 'traefik.frontend.rule=Host:${PROJECT_BASE_URL}'

  apache:
    image: wodby/apache:$APACHE_TAG
    container_name: "${PROJECT_NAME}_apache"
    depends_on:
      - php
    environment:
      APACHE_LOG_LEVEL: debug
      APACHE_BACKEND_HOST: php
      APACHE_VHOST_PRESET: php
      APACHE_DOCUMENT_ROOT: /var/www/html/demo/web
    volumes:
      - ./:/var/www/html
## For macOS users (https://wodby.com/stacks/php/docs/local/docker-for-mac/)
##      - ./:/var/www/html:cached # User-guided caching
##      - docker-sync:/var/www/html # Docker-sync
    labels:
      - 'traefik.backend=${PROJECT_NAME}_apache'
      - 'traefik.port=80'
      - 'traefik.frontend.rule=Host:${PROJECT_BASE_URL}'

  mailhog:
    image: mailhog/mailhog
    container_name: "${PROJECT_NAME}_mailhog"
    labels:
      - 'traefik.backend=${PROJECT_NAME}_mailhog'
      - 'traefik.port=8025'
      - 'traefik.frontend.rule=Host:mailhog.${PROJECT_BASE_URL}'

#  varnish:
#    image: wodby/varnish:$VARNISH_TAG
#    container_name: "${PROJECT_NAME}_varnish"
#    depends_on:
#      - nginx
#    environment:
#      VARNISH_SECRET: secret
#      VARNISH_BACKEND_HOST: nginx
#      VARNISH_BACKEND_PORT: 80
#      VARNISH_PURGE_EXTERNAL_REQUEST_HEADER: X-Real-IP
#    labels:
#      - 'traefik.backend=${PROJECT_NAME}_varnish'
#      - 'traefik.port=6081'
#      - 'traefik.frontend.rule=Host:varnish.${PROJECT_BASE_URL}'

#  redis:
#    container_name: "${PROJECT_NAME}_redis"
#    image: wodby/redis:$REDIS_TAG

#  adminer:
#    container_name: "${PROJECT_NAME}_adminer"
#    image: wodby/adminer:$ADMINER_TAG
#    environment:
## For PostgreSQL:
##      ADMINER_DEFAULT_DB_DRIVER: pgsql
#      ADMINER_DEFAULT_DB_HOST: $DB_HOST
#      ADMINER_DEFAULT_DB_NAME: $DB_NAME
#    labels:
#      - 'traefik.backend=${PROJECT_NAME}_adminer'
#      - 'traefik.port=9000'
#      - 'traefik.frontend.rule=Host:adminer.${PROJECT_BASE_URL}'

#  pma:
#    image: phpmyadmin/phpmyadmin
#    container_name: "${PROJECT_NAME}_pma"
#    environment:
#      PMA_HOST: $DB_HOST
#      PMA_USER: $DB_USER
#      PMA_PASSWORD: $DB_PASSWORD
#      PHP_UPLOAD_MAX_FILESIZE: 1G
#      PHP_MAX_INPUT_VARS: 1G
#    labels:
#      - 'traefik.backend=${PROJECT_NAME}_pma'
#      - 'traefik.port=80'
#      - 'traefik.frontend.rule=Host:pma.${PROJECT_BASE_URL}'

#  solr:
#    image: wodby/solr:$SOLR_TAG
#    container_name: "${PROJECT_NAME}_solr"
#    environment:
#      SOLR_HEAP: 1024m
#    labels:
#      - 'traefik.backend=${PROJECT_NAME}_solr'
#      - 'traefik.port=8983'
#      - 'traefik.frontend.rule=Host:solr.${PROJECT_BASE_URL}'

#  elasticsearch:
#    image: wodby/elasticsearch:$ELASTICSEARCH_TAG
#    environment:
#      ES_JAVA_OPTS: "-Xms500m -Xmx500m"
#    ulimits:
#      memlock:
#        soft: -1
#        hard: -1

#  kibana:
#    image: wodby/kibana:$KIBANA_TAG
#    depends_on:
#      - elasticsearch
#    labels:
#      - 'traefik.backend=${PROJECT_NAME}_kibana'
#      - 'traefik.port=5601'
#      - 'traefik.frontend.rule=Host:kibana.php.docker.localhost'

#  memcached:
#    container_name: "${PROJECT_NAME}_memcached"
#    image: wodby/memcached:$MEMCACHED_TAG

#  rsyslog:
#    container_name: "${PROJECT_NAME}_rsyslog"
#    image: wodby/rsyslog:$RSYSLOG_TAG

#  athenapdf:
#    image: arachnysdocker/athenapdf-service:$ATHENAPDF_TAG
#    container_name: "${PROJECT_NAME}_athenapdf"
#    environment:
#      WEAVER_AUTH_KEY: weaver-auth-key
#      WEAVER_ATHENA_CMD: "athenapdf -S"
#      WEAVER_MAX_WORKERS: 10
#      WEAVER_MAX_CONVERSION_QUEUE: 50
#      WEAVER_WORKER_TIMEOUT: 90
#      WEAVER_CONVERSION_FALLBACK: "false"

#  node:
#    image: wodby/node:$NODE_TAG
#    container_name: "${PROJECT_NAME}_node"
#    working_dir: /app
#    labels:
#      - 'traefik.backend=${PROJECT_NAME}_node'
#      - 'traefik.port=3000'
#      - 'traefik.frontend.rule=Host:front.${PROJECT_BASE_URL}'
#    expose:
#      - "3000"
#    volumes:
#      - ./path/to/your/single-page-app:/app
#    command: sh -c 'npm install && npm run start'

#  blackfire:
#    image: blackfire/blackfire
#    environment:
#      BLACKFIRE_SERVER_ID: XXXXX
#      BLACKFIRE_SERVER_TOKEN: YYYYY

#  webgrind:
#    image: wodby/webgrind:$WEBGRIND_TAG
#    environment:
#      WEBGRIND_PROFILER_DIR: /mnt/files/xdebug/profiler
#    labels:
#      - 'traefik.backend=${PROJECT_NAME}_webgrind'
#      - 'traefik.port=8080'
#      - 'traefik.frontend.rule=Host:webgrind.php.docker.localhost'
#    volumes:
#      - files:/mnt/files

#  opensmtpd:
#    container_name: "${PROJECT_NAME}_opensmtpd"
#    image: wodby/opensmtpd:$OPENSMTPD_TAG

#  xhprof:
#    image: wodby/xhprof:$XHPROF_TAG
#    restart: always
#    volumes:
#      - files:/mnt/files
#    labels:
#      - 'traefik.backend=${PROJECT_NAME}_xhprof'
#      - 'traefik.port=8080'
#      - 'traefik.frontend.rule=Host:xhprof.${PROJECT_BASE_URL}'

  portainer:
    image: portainer/portainer
    container_name: "${PROJECT_NAME}_portainer"
    command: --no-auth -H unix:///var/run/docker.sock
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    labels:
      - 'traefik.backend=${PROJECT_NAME}_portainer'
      - 'traefik.port=9000'
      - 'traefik.frontend.rule=Host:portainer.${PROJECT_BASE_URL}'

  traefik:
    image: traefik
    container_name: "${PROJECT_NAME}_traefik"
    command: -c /dev/null --web --docker --logLevel=INFO
    ports:
      - '8000:80'
#      - '8080:8080' # Dashboard
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

#volumes:
## Docker-sync for macOS users
#  docker-sync:
#    external: true
## For Xdebug profiler
#  files:

Después simplemente:

docker4php miguelm$ docker-compose up -d --remove-orphans

How to add a “out of stock” badge in Woocommerce using AVADA (SOLVED)

You can easily add an “out of stock” badge in Woocommerce by just using CSS:

.outofstock .images a, .products .outofstock a {position:relative;display:block;}
.products .outofstock .fusion-image-wrapper a:before {
    height: 100%;
    position: absolute;
    width: 100%;
    display: inherit !important;
    content: "Agotado \A Disponible por encargo"; // customize this message
    white-space: pre;
    font-size: 0.8em;
    letter-spacing:2px;
    font-weight:bold;
    background: rgba(0, 0, 0, 0.5);
    text-transform: uppercase;
    position: absolute;
    width: 100%;
    text-align: center;
    display: block;
    opacity: 0.7;
    line-height: normal;
    top: 0%;
    padding-top:40%;
    color:white;
}

This is how it looks like in my WordPress install (using Avada theme):

WOOCOMMERCE out of stock avada theme

Actualizar navegador Porsche PCM2.1 (Boxster, Cayenne, Cayman): La guía definitiva

Os dejo el manual para actualizar el navegador PCM2.1 de Porsche (Boxster / Cayenne / Cayman) a los últimos mapas disponibles a día de hoy (versión 2015). Probado en PCM2.1 equipado en Porsche BoxsterS MY05 con amplificador BOSE.

DISCLAIMER: No me hago responsable de cualquier daño ocasionado en vuestros PCM.

El software completo de actualización de compone de 3 CD’s y un DVD.

CD1: 000.043.205.46.002 – update LevelA to LevelB. http://dl.dropbox.com/u/14202177/Update-PCM%202.1-disco%201.nrg

CD2: 000.043.205.46.003 – updates Motorola Phone Module, if installed. http://dl.dropbox.com/u/14202177/Update-PCM%202.1-disco%202.nrg

CD3: 000.044.901.40 – Update for PCM21_NavDVD – Updates Navigation after Level B is installed or if Level B or Level C/C1 was previously installed) http://uploaded.net/file/nl4gapqx

DVD Mapas. En mi caso PORSCHE PCM 2.1 DVD EUROPE 2015 (mapas 2015)

http://ul.to/nu9hrsvw
http://ul.to/3yxpp8pl
http://ul.to/6awukige
http://ul.to/2xuzbgka
http://ul.to/144f68w1
http://ul.to/hpsmtt56

 

Actualizar navegador PCM2.1: PASO 0

Descargar todos los CD’s y grabarlos. Os recomiendo seguir el método indicado por el forero Grimosa (aqui: [url]http://soloporsche.com/showpost.php?p=1288917&postcount=1213[/url]). Es decir, grabarlos a mínima velocidad (1x) con ImgBurn, sobre CD-R de marca reconocida, tipo Verbatim.

Una vez tengamos todo grabado, nos vamos al coche, sacamos el CD del PCM 2.1 y también sacamos la SIM, si hubiera una insertada.

Después pasamos al PASO 1.

Actualizar navegador PCM2.1: PASO 1

Vamos a averiguar la versión de firmware de nuestro PCM2.1. Para ello, se enciende el PCM y se aprietan MAIN+NAVI simultáneamente.

En mi caso, los datos de inicio eran estos:

Aparato: Software de sist.
Teórico: 04113AD1 / 1104
Real: 04113AD1 / 1104
Introducidos: Sí
Encontrados: Sí

Aparato: PCM
Teórico:04202JD1 / 3004 
Real:04202JD1 / 3004
Introducidos: Sí
Encontrados: Sí

Aparato: Amplificador
Teórico: 00017500 / 3504
Real: 00017500 / 3504 
Introducidos: Sí
Encontrados: Sí

Aparato: Sistema navegac...
Teórico: /
Real: 00174156 / 2704
Introducidos:Sí
Encontrados:Sí

PCM2.1 firmware version mode level A

PCM2.1 bose amplifier firmware version mode level A

Si tenéis equipo BOSE, lo más importante es mirar la versión del firmware que tiene. Si tiene la versión 16400 lo más probable es que el equipo quede inservible al actualizar el navegador. Por tanto, NO ACTUALICES si tienes la 16400.

Otro dato importante es la versión del Aparato: PCM. Los valores posibles serán:

04035xxx --> indica Standard Version.
04202xxx --> indica Model Level A.
05024xxx --> indica Model Level B.
05395xxx --> indica Model Level C.

Si estás en la 04035xxx te recomiendo que NO HAGAS NADA, podrías dejar el BOSE inservible. La propia documentación de PORSCHE lo indica:
[quote]Vehicles equipped with Standard Version (04035xxx) first need to be updated to Model Level A (04202xxx) using update disc 000.043.205.46.004 which is not included in this kit. Refer to bulletin Group 9, #1/04, titled “PCM2.1 & BOSE Amplifier Spare Parts Requirements, Part ID 9110.
Read the information in bulletin #1/04 carefully. An update of the BOSE Amplifier (if equipped) may be necessary.[/quote]

Si estás en Model Level A, debes actualizar a Model Level B para poder usar el DVD de mapas de 2015. Ve al PASO 2.

Si estás en Model Level B, únicamente debes actualizar el firmware del navegador y los mapas. Ve al PASO 4.

Actualizar navegador PCM2.1: PASO 2

El propósito de este paso es actualizar del model level A al model level B. Para ello vamos a utilizar el CD1: 000.043.205.46.002.

Lo primero, ENCIENDE EL MOTOR. Si por un casual el PCM se apaga durante la actualización de firmware, el equipo puede quedar inservible. Asi pues, MANTEN ENCENDIDO EL MOTOR durante esta actualización. Haz todo el proceso en un sitio bien ventilado.

Enciende el PCM.

Inserta el CD1 en la ranura del PCM. Pondrá algo asi como “reconociendo CD de datos” y al poco, se iniciará automáticamente. Nos preguntará si queremos actualizar a Model Level B. Le decimos que Sí. Tarda un poco, pero al poco sale una barra de proceso. Ahora podemos tener dos casos, en función de si tienes instalado módulo de teléfono y la versión del mismo.

En el caso de vehículos sin módulo de teléfono o con el módulo de teléfono Motorola, la actualización te irá indicando 2 pasos (R51 y R02).

pcm2.1a update pcm2.1b

pcm2.1a update pcm2.1b

En el caso de vehículos con módulo de teléfono Harman/Becker, la actualización se hará en tres pasos (V5.03.4, R51 y R02).

Tarda un rato. No seas impaciente, no toques nada hasta que termine. Cuando termine el PCM se apagará y volverá a encenderse solo. Si no se encendiera solo, enciéndelo tú a mano y saca el CD.

Si tienes módulo de teléfono Motorola, pasa al PASO 3. Sino, pasa al PASO 4.

Actualizar navegador PCM2.1: PASO 3

El propósito de este paso es actualizar el firmware del módulo de teléfono Motorola.
Asegúrate de que no haya SIM en la ranura de SIM y de tener el motor encendido.

Inserta el CD2 (000.043.205.46.003). Te pondrá algo asi como “reconociendo CD de datos” y al poco te preguntará si quieres actualizar MicPegel Motorola.

update micpegel motorola porsche pcm2.1

Le dices que sí y esperas. Saldrá una barra de proceso. Te indicará que está actualizando a versión R36.

update micpegel motorola porsche pcm2.1

Al terminar aparecerá un mensaje indicando que el proceso ha concluido de forma exitosa.

update micpegel motorola porsche pcm2.1

Saca el CD del PCM y ve al PASO 4.

Actualizar navegador PCM2.1: PASO 4

Este paso debe acometerse cuando nuestro firmware está en Mode Level B, C o C1. Aprieta MAIN+NAVI y asegúrate de que la versión del PCM es 05024xxx (Model Level B) o 05395xxx (Mode Level C).

Saca el DVD de navegación anterior de su sitio. En mi Boxster está en el maletero delantero. En los Cayenne creo que está bajo el asiento del copiloto. Guarda ese DVD.

Inserta ahora en el DVD de navegación (NO en el PCM!) el CD3 (000.044.901.40). Apaga el PCM. Apaga el motor y déjalo apagado 2 minutos o más.

Enciende el motor y DÉJALO ENCENDIDO.

El navegador se encenderá automáticamente. Si no se encendiera, pulsa NAVI en el PCM.

Aparecerá un mensaje preguntándote si quieres actualizar el software de navegación. Le dices que sí.

update pcm2.1 navigation

Aparecerá una barra de proceso, que ira subiendo hasta llegar al 10%.

actualizar navegador pcm porsche boxster 987

Pasará del 10% al 0 y te pondrá: “error durante arranque navegación”.

actualizar navegador pcm porsche boxster 987

En ese momento, ve al cargador de DVD de navegación (maletero o asiento), saca el CD3 y mete el DVD con los mapas de 2015. Pondrá “Sistema navegación arrancando” y al poco, el proceso termina y ya tenemos los nuevos mapas.

actualizar navegador pcm porsche boxster 987

El firmware actualizado:
actualizar navegador pcm porsche boxster 987

Espero que os resulte útil.

Botón de flecha animada con CSS3

El otro día un amigo me pedía que metiera una flechita en movimiento en su web. Os dejo el ejemplo de cómo lo hice, por si os resulta útil. Para crear la flecha utilizo font-awesome 😉

1. En el MARCADO:

<span class="hero-btn-holder" style="">
   <a target="_blank" href="/#main-content" class="hero-btn hero-slider-button">
         <i style="color: #ffffff;" class="fa fa-angle-down fa-4x ut-service-box-icon"></i>
   </a>
</span>

2. En el CSS:

/* flecha abajo en movimiento */
/* buscamos el selector que sea la flecha (en este caso la selección está sacada de un theme de ejemplo) */
#ut-hero-captions > ul:nth-child(1) > li:nth-child(n) > div:nth-child(1) > div:nth-child(1) > div:nth-child(1) > div:nth-child(1) > span:nth-child(2) > a:nth-child(1){
	cursor: pointer;
	-webkit-animation: jumpInc 2s infinite;
       -moz-animation: jumpInc 2s infinite;
         -o-animation: jumpInc 2s infinite;
            animation: jumpInc 2s infinite;
}

@-webkit-keyframes jumpInc {
	0%   {
		margin-top: -122%;
		opacity: 0;
	}
	50%  {
		margin-top: 0%;
		opacity: 1;
	}
	100% {
		margin-top: 122%;
		opacity: 0;
	}
}

@-moz-keyframes jumpInc {
	0%   {
		margin-top: -122%;
		opacity: 0;
	}
	50%  {
		margin-top: 0%;
		opacity: 1;
	}
	100% {
		margin-top: 122%;
		opacity: 0;
	}
}
@-o-keyframes jumpInc {
	0%   {
		margin-top: -122%;
		opacity: 0;
	}
	50%  {
		margin-top: 0%;
		opacity: 1;
	}
	100% {
		margin-top: 122%;
		opacity: 0;
	}
}
@keyframes jumpInc {
	0%   {
		margin-top: -122%;
		opacity: 0;
	}
	50%  {
		margin-top: 0%;
		opacity: 1;
	}
	100% {
		margin-top: 122%;
		opacity: 0;
	}
}

/* /flecha abajo */

Oracle: guess the query of a view [SOLVED]

Some time ago, someone at my work created a new View in our Oracle database called AUTORESUZ (notice the capitals!) and I wanted to know how this view was defined, this is, the query that lies under it.

You can list all the views defined at your Oracle database by having a look at all_views table which stores the following information of each view:

SQL> DESC all_views;
 Name					   NULL?    TYPE
 ----------------------------------------- -------- ----------------------------
 OWNER					   NOT NULL VARCHAR2(30)
 VIEW_NAME				   NOT NULL VARCHAR2(30)
 TEXT_LENGTH					    NUMBER
 TEXT						    LONG
 TYPE_TEXT_LENGTH				    NUMBER
 TYPE_TEXT					    VARCHAR2(4000)
 OID_TEXT_LENGTH				    NUMBER
 OID_TEXT					    VARCHAR2(4000)
 VIEW_TYPE_OWNER				    VARCHAR2(30)
 VIEW_TYPE					    VARCHAR2(30)
 SUPERVIEW_NAME 				    VARCHAR2(30)

The query information is stored in “text” row. So, let’s retrieve the query that our AUTORESUZ has defined:

SQL> SELECT text FROM all_views WHERE view_name = 'AUTORESUZ';
 
TEXT
----------
SELECT a1.

OMFG! The query seems to be there, but it is truncated…

In order to view the full query, you must set long with a value greater that text’s length. Like this:

SQL> SELECT text_length FROM all_views WHERE view_name = 'AUTORESUZ';
 
TEXT_LENGTH
-----------
	369
 
SQL> SELECT text FROM all_views WHERE view_name = 'AUTORESUZ';
 
TEXT
----------
SELECT a1.
 
SQL> SET long 369
SQL> SELECT text FROM all_views WHERE view_name = 'AUTORESUZ';         
 
TEXT
--------------------------------------------------------------------------------
SELECT a1.rec_key AS arecord,
  REGEXP_REPLACE(a2.rec_data,'^\|a(.*)','\1') AS nipuz,
  REGEXP_REPLACE(REGEXP_REPLACE(REGEXP_REPLACE(a1.rec_data,'^\|a(.*)\|6\(UZ.*','
\1'), '(.*)\|c(.*)','\1'), '(.*),\|d(.*)','\1') AS autoruz
 
 FROM var_fields2 a1,  var_fields2 a2
 WHERE a1.rec_key LIKE 'a%' AND a1.MARC_TAG='100' AND
  (a1.rec_key=a2.rec_key AND a2.MARC_TAG='090')

Joomla: know the section [SOLVED]

Lets suppose you are developing a joomla module and want to know the section in which you are.

The following code might help 🙂

<?php
function getSection($iId) {
    $database = &JFactory::getDBO();
    if(Jrequest::getCmd('view',0) == "section") {
        return JRequest::getInt('id');
    }
    elseif(Jrequest::getCmd('view',0) == "category") {
        $sql = "SELECT section FROM #__categories WHERE id = $iId ";
        $database->setQuery( $sql );
        $row=$database->loadResult();
        return $row;
    }
    elseif(Jrequest::getCmd('view',0) == "article") {
        $temp=explode(":",JRequest::getInt('id'));
        $sql = "SELECT sectionid FROM #__content WHERE id = ".$temp[0];
        $database->setQuery( $sql );
        $row=$database->loadResult();
        return $row;
    }
}
 
// use it like:
$sectionId=getSection(JRequest::getInt('id'));
?>

Python & Oracle [SOLVED] ImportError: libclntsh.so.11.1: wrong ELF class: ELFCLASS32

If you are getting a message like this:

>>> import cx_Oracle
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ImportError: libclntsh.so.11.1: wrong ELF class: ELFCLASS32

It means you are having issues with ELF (Executable and Linkable Format)

How to solve em?

First, locate the path to libclntsh.so.11.1 (usually in /usr):

[root@zaguan importaFHdesdeRoble]# find / -name "libclntsh.so.11.1"
/usr/lib/oracle/11.1/client64/lib/libclntsh.so.11.1
/usr/lib64/libclntsh.so.11.1

Note the presence of two files. Lets check wether they are for 32bits or 64bits:

[root@zaguan importaFHdesdeRoble]# file /usr/lib/oracle/11.1/client64/lib/libclntsh.so.11.1
/usr/lib/oracle/11.1/client64/lib/libclntsh.so.11.1: ELF 64-bit LSB shared object, AMD x86-64, version 1 (SYSV), not stripped
 
[root@zaguan importaFHdesdeRoble]# file /usr/lib64/libclntsh.so
/usr/lib64/libclntsh.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), not stripped

If your system is 64 bits (check it out with uname -a) you should be using the ELF 64-bit LSB shared object.

So, you can just:

mv /usr/lib64/libclntsh.so.11.1 /usr/lib64/libclntsh.so.11.1__32bits
cp /usr/lib/oracle/11.1/client64/lib/libclntsh.so.11.1 /usr/lib64/libclntsh.so.11.1

And now, you will be able to import Oracle library from python:

# python
Python 2.4.3 (#1, Apr 14 2011, 20:41:59)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-50)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import cx_Oracle
>>>

Or, if you want to do it “the right way”. Put this in a script.sh file and alter

#!/bin/bash
PATH=$PATH:$HOME/bin
ORACLE_HOME=/usr/lib/oracle/11.1/client64
LD_LIBRARY_PATH=/usr/lib/oracle/11.1/client64/lib
export ORACLE_HOME
export LD_LIBRARY_PATH
export PATH
 
# ALTER HERE with the path to python and the file which has the python code to connect to Oracle
salida=`/usr/bin/python ./pythoncodefile.py`

Mysql SELECT DISTINCT y tildes en utf8 [RESUELTO]

La verdad es que las tildes siempre son una lata en programación y en consultas a bases de datos MySQL
.
Imagina que tienes una tabla con los siguientes valores

ID value
1 Óscar
2 Oscar

Antes de empezar a hacer queries a la BD, nos aseguraremos de que se tiene en cuenta el utf8:

mysql> set name 'utf8';

Observa lo que sucede si haces un select distinct a secas:

mysql> SELECT DISTINCT value from table;
+--------+
| value   |
+--------+
| Oscar   |
+--------+

Los campos de tipo textual (CHAR y VARCHAR por ejemplo) son case-insensitive y accent-insensitive. Esto es, tanto OSCAR como Óscar, Oscar y ÓSCAR son lo mismo para mysql.

Si queremos que nos distinga esto (que Óscar y Oscar sean distintos), tenemos la opción de usar el modificador MD5 o, más simple, el modificador BINARY

mysql> SELECT DISTINCT binary value from table;
+--------+
| value   |
+--------+
| Oscar   |
+--------+
| Óscar   |
+--------+

ENGLISH:
Distinct works depending on column type.
Varchar is case insensitive and accent agnostic while comparing,
Binary string (Binary) columns require byte-to-byte match.
Keyword BINARY in front of an expression, makes it a byte-to-byte
comparison.

Ver imágenes de imageshack (evitar ranitas) [solucionado]

Si no veis las imágenes de imageshack y aparece la dichosa ranita (cubito de hielo con una rana dentro):
rana imageshack

Se debe a que imageshack controla el valor del campo referer de las cabeceras (headers) http para no permitir el hotlinking desde algunos sitios web.

Podéis solucionarlo siguiendo estos pasos:

Eliminar ranitas de imageshack en FIREFOX

1. Herramientas > Complementos
2. Obtener complementos
3. Buscamos ‘RefControl’
4. Descargamos e instalamos el complemento. Se reiniciará Firefox
5. Herramientas > Opciones RefControl…
6. Añadir sitio. En sitio ponemos imageshack.us
7. En acción, ponemos ‘Bloquear – no enviar referer’
8. Aceptamos, y aceptamos de nuevo.

Eliminar ranitas de imageshack en CHROME

En el icono del escritorio de Google Chrome boton derecho -> Propiedades
En la linea Destino: “C:\Archivos de programa\Google\Chrome\Application\chrome.exe”
Al final del todo tenemos que añadir “–no-referrers” (importante añadir un espacio)
con lo cual la linea Destino quedaria asi:
“C:\Archivos de programa\Google\Chrome\Application\chrome.exe” “–no-referrers”

Eliminar ranitas de imageshack en OPERA

Menú—> Configuración —> Opciones —> Avanzado —> Redes —> Desactivar casilla de “enviar info de referencia”.

También podéis usar tinypic u otros servicios que sí admiten hotlinking para evitar problemas a otros usuarios.

(Via forocoches).