This talk included tens of tips and tricks, new features and rarely used options for Symfony and its ecosystem. Besides the full-stack Symfony framework, other related technologies were mentioned, like Doctrine, Composer, Twig, PHPUnit and Monolog.
A quick overview of tips, tricks and code snippets for developers using Symfony and all its ecosystem, from Monolog to Doctrine. Learn how to become more productive and discover some rarely used options and features.
마이크로서비스 스타일로 만들어진 시스템을 모노리틱 스타일로 이관한 사례와 함께 스프링을 이용해 모듈형 모노리스(modular monoliths)를 만든 경험을 바탕으로 모노리틱/마이크로서비스 보다 본질적인 문제를 제기하고, 문제 해결을 위한 아이디어와 코드를 공유합니다.
https://github.com/arawn/building-modular-monoliths-using-spring
이 자료는 2019년 KSUG 세미나에서 진행한 "잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다"를 기반으로 몇가지 내용을 추가하고, 전개 방식을 다듬어 조금 더 친절하게 만들어졌습니다.
A Hacker's perspective on AEM applications securityMikhail Egorov
Adobe Experience Manager (AEM), is a comprehensive content management solution for building websites, managing marketing content and assets. I started to look into AEM security back in 2015. Since then I discovered and reported several server-side vulnerabilities and developed toolset for AEM hacking to automate security testing of AEM web-applications.
In 2019 I reported one code injection and three XML external entity (XXE) vulnerabilities to Adobe PSIRT. They are known as CVE-2019-8086, CVE-2019-8087, CVE-2019-8088. These vulnerabilities allow anonymous attackers to compromise AEM web-application.
In the talk, I will disclose details of discovered vulnerabilities and exploitation techniques.
A quick overview of tips, tricks and code snippets for developers using Symfony and all its ecosystem, from Monolog to Doctrine. Learn how to become more productive and discover some rarely used options and features.
마이크로서비스 스타일로 만들어진 시스템을 모노리틱 스타일로 이관한 사례와 함께 스프링을 이용해 모듈형 모노리스(modular monoliths)를 만든 경험을 바탕으로 모노리틱/마이크로서비스 보다 본질적인 문제를 제기하고, 문제 해결을 위한 아이디어와 코드를 공유합니다.
https://github.com/arawn/building-modular-monoliths-using-spring
이 자료는 2019년 KSUG 세미나에서 진행한 "잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다"를 기반으로 몇가지 내용을 추가하고, 전개 방식을 다듬어 조금 더 친절하게 만들어졌습니다.
A Hacker's perspective on AEM applications securityMikhail Egorov
Adobe Experience Manager (AEM), is a comprehensive content management solution for building websites, managing marketing content and assets. I started to look into AEM security back in 2015. Since then I discovered and reported several server-side vulnerabilities and developed toolset for AEM hacking to automate security testing of AEM web-applications.
In 2019 I reported one code injection and three XML external entity (XXE) vulnerabilities to Adobe PSIRT. They are known as CVE-2019-8086, CVE-2019-8087, CVE-2019-8088. These vulnerabilities allow anonymous attackers to compromise AEM web-application.
In the talk, I will disclose details of discovered vulnerabilities and exploitation techniques.
배민찬(https://www.baeminchan.com) 서비스의 백엔드 시스템 중 일부가 지난 1년간 어떤 고민과 아이디어, 결과물을 만들어냈는지 공유하려고 합니다. 발표 중 언급되는 용어나 도구에 대해 일반적인 정의나 간단한 설명은 언급되나 자세히 다루지 않습니다. 사용된 도구들로 어떻게 이벤트 기반 분산 시스템을 만들었는지에 대한 이야기가 중심입니다.
'Ansible Roles done right' is a talk about "Applying TDD while writing roles. Automatic tests powered by Continuous Integration + containers. Quick demo of the new ansible-container." Funny title: "When your applications don't have tests, at least your infrastructure does..."
Formation complète ici:
http://www.alphorm.com/tutoriel/formation-en-ligne-virtualbox
Avec cette formation Oracle VirtualBox, vous allez découvrir le système de virtualisation GRATUIT, Oracle VirtualBox.
Cette formation pratique vous permettra d’acquérir les connaissances et compétences pour installer, gérer et maitriser l’environnement Oracle VirtualBox. Vous allez pouvoi apprendre la gestion des machines virtuelles, les clones, les snapshots, les méthodes de connexion réseau et les pilotes Virtio, la gestion du stockage, l'outil VBoxManage, le serveur Oracle VirtualBox,...
Deux bonus vous sont offerts: un lab réseau Cisco avec GNS3 pour connecter vos machines virtuelles , et un Lab SAN ISCSI pour partager et téléporter vos machines virtuelles.
A story of the passive aggressive sysadmin of AEMFrans Rosén
# By Frans Rosén
Adobe Experience Manager is an enterprise CMS with a troubled history. It was created with the angle of high customization factor, enabling consulting firms to deploy it all over the world for huge customers.
Then came security.
Frans will go through some terrible default configuration mistakes, Adobe’s love for bad Flash and how a sysadmin accidentialy exposed an international multi billion dollar company using only sad thoughts.
# About speaker
Frans Rosén is a tech entrepreneur, bug bounty hunter and a Security Advisor at Detectify, a security service for developers. He’s a frequent blogger at Detectify Labs and a top ranked participant of bug bounty programs, receiving some of the highest bounty payouts ever on HackerOne.
Frans was recently featured as #2 on Hackread’s list of 10 Famous Bug Bounty Hunters of All Time and the results of his security research has been covered in numerous international publications such as Observer, BBC, Ars Technica, Wired and Mashable.
Build clouds the way some of the world’s biggest public and private clouds are built—using CloudStack. This 60-minute webinar with the Cloudstack team will help you gain a better understanding of the CloudStack architecture and feature set.
Safeguarded Copy function that is available with IBM® Spectrum Virtualize software Version
8.4.2 supports the ability to create cyber-resilient point-in-time copies of volumes that cannot
be changed or deleted through user errors, malicious actions, or ransomware attacks. The
system integrates with IBM Copy Services Manager to provide automated backup copies and
data recovery.
This IBM Redpaper publication introduces the features and functions of Safeguarded Copy
function by using several examples.
This document is aimed at pre-sales and post-sales technical support and storage
administrators.
Formation complète ici:
http://www.alphorm.com/tutoriel/formation-en-ligne-kvm
Avec cette formation vous allez découvrir la puissance du système de virtualisation Libre KVM – KernelBase Virtual Machine et libvirt : librairie, outils notamment utilisée par KVM, Xen, Vmware, OpenStack...
Cette formation pratique vous permettra d'acquérir les connaissances et compétences nécessaires pour configurer et gérer un environnement virtualisé OpenSource avec du stockage San et NAS et les réseaux Virtuels. Aucune connaissance de kvm n’est requise. Toutefois une bonne connaissance des OS, réseaux, stockage est un plus, mais pas indispensable, un plus quand même.
Durant cette formation Ludovic, vous apprendra comment configurer, administrer au quotidien une infrastructure virtualisé, ainsi que les bonnes pratiques qui vous aideront à optimiser votre infrastructure.
Vous découvrirez également la communauté opensource et enfin vous donnera les éléments pour bien démarrer et mettre en œuvre un projet de virtualisation libre.
In this tutorial you will learn the basics of an OpenNebula deployment. To follow this tutorial you will need this OVA: https://s3.amazonaws.com/one-tutorials/OpenNebula-Tutorial-4.14.2.ova
배민찬(https://www.baeminchan.com) 서비스의 백엔드 시스템 중 일부가 지난 1년간 어떤 고민과 아이디어, 결과물을 만들어냈는지 공유하려고 합니다. 발표 중 언급되는 용어나 도구에 대해 일반적인 정의나 간단한 설명은 언급되나 자세히 다루지 않습니다. 사용된 도구들로 어떻게 이벤트 기반 분산 시스템을 만들었는지에 대한 이야기가 중심입니다.
'Ansible Roles done right' is a talk about "Applying TDD while writing roles. Automatic tests powered by Continuous Integration + containers. Quick demo of the new ansible-container." Funny title: "When your applications don't have tests, at least your infrastructure does..."
Formation complète ici:
http://www.alphorm.com/tutoriel/formation-en-ligne-virtualbox
Avec cette formation Oracle VirtualBox, vous allez découvrir le système de virtualisation GRATUIT, Oracle VirtualBox.
Cette formation pratique vous permettra d’acquérir les connaissances et compétences pour installer, gérer et maitriser l’environnement Oracle VirtualBox. Vous allez pouvoi apprendre la gestion des machines virtuelles, les clones, les snapshots, les méthodes de connexion réseau et les pilotes Virtio, la gestion du stockage, l'outil VBoxManage, le serveur Oracle VirtualBox,...
Deux bonus vous sont offerts: un lab réseau Cisco avec GNS3 pour connecter vos machines virtuelles , et un Lab SAN ISCSI pour partager et téléporter vos machines virtuelles.
A story of the passive aggressive sysadmin of AEMFrans Rosén
# By Frans Rosén
Adobe Experience Manager is an enterprise CMS with a troubled history. It was created with the angle of high customization factor, enabling consulting firms to deploy it all over the world for huge customers.
Then came security.
Frans will go through some terrible default configuration mistakes, Adobe’s love for bad Flash and how a sysadmin accidentialy exposed an international multi billion dollar company using only sad thoughts.
# About speaker
Frans Rosén is a tech entrepreneur, bug bounty hunter and a Security Advisor at Detectify, a security service for developers. He’s a frequent blogger at Detectify Labs and a top ranked participant of bug bounty programs, receiving some of the highest bounty payouts ever on HackerOne.
Frans was recently featured as #2 on Hackread’s list of 10 Famous Bug Bounty Hunters of All Time and the results of his security research has been covered in numerous international publications such as Observer, BBC, Ars Technica, Wired and Mashable.
Build clouds the way some of the world’s biggest public and private clouds are built—using CloudStack. This 60-minute webinar with the Cloudstack team will help you gain a better understanding of the CloudStack architecture and feature set.
Safeguarded Copy function that is available with IBM® Spectrum Virtualize software Version
8.4.2 supports the ability to create cyber-resilient point-in-time copies of volumes that cannot
be changed or deleted through user errors, malicious actions, or ransomware attacks. The
system integrates with IBM Copy Services Manager to provide automated backup copies and
data recovery.
This IBM Redpaper publication introduces the features and functions of Safeguarded Copy
function by using several examples.
This document is aimed at pre-sales and post-sales technical support and storage
administrators.
Formation complète ici:
http://www.alphorm.com/tutoriel/formation-en-ligne-kvm
Avec cette formation vous allez découvrir la puissance du système de virtualisation Libre KVM – KernelBase Virtual Machine et libvirt : librairie, outils notamment utilisée par KVM, Xen, Vmware, OpenStack...
Cette formation pratique vous permettra d'acquérir les connaissances et compétences nécessaires pour configurer et gérer un environnement virtualisé OpenSource avec du stockage San et NAS et les réseaux Virtuels. Aucune connaissance de kvm n’est requise. Toutefois une bonne connaissance des OS, réseaux, stockage est un plus, mais pas indispensable, un plus quand même.
Durant cette formation Ludovic, vous apprendra comment configurer, administrer au quotidien une infrastructure virtualisé, ainsi que les bonnes pratiques qui vous aideront à optimiser votre infrastructure.
Vous découvrirez également la communauté opensource et enfin vous donnera les éléments pour bien démarrer et mettre en œuvre un projet de virtualisation libre.
In this tutorial you will learn the basics of an OpenNebula deployment. To follow this tutorial you will need this OVA: https://s3.amazonaws.com/one-tutorials/OpenNebula-Tutorial-4.14.2.ova
Twig is the template engine used by Drupal 8 and other modern PHP applications. Twig's expressiveness, consistency and secure-by-default policy are still unparalleled among PHP's template engines.
In this session you'll learn advanced techniques, tips and tricks useful for real-world applications and uncommonly used features that will allow you to master Twig.
The Wonderful World of Symfony ComponentsRyan Weaver
Wow, Symfony Components!
In this talk, we'll look at the history of PHP, and the struggles as a community to create shared libraries between our large community. Find out the significance of PSR-0 and Composer in *your* life and how you can leverage libraries from all of PHP in your projects.
We'll also look at the most fundamental Symfony2 components - HttpFoundation, HttpKernel, EventDispatcher, & Routing - including those that have been adopted by Drupal 8. We'll also check out a bunch of the other interesting Symfony2 components that can be used as tools in any PHP project.
The goal of this talk is to show you just how easy finding and using high quality libraries has become in PHP. By the end, you'll be excited and ready to high-five all of your PHP friends.
There are so many interesting ways to authenticate a user: via an API token, social login, a traditional HTML form or anything else you can dream up. But until now, creating a custom authentication system in Symfony has meant a lot of files and a lot of complexity. Introducing Guard: a simple, but expandable authentication system built on top of the security component and introduced in Symfony 2.8. Want to authenticate via an API token? Great - that's just one class. Social login? Easy! Have some crazy legacy central authentication system? In this talk, we'll show you how you'd implement any of these in your application today. Don't get me wrong - you'll still need to do some work. But finally, the path will be clear and joyful.
Symfony 3.0 is just around the corner. Are you ready to migrate? The Symfony core team created a continuous upgrade path for progressively upgrading current apps. In this session, I'll show you this path so you'll be able to migrate your own applications to Symfony 3.0.
Symfony: Your Next Microframework (SymfonyCon 2015)Ryan Weaver
Microservices are a huge trend, and microframeworks are perfect for them: put together just a few files, write some code, and your done!
But Symfony is a big framework, right? Wrong! Symfony can be as small as a single file!
In this talk, we'll learn how to use Symfony as a micro-framework for your next project. Your app will stay small and clear, but without needing to give up the features or third-party bundles that you love. And if the project grows, it can evolve naturally into a full Symfony project.
So yes, Symfony can also be a microframework. Tell the world!
Las Jornadas Symfony 2011 comenzaron con una breve introducción a Symfony2.
Durante la presentación se muestran algunas de las características más destacadas de Symfony2 a través de diez palabras clave.
If you have used Facebook's React library, then you are familiar with the concept of application state. React components are, at their core (and as noted in the official documentation), simple state machines. This declarative approach to building a UI may take some adjusting to, but it ultimately simplifies kludgy imperative code into smaller, much more manageable pieces.
This pattern of manipulating state and responding to those changes can be implemented to great effect using the Symfony Event Dispatcher. This talk will step through this state-based approach to building an easily maintained and testable PHP application, tease out a few gotchas, and share real-world applications.
The quest for global design principles (SymfonyLive Berlin 2015)Matthias Noback
If you’re a programmer you make design decisions every second. You need to think, and often think hard, about everything. Luckily there are many useful design principles and patterns that you can apply. But some of them merely expose code smells. Others only help you design your classes. And some are applicable to packages only. Wouldn’t it be nice to have some more general, always useful, invariably applicable, foundational design principles? In this talk we’ll look at software from many different perspectives, and while we’re zooming in and out, we’ll discover some of the deeper principles that form the basis of proper object-oriented design. After attending this talk you will be able to make better design decisions by reflecting on the stream of messages that is flowing from object to object, and from application to application.
The Bundle system is one of the greatest and most powerful features of Symfony2. Bundles contain all the files related to a single feature of your application: controllers, entities, event listeners, form types, Twig templates, etc. But how much of that actually needs to be inside a bundle?
In this talk we’ll take a bundle, containing all those different types of classes, configuration files and templates, and strip it down to the bare necessities. And I promise that after moving many files out of the bundle, everything still works.
While looking for ways to move things out of the bundle, I will discuss some of the more advanced features of bundle design, like prepending configuration, compiler passes and Doctrine mapping drivers. We will end with a very lean bundle, surrounded by a few highly reusable, maximally decoupled libraries.
The Bundle system is one of the greatest and most powerful features of Symfony2. Bundles contain all the files related to a single feature of your application: controllers, entities, event listeners, form types, Twig templates, etc. But how much of that actually needs to be inside a bundle?
In this talk we’ll take a bundle, containing all those different types of classes, configuration files and templates, and strip it down to the bare necessities. And I promise that after moving many files out of the bundle, everything still works.
While looking for ways to move things out of the bundle, I will discuss some of the more advanced features of bundle design, like prepending configuration, compiler passes and Doctrine mapping drivers. We will end with a very lean bundle, surrounded by a few highly reusable, maximally decoupled libraries.
The Bundle system is one of the greatest and most powerful features of Symfony2. Bundles contain all the files related to a single feature of your application: controllers, entities, event listeners, form types, Twig templates, etc. But how much of that actually needs to be inside a bundle?
In this talk we’ll take a bundle, containing all those different types of classes, configuration files and templates, and strip it down to the bare necessities. And I promise that after moving many files out of the bundle, everything still works.
While looking for ways to move things out of the bundle, I will discuss some of the more advanced features of bundle design, like prepending configuration, compiler passes and Doctrine mapping drivers. We will end with a very lean bundle, surrounded by a few highly reusable, maximally decoupled libraries.
[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rulesSrijan Technologies
Speaker: Josef Dabernig a.k.a Dasjo
This webinar takes a look at how to automate some powerful backend capabilities for your Drupal site, using the Drupal 8 Rules. Take a look at how D8 Rules can change the way we build sites. Also, learn how you can contribute to getting Rules closer to a stable release.
Presentation for azPHP on setting up a new project using Zend_Tool. Also goes over creating basic modules, controllers, actions, models and layouts.
All code in the presentation has not necessarily been tested. Will update presentation when done.
Refactoring, Agile Entwicklung, Continuous Integration – all diese für nachhaltigen Erfolg wichtigen Vorgehensweisen setzen Erfahrung mit Unit Testing voraus. Abseits von den üblichen "Bowling"-Beispielen möchten wir gerne einen Crashkurs inkl. Best Practices für das erfolgreiche Unit Testing durchführen. Anhand eines Beispielprojekts auf Basis des Zend Frameworks werden wir nach der Installation von PHPUnit auf allen Notebooks gemeinsam eine kleine Applikation aufbauen, die durchgehend Test-driven entwickelt wird.
Andreas Hucks
SensioLabs Deutschland
CTO
Symfony has a wide user base today. Most who work with Symfony on a daily basis have configured their own services, are fluent in configuring routing and validators. But what is actually going on under the hood? What happens when the configuration is parsed? What is a cache warmup? What happens to a request before hitting your controller? How does the HttpKernel work? Andreas will help us gain insight into the inner workings of the Symfony framework. If you have used
Symfony, but have never built a compiler pass, a cache warmer, or are wondering how exactly the container is built, this talk is for you.
Practical tips for dealing with projects involving legacy code. Covers investigating past projects, static analysis of existing code, and methods for changing legacy code.
Presented at PHP Benelux '10
deSymfony 2017: Symfony 4, Symfony Flex y el futuro de SymfonyJavier Eguiluz
Un recorrido por las novedades que traerá Symfony 4 (cuando se publique en noviembre de 2017) y un primer vistazo a Symfony Flex, la nueva herramienta para crear y gestionar aplicaciones Symfony.
Silex, desarrollo web ágil y profesional con PHPJavier Eguiluz
Silex es el microframework de moda en el mundo PHP. Silex te permite desarrollar aplicaciones web profesionales con una agilidad sin precedentes. Su aprendizaje es tan rápido y sencillo que podrás dominarlo en menos de una hora.
This is the winner proposal of the Sismo Challenge programming contest organized by ibuildings.
Reference: http://techportal.ibuildings.com/2012/04/17/sismo-challenge-results/
La primera parte de la presentación trata de la seguridad en Symfony2, explicando los conceptos de autenticación y autorización.
La segunda parte muestra cómo crear el backend o parte de administración de un sitio web. Primero se hace todo a mano, luego se utiliza el generador de código de Symfony2 y por último se utiliza el Sonata Admin Bundle.
"Twig, cuando Django encontró a Symfony" fue la primera ponencia impartida durante el segundo día de las Jornadas Symfony 2011.
Durante la misma, se explican las características más destacadas del motor de plantillas Twig, empezando con las más adecuadas para diseñadores/maquetadores y siguiendo después con las características para desarrolladores.
También se mencionan brevemente las ventajas de la integración de Twig en Symfony2 y se concluye con un ejemplo práctico del uso de Twig en proyectos PHP propios.
Backend fue la quinta ponencia impartida durante el primer día de las Jornadas Symfony 2011. Se trata de la quinta parte de las seis que forman el tutorial de desarrollo de la aplicación github.com/desymfony.
Durante la misma se explica cómo crear a mano la parte de administración de la aplicación. También se explica cómo proteger la parte de administración con la protección que ofrece HTTP y con usuarios creados en memoria y no en base de datos. Por último, se muestra brevemente cómo utilizar el nuevo generador interactivo para crear automáticamente una administración básica.
Desymfony 2011 - Tutorial #1: Instalacion y primeros pasosJavier Eguiluz
Instalación y primeros pasos fue la primera ponencia impartida durante las Jornadas Symfony 2011. Se trata de la primera parte de las seis que forman el tutorial de desarrollo de la aplicación github.com/desymfony.
Durante la misma se explIca cómo instalar y configurar Symfony2, cómo instalar el proyecto deSymfony, cómo crear los bundles con el generador interactivo y también se introduce el funcionamiento de la arquitectura MVC en Symfony2 mediante la programación de la parte dedicada a mostrar las páginas estáticas de la aplicación.
Esta presentación es la versión simplificada de la que se utilizó en las primeras Jornadas Symfony. Puedes ver la grabación en vídeo de la presentación original en http://bit.ly/symfony2
- - - - - - -
This is the simplified version of the presentation used at the first Spanish Symfony Conference. You can watch the video recording of the original presentation at http://bit.ly/symfony2
Epistemic Interaction - tuning interfaces to provide information for AI supportAlan Dix
Paper presented at SYNERGY workshop at AVI 2024, Genoa, Italy. 3rd June 2024
https://alandix.com/academic/papers/synergy2024-epistemic/
As machine learning integrates deeper into human-computer interactions, the concept of epistemic interaction emerges, aiming to refine these interactions to enhance system adaptability. This approach encourages minor, intentional adjustments in user behaviour to enrich the data available for system learning. This paper introduces epistemic interaction within the context of human-system communication, illustrating how deliberate interaction design can improve system understanding and adaptation. Through concrete examples, we demonstrate the potential of epistemic interaction to significantly advance human-computer interaction by leveraging intuitive human communication strategies to inform system design and functionality, offering a novel pathway for enriching user-system engagements.
Generating a custom Ruby SDK for your web service or Rails API using Smithyg2nightmarescribd
Have you ever wanted a Ruby client API to communicate with your web service? Smithy is a protocol-agnostic language for defining services and SDKs. Smithy Ruby is an implementation of Smithy that generates a Ruby SDK using a Smithy model. In this talk, we will explore Smithy and Smithy Ruby to learn how to generate custom feature-rich SDKs that can communicate with any web service, such as a Rails JSON API.
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualityInflectra
In this insightful webinar, Inflectra explores how artificial intelligence (AI) is transforming software development and testing. Discover how AI-powered tools are revolutionizing every stage of the software development lifecycle (SDLC), from design and prototyping to testing, deployment, and monitoring.
Learn about:
• The Future of Testing: How AI is shifting testing towards verification, analysis, and higher-level skills, while reducing repetitive tasks.
• Test Automation: How AI-powered test case generation, optimization, and self-healing tests are making testing more efficient and effective.
• Visual Testing: Explore the emerging capabilities of AI in visual testing and how it's set to revolutionize UI verification.
• Inflectra's AI Solutions: See demonstrations of Inflectra's cutting-edge AI tools like the ChatGPT plugin and Azure Open AI platform, designed to streamline your testing process.
Whether you're a developer, tester, or QA professional, this webinar will give you valuable insights into how AI is shaping the future of software delivery.
Accelerate your Kubernetes clusters with Varnish CachingThijs Feryn
A presentation about the usage and availability of Varnish on Kubernetes. This talk explores the capabilities of Varnish caching and shows how to use the Varnish Helm chart to deploy it to Kubernetes.
This presentation was delivered at K8SUG Singapore. See https://feryn.eu/presentations/accelerate-your-kubernetes-clusters-with-varnish-caching-k8sug-singapore-28-2024 for more details.
Transcript: Selling digital books in 2024: Insights from industry leaders - T...BookNet Canada
The publishing industry has been selling digital audiobooks and ebooks for over a decade and has found its groove. What’s changed? What has stayed the same? Where do we go from here? Join a group of leading sales peers from across the industry for a conversation about the lessons learned since the popularization of digital books, best practices, digital book supply chain management, and more.
Link to video recording: https://bnctechforum.ca/sessions/selling-digital-books-in-2024-insights-from-industry-leaders/
Presented by BookNet Canada on May 28, 2024, with support from the Department of Canadian Heritage.
Key Trends Shaping the Future of Infrastructure.pdfCheryl Hung
Keynote at DIGIT West Expo, Glasgow on 29 May 2024.
Cheryl Hung, ochery.com
Sr Director, Infrastructure Ecosystem, Arm.
The key trends across hardware, cloud and open-source; exploring how these areas are likely to mature and develop over the short and long-term, and then considering how organisations can position themselves to adapt and thrive.
DevOps and Testing slides at DASA ConnectKari Kakkonen
My and Rik Marselis slides at 30.5.2024 DASA Connect conference. We discuss about what is testing, then what is agile testing and finally what is Testing in DevOps. Finally we had lovely workshop with the participants trying to find out different ways to think about quality and testing in different parts of the DevOps infinity loop.
UiPath Test Automation using UiPath Test Suite series, part 3DianaGray10
Welcome to UiPath Test Automation using UiPath Test Suite series part 3. In this session, we will cover desktop automation along with UI automation.
Topics covered:
UI automation Introduction,
UI automation Sample
Desktop automation flow
Pradeep Chinnala, Senior Consultant Automation Developer @WonderBotz and UiPath MVP
Deepak Rai, Automation Practice Lead, Boundaryless Group and UiPath MVP
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf91mobiles
91mobiles recently conducted a Smart TV Buyer Insights Survey in which we asked over 3,000 respondents about the TV they own, aspects they look at on a new TV, and their TV buying preferences.
Securing your Kubernetes cluster_ a step-by-step guide to success !KatiaHIMEUR1
Today, after several years of existence, an extremely active community and an ultra-dynamic ecosystem, Kubernetes has established itself as the de facto standard in container orchestration. Thanks to a wide range of managed services, it has never been so easy to set up a ready-to-use Kubernetes cluster.
However, this ease of use means that the subject of security in Kubernetes is often left for later, or even neglected. This exposes companies to significant risks.
In this talk, I'll show you step-by-step how to secure your Kubernetes cluster for greater peace of mind and reliability.
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...DanBrown980551
Do you want to learn how to model and simulate an electrical network from scratch in under an hour?
Then welcome to this PowSyBl workshop, hosted by Rte, the French Transmission System Operator (TSO)!
During the webinar, you will discover the PowSyBl ecosystem as well as handle and study an electrical network through an interactive Python notebook.
PowSyBl is an open source project hosted by LF Energy, which offers a comprehensive set of features for electrical grid modelling and simulation. Among other advanced features, PowSyBl provides:
- A fully editable and extendable library for grid component modelling;
- Visualization tools to display your network;
- Grid simulation tools, such as power flows, security analyses (with or without remedial actions) and sensitivity analyses;
The framework is mostly written in Java, with a Python binding so that Python developers can access PowSyBl functionalities as well.
What you will learn during the webinar:
- For beginners: discover PowSyBl's functionalities through a quick general presentation and the notebook, without needing any expert coding skills;
- For advanced developers: master the skills to efficiently apply PowSyBl functionalities to your real-world scenarios.
14. Accessing request parameters
use SensioBundleFrameworkExtraBundleConfigurationRoute;
use SymfonyBundleFrameworkBundleControllerController;
use SymfonyComponentHttpFoundationRequest;
/** @Route("/blog") */
class BlogController extends Controller
{
/** @Route("/", name="blog_index") */
public function indexAction()
{
$value1 = $request->query->get('parameter1');
$value2 = $request->request->get('parameter2');
// ...
}
}
15. Accessing request parameters
use SensioBundleFrameworkExtraBundleConfigurationRoute;
use SymfonyBundleFrameworkBundleControllerController;
use SymfonyComponentHttpFoundationRequest;
/** @Route("/blog") */
class BlogController extends Controller
{
/** @Route("/", name="blog_index") */
public function indexAction()
{
$value1 = $request->query->get('parameter1');
$value2 = $request->request->get('parameter2');
// ...
}
}
everybody uses the get() method,
but there are other useful methods
16. ParameterBag defines some useful methods
// very useful methods
$pageNumber = $request->query->getInt('page');
$isPublished = $request->query->getBoolean('published');
19. Naming
strategies
I learned this from
Ruud
Bijnen
More information
http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/
namingstrategy.html
20. Setting custom table/properties names
namespace AppBundleEntity;
use DoctrineORMMapping as ORM;
/** @ORMTable(name="api_users") */
class ApiUsers
{
/** @ORMColumn(type="string", name="api_token") */
private $apiToken;
/** @ORMColumn(type="datetime", name="created_at") */
private $createdAt;
}
21. Setting custom table/properties names
namespace AppBundleEntity;
use DoctrineORMMapping as ORM;
/** @ORMTable(name="api_users") */
class ApiUsers
{
/** @ORMColumn(type="string", name="api_token") */
private $apiToken;
/** @ORMColumn(type="datetime", name="created_at") */
private $createdAt;
}
23. Using a built-in Doctrine naming strategy
namespace AppBundleEntity;
use DoctrineORMMapping as ORM;
/** @ORMTable */
class ApiUsers
{
/** @ORMColumn(type="string") */
private $apiToken;
/** @ORMColumn(type="datetime") */
private $createdAt;
}
# app/config/config.yml
doctrine:
dbal:
# ...
orm:
naming_strategy: doctrine.orm.naming_strategy.underscore
this is automatically
translated into api_token
24. Defining a custom naming strategy
namespace DoctrineORMMapping;
interface NamingStrategy
{
function classToTableName($className);
function propertyToColumnName($propertyName);
function referenceColumnName();
function joinColumnName($propertyName);
function joinTableName($sourceEntity, $targetEntity, $propertyName);
function joinKeyColumnName($entityName, $referencedColumnName);
}
27. What if the target entity can change?
Invoice
entity
User
entityManyToOne
Company
entity
28. Our needs
• Create a generic InvoiceBundle able to
work both with User and Company
entities.
• No code change or special configuration is
needed for the bundle.
29. 1. Define an abstract "subject" interface
namespace AcmeInvoiceBundleModel;
interface InvoiceSubjectInterface
{
// Add here your custom methods
// ...
}
30. 2. Make entities implement this interface
use DoctrineORMMapping as ORM;
use AcmeInvoiceBundleModelInvoiceSubjectInterface;
/** @ORMEntity */
class User implements InvoiceSubjectInterface
{
// ...
}
/** @ORMEntity */
class Company implements InvoiceSubjectInterface
{
// ...
}
different
applications
31. 3. Configure the entity association
namespace AcmeInvoiceBundleEntity;
use DoctrineORMMapping AS ORM;
use AcmeInvoiceBundleModelInvoiceSubjectInterface;
/** @ORMEntity */
class Invoice
{
/**
* @ORMManyToOne(
targetEntity="AcmeInvoiceBundleModelInvoiceSubjectInterface")
*/
protected $subject;
}
32. 3. Configure the entity association
namespace AcmeInvoiceBundleEntity;
use DoctrineORMMapping AS ORM;
use AcmeInvoiceBundleModelInvoiceSubjectInterface;
/** @ORMEntity */
class Invoice
{
/**
* @ORMManyToOne(
targetEntity="AcmeInvoiceBundleModelInvoiceSubjectInterface")
*/
protected $subject;
}
abstract target entity
33. 4. Define the target entity (at each application)
# app/config/config.yml
doctrine:
# ...
orm:
# ...
resolve_target_entities:
AcmeInvoiceBundleModelInvoiceSubjectInterface:
AcmeAppBundleEntityCustomer
this is where magic
happens: dynamic entity
resolution at runtime
34. Improved
WHERE … IN
I learned this from More information
http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/changelog/
migration_2_5.html#query-api-where-in-query-using-a-collection-as-parameter
Marco
Pivetta
35. Common code when using collections
$categories = ...
$categoryIds = array();
foreach ($categories as $category) {
$categoryIds[] = $category->getId();
}
$queryBuilder = $this
->where('model.category IN (:category_ids)')
->setParameter('category_ids', $categoryIds)
;
36. Common code when using collections
$categories = ...
$categoryIds = array();
foreach ($categories as $category) {
$categoryIds[] = $category->getId();
}
$queryBuilder = $this
->where('model.category IN (:category_ids)')
->setParameter('category_ids', $categoryIds)
;
transform the
ArrayCollection
into an array of IDs
37. In Doctrine 2.5 this is no longer needed
$categories = ...
$categoryIds = array();
foreach ($categories as $category) {
$categoryIds[] = $category->getId();
}
$queryBuilder = $this
->where('model.category IN (:categories)')
->setParameter('categories', $categories)
;
WHERE..IN
supports the use of
ArrayCollection
40. Define the default table options
# app/config/config.yml
doctrine:
dbal:
default_table_options:
charset: utf8mb4
collate: utf8mb4_unicode_ci
engine: InnoDB
DoctrineBundle 1.6NEW
required to
support emojis
41. Savepoints
I learned this from More information
https://github.com/doctrine/DoctrineBundle/pull/451
http://doctrine.readthedocs.org/en/latest/en/manual/transactions.html
Christopher
Davis
42. Normal Doctrine transaction
try {
$conn->beginTransaction();
// do something ...
$conn->commit();
} catch(Exception $e) {
$conn->rollback();
}
43. Doctrine transaction with save points
try {
$conn->beginTransaction('create_user');
// do something ...
$conn->commit('create_user');
} catch(Exception $e) {
$conn->rollback('create_user');
}
Give a name to a
transaction to create
a "save point"
44. Nesting Doctrine transactions
try {
$conn->beginTransaction();
// do something ...
$conn->beginTransaction('create_user');
try {
// do something ...
$conn->commit('create_user');
} catch(Exception $e) { $conn->rollback('create_user'); }
$conn->commit();
} catch(Exception $e) { $conn->rollback(); }
Nested transaction
with a save point
49. The "action" suffix is optional for annotations
class DefaultController extends Controller
{
/**
* @Route("/", name="homepage")
*/
public function index(Request $request)
{
// ...
}
}
no need to call this
method indexAction()
50. The "action" suffix is optional for annotations
class DefaultController extends Controller
{
/**
* @Route("/", name="homepage")
*/
public function index(Request $request)
{
// ...
}
}
no need to call this
method indexAction()
this only works when using
routing annotations
51. The "action" suffix is optional for annotations
class DefaultController extends Controller
{
/**
* @Route("/", name="homepage")
*/
public function index(Request $request)
{
// ...
}
}
no need to call this
method indexAction()
this only works when using
routing annotations
best used when the
controller class only
contains action methods
52. The "method" param is optional for listeners
# app/config/services.yml
services:
app.exception_listener:
class: AppBundleEventListenerExceptionListener
tags:
- {
name: kernel.event_listener,
event: kernel.exception,
method: 'onKernelException'
}
no need to define the
method parameter
53. The "method" param is optional for listeners
# app/config/services.yml
services:
app.exception_listener:
class: AppBundleEventListenerExceptionListener
tags:
- {
name: kernel.event_listener,
event: kernel.exception,
method: 'onKernelException'
}
no need to define the
method parameter
on + camelCased event name
54. The is_granted() check in error pages
{# app/Resources/TwigBundle/views/Exception/error.html.twig #}
{% if app.user and is_granted('ROLE_ADMIN') %}
...
{% endif %}
Symfony 2.7 and previous need
this check to avoid issues in
pages not covered by a firewall.
55. The is_granted() check in error pages
{# app/Resources/TwigBundle/views/Exception/error.html.twig #}
{% if app.user and is_granted('ROLE_ADMIN') %}
...
{% endif %}
Symfony 2.7 and previous need
this check to avoid issues in
pages not covered by a firewall.
{% if is_granted('ROLE_ADMIN') %}
...
{% endif %}
Symfony 2.8 no longer
requires this check
58. This is what we
said during
SymfonyCon 2014
Don't load test classes in production
{
"autoload": {
"psr-4": { "MyLibrary": "src/" }
},
"autoload-dev": {
"psr-4": { "MyLibraryTests": "tests/" }
}
}
59. New "exclude-from-classmap" option
// composer.json
{
"autoload": {
"exclude-from-classmap": ["/Tests/", "/test/", "/tests/"]
}
}
These classes are excluded
from the optimized autoloader
60. New "exclude-from-classmap" option
// composer.json
{
"autoload": {
"exclude-from-classmap": ["/Tests/", "/test/", "/tests/"]
}
}
$ composer dump-autoload --optimize
These classes are excluded
from the optimized autoloader
64. Deprecated
filters
I learned this from More information
http://twig.sensiolabs.org/doc/advanced.html#deprecated-filtersFabien
Potencier
65. Applications evolve in time…
class AppExtension extends Twig_Extension
{
public function getFilters()
{
return array(
new Twig_SimpleFilter('old_filter', ...),
new Twig_SimpleFilter('new_filter', ...),
);
}
}
How can you deprecate
"old_filter" without
breaking the application?
66. Filters can be deprecated
class AppExtension extends Twig_Extension
{
public function getFilters()
{
return array(
new Twig_SimpleFilter('old_filter', ..., array(
'deprecated' => true,
'alternative' => 'new_filter',
)),
new Twig_SimpleFilter('new_filter', ...),
);
}
}
Twig 1.23NEW
This is how you deprecate
filters and alert developers
without breaking things
67. Check if some
block exists
I learned this from More information
https://github.com/twigphp/Twig/pull/1831Martin
Hasoň
68. Avoid missing blocks
{% if 'title' is block %}
<title>{{ block('title') }}<title>
{% endif %}
Twig 1.2XNEW
not merged yet
70. The problem with filter arguments
{{ product.photo|image(400, 150, 0.9) }}
71. The problem with filter arguments
{{ product.photo|image(400, 150, 0.9) }}
What if I need to define more arguments?
72. The problem with filter arguments
{{ product.photo|image(400, 150, 0.9) }}
{{ product.photo|image(
width = 400, height = 150, opacity = 0.9
) }}
What if I need to define more arguments?
this is a valid solution for Twig, but the
underlying PHP code is still very complex
73. Defining a filter with lots of arguments
<?php
$filter = new Twig_SimpleFilter('image', function (
$path, $width, $height, $opacity
) {
$path = ...
$width = ...
$height = ...
$opacity = ...
});
74. Defining a variadic filter
$filter = new Twig_SimpleFilter('image', function (
$path, $options = array()
) {
// ...
}, array('is_variadic' => true));
75. Defining a variadic filter
$filter = new Twig_SimpleFilter('image', function (
$path, $options = array()
) {
// ...
}, array('is_variadic' => true));
a single variadic parameter holds any
number of passed parameters (unlimited)
77. Template
source code
I learned this from More information
https://github.com/twigphp/Twig/pull/1813
https://github.com/twigphp/Twig/pull/1807
Nicolas
Grekas
78. The Template class added a new method
abstract class Twig_Template implements Twig_TemplateInterface
{
// ...
public function getSource()
{
// ...
}
}
Twig 1.22NEW
79. How to display the source code of the template
{% set template = _self %}
{{ template.source|e }}
80. How to display the source code of the template
{% set template = _self %}
{{ template.source|e }}
having the source code allows for
example to test if the template is
backwards/forwards compatible
81. The (dirty) secret of the getSource() method
/* default/index.html.twig */
class __TwigTemplate_c917e55e0a4ad9b0ed28003c15c48de756d875a69e121aca97d5a53e84eaef4f extends Twig_Template
{
public function __construct(Twig_Environment $env) { }
protected function doDisplay(array $context, array $blocks = array()) { // ... }
public function getTemplateName()
{
return "default/index.html.twig";
}
// ...
public function getDebugInfo()
{
return array ( 115 => 54, 109 => 53, 93 => 43, 68 => 22, 66 => 21, 57 => 15, 46 => 7, 41 => 4, 35 => 3, 11 => 1,);
}
}
/* {% extends 'base.html.twig' %}*/
/* */
/* {% block body %}*/
/* <div id="wrapper">*/
/* <div id="container">*/
/* <div id="welcome">*/
/* <h1><span>Welcome to</span> Symfony {{ constant('SymfonyComponentHttpKernelKernel::VERSION') }}</h1>*/
/* </div>*/
/* ... */
Compiled Twig templates include
its full source code at the bottom
83. Email delivery
whitelist
I learned this from More information
https://github.com/symfony/symfony-docs/pull/4924
https://github.com/symfony/symfony-docs/pull/4925
Terje
Bråten
E.
Weimann
84. In dev environment, redirect all emails
# app/config/config_dev.yml
swiftmailer:
delivery_address: dev@example.com
85. Whitelist some emails in dev environment
# app/config/config_dev.yml
swiftmailer:
delivery_address: dev@example.com
delivery_whitelist:
- "/notifications@example.com$/"
- "/^admin@*$/""
86. Whitelist some emails in dev environment
# app/config/config_dev.yml
swiftmailer:
delivery_address: dev@example.com
delivery_whitelist:
- "/notifications@example.com$/"
- "/^admin@*$/""
email addresses that match
the regular expression will be
sent (even in dev environment)
89. Setting ENV variables via the web server
<VirtualHost *:80>
ServerName Symfony
DocumentRoot "/path/to/symfony_2_app/web"
DirectoryIndex index.php index.html
SetEnv SYMFONY__DATABASE_USER user
SetEnv SYMFONY__DATABASE_PASSWORD secret
<Directory "/path/to/symfony_2_app/web">
AllowOverride All
Allow from All
</Directory>
</VirtualHost>
same as setting
database_user and
database_password
in parameters.yml
90. ENV variables are dumped into the container
// app/cache/dev/appDevDebugProjectContainer.xml
<container>
<parameters>
<parameter key="database_user">root</parameter>
<parameter key="database_password"> __secret__ </parameter>
<!-- ... -->
</parameters>
</container>
// app/cache/prod/appProdProjectContainer.php
protected function getDefaultParameters()
{
return array(
// ...
'database_user' => 'root',
'database_password' => __secret__,
);
}
DEV
environment
PROD
environment
91. ENV variables are dumped into the container
// app/cache/dev/appDevDebugProjectContainer.xml
<container>
<parameters>
<parameter key="database_user">root</parameter>
<parameter key="database_password"> __secret__ </parameter>
<!-- ... -->
</parameters>
</container>
// app/cache/prod/appProdProjectContainer.php
protected function getDefaultParameters()
{
return array(
// ...
'database_user' => 'root',
'database_password' => __secret__,
);
}
DEV
environment
PROD
environment
You can see the password.
92. ENV variables are dumped into the container
// app/cache/dev/appDevDebugProjectContainer.xml
<container>
<parameters>
<parameter key="database_user">root</parameter>
<parameter key="database_password"> __secret__ </parameter>
<!-- ... -->
</parameters>
</container>
// app/cache/prod/appProdProjectContainer.php
protected function getDefaultParameters()
{
return array(
// ...
'database_user' => 'root',
'database_password' => __secret__,
);
}
DEV
environment
PROD
environment
You can see the password.
It's static (if ENV variable
changes, app breaks)
93. This is what you want…
// app/cache/prod/appProdProjectContainer.php
protected function getDefaultParameters()
{
return array(
// ...
'database_user' => 'root',
'database_password' => getenv("SYMFONY__DATABASE_PASSWORD");
);
}
94. This is what you want…
// app/cache/prod/appProdProjectContainer.php
protected function getDefaultParameters()
{
return array(
// ...
'database_user' => 'root',
'database_password' => getenv("SYMFONY__DATABASE_PASSWORD");
);
}
… but we failed at
implementing this feature.
100. 3. In "dev" machine
• Credentials file doesn't exist but no error is
triggered (because of ignore_errors).
• App uses the regular parameters.yml file.
101. 4. In "prod" machine
• Credentials file overrides parameters.yml
• The right parameters are available
anywhere (e.g. console commands)
• Developers can't see the production
configuration options.
• Requires discipline to add/remove options.
107. Creating a custom channel is painless
# app/config/config.yml
monolog:
channels: ["marketing"]
now you can process these
messages apart from the
rest of logs (e.g. save them
in a different file)
$this->get('monolog.logger.marketing')->info('......');
# app/logs/dev.log
[2015-11-30 17:44:19] marketing.INFO: ...... [] []
108. The channel name can be a parameter
# app/config/config.yml
parameters:
app_channel: 'marketing'
monolog:
channels: [%app_channel%]
services:
app_logger:
class: ...
tags: [{ name: monolog.logger, channel: %app_channel% }]
MonologBundle 2.8NEW
112. Creating simple custom formatters is painless
# app/config/config.yml
services:
app.log.formatter:
class: 'MonologFormatterLineFormatter'
public: false
arguments:
- "%%level_name%% [%%datetime%%] [%%channel%%] %%message%%n
%%context%%nn"
- 'H:i:s'
- false
the format of
each log line
113. Creating simple custom formatters is painless
# app/config/config.yml
services:
app.log.formatter:
class: 'MonologFormatterLineFormatter'
public: false
arguments:
- "%%level_name%% [%%datetime%%] [%%channel%%] %%message%%n
%%context%%nn"
- 'H:i:s'
- false
the format of
each log line
the format of
%datetime% placeholder
114. Creating simple custom formatters is painless
# app/config/config.yml
services:
app.log.formatter:
class: 'MonologFormatterLineFormatter'
public: false
arguments:
- "%%level_name%% [%%datetime%%] [%%channel%%] %%message%%n
%%context%%nn"
- 'H:i:s'
- false
the format of
each log line
the format of
%datetime% placeholder
115. Creating simple custom formatters is painless
# app/config/config.yml
services:
app.log.formatter:
class: 'MonologFormatterLineFormatter'
public: false
arguments:
- "%%level_name%% [%%datetime%%] [%%channel%%] %%message%%n
%%context%%nn"
- 'H:i:s'
- false
the format of
each log line
the format of
%datetime% placeholder
ignore n inside the
log messages?
117. Custom log format Default log format
INFO [18:38:21] [php] The SymfonyComponent
DependencyInjectionReference::isStrict method is
deprecated since version 2.8 and will be removed in 3.0.
{"type":16384,"file":"myproject/vendor/symfony/symfony/
src/Symfony/Component/DependencyInjection/
Reference.php","line":73,"level":28928}
INFO [18:38:21] [request] Matched route "homepage".
{"route_parameters":{"_controller":"AppBundle
Controller
DefaultController::indexAction","_route":"homepage"},"r
equest_uri":"http://127.0.0.1:8000/"}
INFO [18:38:21] [security] Populated the TokenStorage
with an anonymous Token.
[]
DEBUG [18:38:21] [event] Notified event "kernel.request"
to listener "SymfonyComponentHttpKernelEventListener
DebugHandlersListener::configure".
[]
DEBUG [18:38:21] [event] Notified event "kernel.request"
to listener "SymfonyComponentHttpKernelEventListener
ProfilerListener::onKernelRequest".
[2015-11-30 18:38:21] php.INFO: The SymfonyComponent
DependencyInjectionReference::isStrict method is
deprecated since version 2.8 and will be removed in 3.0.
{"type":16384,"file":"myproject/vendor/symfony/symfony/
src/Symfony/Component/DependencyInjection/
Reference.php","line":73,"level":28928} []
[2015-11-30 18:38:21] request.INFO: Matched route
"homepage". {"route_parameters":
{"_controller":"AppBundleController
DefaultController::indexAction","_route":"homepage"},"r
equest_uri":"http://127.0.0.1:8000/"} []
[2015-11-30 18:38:21] security.INFO: Populated the
TokenStorage with an anonymous Token. [] []
[2015-11-30 18:38:21] event.DEBUG: Notified event
"kernel.request" to listener "SymfonyComponent
HttpKernelEventListener
DebugHandlersListener::configure". [] []
[2015-11-30 18:38:21] event.DEBUG: Notified event
"kernel.request" to listener "SymfonyComponent
HttpKernelEventListener
ProfilerListener::onKernelRequest". [] []
[2015-11-30 18:38:21] event.DEBUG: Notified event
"kernel.request" to listener "SymfonyComponent
HttpKernelEventListenerDumpListener::configure". []
[]
138. The security.interactive_login event
services:
login_listener:
class: AppBundleListenerLoginListener
arguments: ['@security.token_storage', '@doctrine']
tags:
- { name: 'kernel.event_listener', event: 'security.interactive_login' }
the most common event to "do things"
after the user successfully logs in
139. Defining a success handler
namespace AppBundleSecurity;
use SymfonyComponentSecurityHttpAuthenticationAuthenticationSuccessHandlerInterface;
class LoginHandler implements AuthenticationSuccessHandlerInterface
{
public function onAuthenticationSuccess(Request $request, TokenInterface $token)
{
// do something ...
return $this->redirect('...');
return new Response('...');
}
}
140. Defining a success handler
namespace AppBundleSecurity;
use SymfonyComponentSecurityHttpAuthenticationAuthenticationSuccessHandlerInterface;
class LoginHandler implements AuthenticationSuccessHandlerInterface
{
public function onAuthenticationSuccess(Request $request, TokenInterface $token)
{
// do something ...
return $this->redirect('...');
return new Response('...');
}
}
you just need to implement
this interface…
141. Defining a success handler
namespace AppBundleSecurity;
use SymfonyComponentSecurityHttpAuthenticationAuthenticationSuccessHandlerInterface;
class LoginHandler implements AuthenticationSuccessHandlerInterface
{
public function onAuthenticationSuccess(Request $request, TokenInterface $token)
{
// do something ...
return $this->redirect('...');
return new Response('...');
}
}
you just need to implement
this interface…
…and return a Response
instance
143. Enabling the success handler
# app/config/services.yml
services:
app.login_handler:
class: AppBundleSecurityLoginHandler
arguments: ...
# app/config/security.yml
firewalls:
main:
pattern: ^/
form_login:
success_handler: app.login_handler
the LoginHandler class is
executed when the user logs
in successfully and after the
event.interactive_login
145. Meaningful
data providers
I learned this from More information
http://www.thisprogrammingthing.com/2015/making-dataproviders-more-maintainableScott
Warren
146. Common data providers
public function getUserData()
{
return array(
array(true, false, false),
array(true, true, false),
array(true, true, true),
);
}
/** @dataProvider getUserData */
public function testRegistration($register, $enable, $notify)
{
// ...
}
147. When an error happens…
$ phpunit -c app
F..
Time: 137 ms, Memory: 12.50Mb
There was 1 failure:
1) AppBundleTestsControllerDefaultControllerTest::testRegistration
with data set #0 (true, false, false)
very hard to understand
the exact error
148. Meaningful data providers
public function getUserData()
{
return array(
'register user only' => array(true, false, false),
'register and enable' => array(true, true, false),
'register, enable and notify' => array(true, true, true),
);
}
/** @dataProvider getUserData */
public function testRegistration($register, $enable, $notify)
{
// ...
}
array keys are the
labels of each data set
149. When an error happens…
$ phpunit -c app
F..
Time: 137 ms, Memory: 12.50Mb
There was 1 failure:
1) AppBundleTestsControllerDefaultControllerTest::testRegistration
with data set "register user only" (true, false, false)
meaningful error
messages
151. Common data providers
public function dataProvider()
{
public function providerBasicDrivers()
{
return array(
array('doctrine.orm.cache.apc.class', array('type' => 'apc')),
array('doctrine.orm.cache.array.class', array('type' => 'array')),
array('doctrine.orm.cache.xcache.class', array('type' => 'xcache')),
array('doctrine.orm.cache.wincache.class', array('type' => 'wincache')),
array('doctrine.orm.cache.zenddata.class', array('type' => 'zenddata')),
);
}
}
152. Data providers using PHP generators
public function dataProvider()
{
public function providerBasicDrivers()
{
yield ['doctrine.orm.cache.apc.class', ['type' => 'apc']];
yield ['doctrine.orm.cache.array.class', ['type' => 'array']];
yield ['doctrine.orm.cache.xcache.class', ['type' => 'xcache']];
yield ['doctrine.orm.cache.wincache.class', ['type' => 'wincache']];
yield ['doctrine.orm.cache.zenddata.class', ['type' => 'zenddata']];
}
}
PHP 5.5NEW
153. Data providers using PHP generators
public function dataProvider()
{
public function providerBasicDrivers()
{
yield ['doctrine.orm.cache.apc.class', ['type' => 'apc']];
yield ['doctrine.orm.cache.array.class', ['type' => 'array']];
yield ['doctrine.orm.cache.xcache.class', ['type' => 'xcache']];
yield ['doctrine.orm.cache.wincache.class', ['type' => 'wincache']];
yield ['doctrine.orm.cache.zenddata.class', ['type' => 'zenddata']];
}
}
PHP 5.5NEW
it reduces memory
consumption
154. Better setUp
and tearDown
I learned this from More information
https://phpunit.de/manual/current/en/appendixes.annotations.html
#appendixes.annotations.before
Sebastian
Bergmann
155. Common use of setUp( ) method in tests
class IntegrationTest extends PHPUnit_Framework_TestCase
{
private $rootDir;
private $fs;
public function setUp()
{
$this->rootDir = realpath(__DIR__.'/../../../../');
$this->fs = new Filesystem();
if (!$this->fs->exists($this->rootDir.'/symfony.phar')) {
throw new RuntimeException("...");
}
}
}
156. Common use of setUp( ) method in tests
class IntegrationTest extends PHPUnit_Framework_TestCase
{
private $rootDir;
private $fs;
public function setUp()
{
$this->rootDir = realpath(__DIR__.'/../../../../');
$this->fs = new Filesystem();
if (!$this->fs->exists($this->rootDir.'/symfony.phar')) {
throw new RuntimeException("...");
}
}
}
public function setUp()
public function tearDown()
public static function setUpBeforeClass()
public static function tearDownAfterClass()
157. Better alternative: @before annotation
class IntegrationTest extends PHPUnit_Framework_TestCase
{
private $rootDir;
private $fs;
/** @before */
public function initialize()
{
$this->rootDir = realpath(__DIR__.'/../../../../');
$this->fs = new Filesystem();
}
/** @before */
public function checkPharFile() {
if (!$this->fs->exists($this->rootDir.'/symfony.phar')) {
throw new RuntimeException("...");
}
}
}
158. Better alternative: @before annotation
class IntegrationTest extends PHPUnit_Framework_TestCase
{
private $rootDir;
private $fs;
/** @before */
public function initialize()
{
$this->rootDir = realpath(__DIR__.'/../../../../');
$this->fs = new Filesystem();
}
/** @before */
public function checkPharFile() {
if (!$this->fs->exists($this->rootDir.'/symfony.phar')) {
throw new RuntimeException("...");
}
}
}
you can define any number
of @before methods
159. Better alternative: @before annotation
class IntegrationTest extends PHPUnit_Framework_TestCase
{
private $rootDir;
private $fs;
/** @before */
public function initialize()
{
$this->rootDir = realpath(__DIR__.'/../../../../');
$this->fs = new Filesystem();
}
/** @before */
public function checkPharFile() {
if (!$this->fs->exists($this->rootDir.'/symfony.phar')) {
throw new RuntimeException("...");
}
}
}
you can define any number
of @before methods
order matters (first
method is executed first)
160. Alternatives to setUp and tearDown
class IntegrationTest extends PHPUnit_Framework_TestCase
{
/** @before */
public function initialize() { }
/** @after */
public function clean() { }
/** @beforeClass */
public static function initialize() { }
/** @afterClass */
public static function initialize() { }
}
161. Avoid risky
tests
I learned this from More information
https://phpunit.de/manual/current/en/risky-tests.htmlSebastian
Bergmann
166. Use the PHPUnit Bridge to detect deprecations
$ composer require --dev symfony/phpunit-bridge
$ phpunit -c app
PHPUnit by Sebastian Bergmann and contributors.
.................
Time: 3.7 seconds, Memory: 75.00Mb
OK (17 tests, 21 assertions)
Remaining deprecation notices (368)
OK (17 tests, 21 assertions)
Remaining deprecation notices (368)
167. When a deprecation occurs…
This information is
useful, but incomplete.
Often you need the
stack trace of the code
that triggered the
deprecation.
168. On-demand deprecation stack traces
// BEFORE
$ phpunit -c app
// AFTER
$ SYMFONY_DEPRECATIONS_HELPER=/Blog::index/
phpunit -c app
A regular expression that
is matched against
className::methodName
169. On-demand deprecation stack traces
$ SYMFONY_DEPRECATIONS_HELPER=/.*/ phpunit -c app
The class "SymfonyBundleAsseticBundleConfigAsseticResource" is performing resource
checking through ResourceInterface::isFresh(), which is deprecated since 2.8 and will be removed in 3.0
Stack trace:
#0 vendor/symfony/symfony/src/Symfony/Component/Config/Resource/BCResourceInterfaceChecker.php(32):
trigger_error()
#1 app/bootstrap.php.cache(3061): SymfonyComponentConfigResourceBCResourceInterfaceChecker->isFresh()
#2 vendor/symfony/symfony/src/Symfony/Component/Config/ResourceCheckerConfigCacheFactory.php(45):
SymfonyComponentConfigResourceCheckerConfigCache->isFresh()
#3 vendor/symfony/symfony/src/Symfony/Component/Routing/Router.php(302): SymfonyComponentConfigResourceCheckerConfigCacheFactory->cache()
#4 vendor/symfony/symfony/src/Symfony/Component/Routing/Router.php(250): SymfonyComponentRoutingRouter->getMatcher()
#5 vendor/symfony/symfony/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php(154): SymfonyComponentRoutingRouter->matchRequest()
#6 [internal function]: SymfonyComponentHttpKernelEventListenerRouterListener->onKernelRequest()
#7 vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php(61): call_user_func()
#8 [internal function]: SymfonyComponentEventDispatcherDebugWrappedListener->__invoke()
#9 vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/EventDispatcher.php(181): call_user_func()
#10 vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/EventDispatcher.php(46): SymfonyComponentEventDispatcherEventDispatcher->doDispatch()
#11 vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php(132): SymfonyComponentEventDispatcherEventDispatcher-
>dispatch()
#12 app/bootstrap.php.cache(3178): SymfonyComponentEventDispatcherDebugTraceableEventDispatcher->dispatch()
#13 app/bootstrap.php.cache(3151): SymfonyComponentHttpKernelHttpKernel->handleRaw()
#14 app/bootstrap.php.cache(3302): SymfonyComponentHttpKernelHttpKernel->handle()
#15 app/bootstrap.php.cache(2498): SymfonyComponentHttpKernelDependencyInjectionContainerAwareHttpKernel->handle()
#16 vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Client.php(79): SymfonyComponentHttpKernelKernel->handle()
#17 vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Client.php(131): SymfonyComponentHttpKernelClient->doRequest()
#18 vendor/symfony/symfony/src/Symfony/Component/BrowserKit/Client.php(317): SymfonyBundleFrameworkBundleClient->doRequest()
#19 src/AppBundle/Tests/Controller/Admin/BlogControllerTest.php(42): SymfonyComponentBrowserKitClient->request()
#20 [internal function]: AppBundleTestsControllerAdminBlogControllerTest->testRegularUsersCannotAccessToTheBackend()
#21 {main}
It stops at the first
deprecation and shows
its stack trace
173. Automatic "smoke testing" for services
public function testContainerServices()
{
$client = static::createClient();
foreach ($client->getContainer()->getServiceIds() as $serviceId) {
$service = $client->getContainer()->get($serviceId);
$this->assertNotNull($service);
}
}
174. Automatic "smoke testing" for services
public function testContainerServices()
{
$client = static::createClient();
foreach ($client->getContainer()->getServiceIds() as $serviceId) {
$service = $client->getContainer()->get($serviceId);
$this->assertNotNull($service);
}
}
get all services defined
by the container
175. Automatic "smoke testing" for services
public function testContainerServices()
{
$client = static::createClient();
foreach ($client->getContainer()->getServiceIds() as $serviceId) {
$service = $client->getContainer()->get($serviceId);
$this->assertNotNull($service);
}
}
get all services defined
by the container
try to instantiate all of
them to look for errors
176. Automatic "smoke testing" for services
public function testContainerServices()
{
$client = static::createClient();
foreach ($client->getContainer()->getServiceIds() as $serviceId) {
try {
$service = $client->getContainer()->get($serviceId);
$this->assertNotNull($service);
} catch(InactiveScopeException $e) { }
}
}
you may need this try … catch to avoid
issues with request related services
177. Manual "smoke testing" for important services
public static function dataServices()
{
return [
['app.datetimepicker', 'AppBundleFormTypeDateTimePickerType'],
['app.redirect_listener', 'AppBundleEventListenerRedirectToPreferredLocaleListener'],
];
}
/** @dataProvider dataServices */
public function testImportantServices($id, $class)
{
$client = static::createClient();
$service = $client->getContainer()->get($id);
$this->assertInstanceOf($class, $service);
}
check that the service
is instantiable and that
the returned class is
the right one
179. Service instantiation should not take too long
public function testContainerServices()
{
$client = static::createClient();
foreach ($client->getContainer()->getServiceIds() as $serviceId) {
try {
$startedAt = microtime(true);
$service = $client->getContainer()->get($serviceId);
$elapsed = (microtime(true) - $startedAt) * 1000;
$this->assertLessThan(50, $elapsed);
} catch(InactiveScopeException $e) {
}
}
}
180. Service instantiation should not take too long
public function testContainerServices()
{
$client = static::createClient();
foreach ($client->getContainer()->getServiceIds() as $serviceId) {
try {
$startedAt = microtime(true);
$service = $client->getContainer()->get($serviceId);
$elapsed = (microtime(true) - $startedAt) * 1000;
$this->assertLessThan(50, $elapsed);
} catch(InactiveScopeException $e) {
}
}
}
services should be
created in 50ms or less
181. Most expensive
services in
Symfony Standard
Service Time (ms)
cache_warmer 42.95
doctrine.orm.default_entity_manager 14.05
web_profiler.controller.router 11.88
swiftmailer.mailer.default 6.65
profiler 5.45
annotation_reader 4.53
doctrine.dbal.default_connection 4.22
form.type_extension.form.validator 4.13
routing.loader 4.02
form.type.choice 3.10
184. Common lifecycle of a command
class MyCustomCommand extends ContainerAwareCommand
{
protected function configure()
{
}
protected function execute(InputInterface $input, OutputInterface $output)
{
}
}
185. Full lifecycle of a command
class MyCustomCommand extends ContainerAwareCommand
{
protected function configure()
{ }
protected function initialize(InputInterface $input, OutputInterface $output)
{ }
protected function interact(InputInterface $input, OutputInterface $output)
{ }
protected function execute(InputInterface $input, OutputInterface $output)
{ }
}
here you can ask the user for
any missing option or argument
186. Ask for any missing command argument
class MyCommand extends ContainerAwareCommand
{
// ...
protected function interact(InputInterface $input, OutputInterface $output)
{
$dialog = $this->getHelper('dialog');
foreach ($input->getArguments() as $argument => $value) {
if ($value === null) {
$input->setArgument($argument, $dialog->ask($output,
sprintf('<question>%s</question>: ', ucfirst($argument))
));
}
}
}
}
the interact() method is usually
very verbose. This is the minimal
useful interact() method.
190. Most commands are a mess
$description = $this->formatSection(
'container', sprintf('Information for service <info>%s</info>', $options['id']))
."n".sprintf('<comment>Service Id</comment> %s', isset($options['id']) ? $options['id'] : '-')
."n".sprintf('<comment>Class</comment> %s', get_class($service)
);
$description[] = sprintf('<comment>Scope</comment> %s', $definition->getScope(false));
$description[] = sprintf('<comment>Public</comment> %s', $definition->isPublic() ? 'yes' : 'no');
$description[] = sprintf('<comment>Synthetic</comment> %s', $definition->isSynthetic() ? 'yes' : 'no');
$description[] = sprintf('<comment>Lazy</comment> %s', $definition->isLazy() ? 'yes' : 'no');
$this->writeText($description, $options);
you are mixing content with
presentation, like in the good
old days of HTML+CSS
191. The new "Style Guide"
makes built-in commands
visually consistent.
192. You can use it in your own commands too
use SymfonyComponentConsoleStyleSymfonyStyle;
class MyCustomCommand
{
// ...
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
$io->...
// ...
}
}
193. Displaying a title (BEFORE)
// alternative 1
$formatter = $this->getHelperSet()->get('formatter');
$formattedBlock = $formatter->formatBlock($title, '', true);
$output->writeln($formattedBlock);
// alternative 2
$title = 'Lorem Ipsum Dolor Sit Amet';
$output->writeln('<info>'.$title.'</info>');
$output->writeln(str_repeat('=', strlen($title)));
// alternative 3
$output->writeln('');
$output->writeln('Add User Command Interactive Wizard');
$output->writeln('-----------------------------------');
194. Displaying a title (AFTER)
use SymfonyComponentConsoleStyleSymfonyStyle;
$io = new SymfonyStyle($input, $output);
$io->title('Lorem Ipsum Dolor Sit Amet');
195. Displaying a title (AFTER)
use SymfonyComponentConsoleStyleSymfonyStyle;
$io = new SymfonyStyle($input, $output);
$io->title('Lorem Ipsum Dolor Sit Amet');
196. Displaying a table (BEFORE)
$table = new Table($this->getOutput());
$table->setStyle('compact');
$table->setHeaders(['Parameter', 'Value']);
$table->addRow(['...', '...']);
$table->addRow(['...', '...']);
$table->addRow(['...', '...']);
$table->render();
197. Displaying a table (AFTER)
use SymfonyComponentConsoleStyleSymfonyStyle;
$headers = ['Parameter', 'Value'];
$rows = [ ... ];
$io = new SymfonyStyle($input, $output);
$io->table($headers, $rows);
198. Displaying a table (AFTER)
use SymfonyComponentConsoleStyleSymfonyStyle;
$headers = ['Parameter', 'Value'];
$rows = [ ... ];
$io = new SymfonyStyle($input, $output);
$io->table($headers, $rows);
199. All the common features are covered
$io = new SymfonyStyle($input, $output);
$io->title();
$io->section();
$io->text();
$io->listing();
$io->table();
$io->choice();
$io->success();
$io->error();
$io->warning();
$io->ask();
$io->askHidden();
$io->confirm();
200. Create consistent commands effortlesslyFull Sample Command
$ php app/console command
Lorem Ipsum Dolor Sit Amet
==========================
// Duis aute irure dolor in reprehenderit in voluptate velit esse
// cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
Name Method Scheme Host Path
----------------- ------ ------ ---- ---------------------
admin_post_new ANY ANY ANY /admin/post/new
admin_post_show GET ANY ANY /admin/post/{id}
admin_post_edit ANY ANY ANY /admin/post/{id}/edit
admin_post_delete DELETE ANY ANY /admin/post/{id}
----------------- ------ ------ ---- ---------------------
! [CAUTION] Lorem ipsum dolor sit amet, consectetur adipisicing elit,
! sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
! Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.
Consectetur Adipisicing Elit Sed Do Eiusmod
-------------------------------------------
* Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
* Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo.
* Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
Bundle namespace:
> AppBundle <Enter>
Bundle name [AcmeAppBundle]:
> <Enter>
Configuration format (yml, xml, php, annotation) [annotation]:
> <Enter>
Command title
All types of questions
Section title
List
Info message
Table
Caution admonition
! Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.
Consectetur Adipisicing Elit Sed Do Eiusmod
-------------------------------------------
* Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
* Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo.
* Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
Bundle namespace:
> AppBundle <Enter>
Bundle name [AcmeAppBundle]:
> <Enter>
Configuration format (yml, xml, php, annotation) [annotation]:
> <Enter>
Do you want to enable the bundle? (yes/no) [yes]:
> <Enter>
Configuration format (select one) [annotation]:
> yml
> xml
> php
> annotation
! [NOTE] Duis aute irure dolor in reprehenderit in voluptate velit esse
! cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat.
[OK] Lorem ipsum dolor sit amet, consectetur adipisicing elit
[ERROR] Duis aute irure dolor in reprehenderit in voluptate velit esse.
[WARNING] Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi.
All ty
Secti
List
All ty
resul
Note