Desarrollo código mantenible en WordPress utilizando Symfony
-
Upload
asier-marques -
Category
Technology
-
view
927 -
download
2
Transcript of Desarrollo código mantenible en WordPress utilizando Symfony
Acerca de mí
Asier MarquésOne man army in Simettric.com
@asiermarquesgithub.com/Simettriclinkedin.com/in/asier
"Cuando miras al abismo, el abismo también mira
dentro de tí"
WtfPress
WtfPress hell
— HTTP vs WP_Query
— Hooks oriented development
— Dependencias (plugins) delegadas en el usuario
— Ausencia de aplicación de PSRs
— No se utiliza Composer
Wtf_Query
/category/animales => index.php?category=animales
WP_Query( array( “category” => “animales”) );
theme/category.php
Template hierarchy
WP_Query ruta personalizada
add_action('init', function() {
add_rewrite_rule( '^tasks/([^/]*)/?', 'index.php?post_type=task' . '&category=$matches[1]' . '&controller=mi_accion', 'top' );
add_rewrite_tag('%controller%', '(([^/]*))');
});
Al entrar en esa ruta...
$wp_query->query_vars["post_type"]
$wp_query->query_vars["category"]
$wp_query->query_vars["controller"]
...podemos llamar a nuestro "controlador"
add_action('parse_query', function(\WP_Query $wp_query) {
if( $wp_query->query_vars["controller"] == "mi_accion" ) { // ¿mi controlador? }
});
Hooks driven development
WordPress heaven
— Mercado
— Tendencia a utilizarse como prototipo para validar mercado
— Su uso masivo
Cómo mejorarlo
— Composer
— Injección de dependencias
— Mejor gestión de rutas
— Eliminar lógica de negocio en templates
— MVC
— Sin romper compatibilidad
Demo
Aplicando MVC e Inyección de dependencias
Inyección de dependencias
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator([__DIR__ . "/Config"]));
$loader->load('services.yml');
Nuestro controller
class MiControlador {
/** * Route("/custom-path/{method}", name="mi_ruta"); */ function miAccion(Request $request) {
return 'template.php'; }
}
Anotación de ruta
/** * @Annotation * @Target({"PROPERTY"}) */class Route{
/** @var string */ public $path;
/** @var string */ public $name;
function __construct( $data=[] ){
if (isset($data['value'])) { $data['path'] = $data['value']; unset($data['value']); }
}
}
Recopilando las rutas
$routes = [];
AnnotationRegistry::registerFile( __DIR__ . "/Annotations/Route.php" );
$reflClass = new \ReflectionClass("MiControlador.php");
foreach($reflClass->getMethods() as $method) {
$classAnnotations = $reader->getMethodAnnotations($method);
foreach ($classAnnotations as $route) {
$routes[$route->name] = $route;
}}
Ejecutar controlador
add_action('parse_query', function(\WP_Query $wp_query) use ($container) {
if($route_name = $wp_query->query_vars[“route_name”]) {
if(isset( $routes[$route_name] )) {
$route = $routes[$route_name];
$controller = $route->createControllerInstance( $container );
$template = call_user_function( [ $controller, $route->getAction() ] );
$container->get("view")->setTemplate($template); } }});
Vistas
add_filter( 'template_include', function ( $template ) use ($container) {
return $container->get("view")->getTemplate() ? : $template;
}
¿Twig?Una de las formas de hacerlo (ejemplo simplificado)
add_filter( 'template_include', function ( $template ) use ($container) {
if ( $template = $container->get("wp_query")->query_vars["twig.template"] ) {
$twig = $container->get("twig");
$twig->render( $template );
// gestionar el response y terminar ejecución
}
return $template;
}
sense.simettic.comgithub.com/Simettric/Sense
Un proyecto en desarrollo activo, se acepta feedback [email protected]
Composer
Composer
— WPackagist.org
— Composer installers
"repositories": [ { "type": "composer", "url": "https://wpackagist.org" } ], "require": { "php": ">=5.4", "composer/installers": "1.*", "johnpbloch/wordpress": "4.*", "wpackagist-plugin/akismet": "dev-trunk", "wpackagist-theme/hueman": "*" }, "extra": { "wordpress-install-dir": "public/_wordpress/", "installer-paths": { "public/wp-content/plugins/{$name}/": ["type:wordpress-plugin"], "public/wp-content/themes/{$name}/": ["type:wordpress-theme"] } }
Estructura de directorios con Composer
Gestionados por composer
— public/_wordpress/
— public/wp-content/
— vendor/
Punto de entrada y configuración
— public/index.php— public/wp-config.php
public/index.php
define('WP_USE_THEMES', true);
require( __DIR__ . '/_wordpress/wp-blog-header.php' );
public/wp-config.php
require __DIR__ . '/../vendor/autoload.php';
define( 'SITE_HOST', 'http://example.com' );define( 'WP_SITEURL', SITE_HOST . '/_wordpress' );define( 'WP_HOME', SITE_HOST . '/' );define( 'WP_CONTENT_DIR', __DIR__ . '/wp-content' );define( 'WP_CONTENT_URL', SITE_HOST . '/wp-content' );
if ( !defined('ABSPATH') ) define('ABSPATH', __DIR__ . '/_wordpress');
Demo
Una instalación base
github.com/Simettric/wordpress-composer-installation
Entornos mixtos WordPress + Symfony
EkinoWordpressBundle
SeguridadUsando el login de WordPress para autenticarme en Symfony
ekino_wordpress: security: firewall_name: "secured_area" login_url: "/wp-login.php"
security: providers: main: entity: { class: Ekino\WordpressBundle\Entity\User, property: login }
firewalls: secured_area: pattern: ^/admin access_denied_handler: ekino.wordpress.security.entry_point entry_point: ekino.wordpress.security.entry_point anonymous: ~
access_control: - { path: ^/admin, roles: ROLE_WP_ADMINISTRATOR }
Repositorios
$postManager = $this->get('ekino.wordpress.manager.post');$userManager = $this->get('ekino.wordpress.manager.user');
$user = $userManager->find(2);
$post = $postManager->find(1);$post->setAuthor($user);
$postManager->save($post);
Conclusiones
— Se puede crear buen código en WordPress sin estar acoplado
— Se puede iniciar un proyecto en WordPress y migrar a Symfony después
— Se pueden integrar ambas plataformas
Code is poetry a symphony
Gracias
¿Preguntas?
Asier MarquésOne man army in Simettric.com
@asiermarquesgithub.com/Simettriclinkedin.com/in/asier