CursosEmpresasBlogLiveConfPrecios

Listado y Postulación a Ofertas de Trabajo en Symfony

Clase 12 de 17 • Curso de Symfony Framework

Contenido del curso

Symfony Framework

  • 1
    Crea una bolsa de empleo con Symfony

    Crea una bolsa de empleo con Symfony

    01:00 min
  • 2
    Autenticación y Gestión de Ofertas en Symfony

    Autenticación y Gestión de Ofertas en Symfony

    10:12 min
  • 3
    Desarrollo de Bolsa de Empleo con Symfony en PHP

    Desarrollo de Bolsa de Empleo con Symfony en PHP

    02:42 min
  • 4
    Modelo de Datos para Bolsa de Empleo: Entidades y Relaciones

    Modelo de Datos para Bolsa de Empleo: Entidades y Relaciones

    02:17 min
  • 5
    Virtualización y configuración de entornos de desarrollo con Homestead

    Virtualización y configuración de entornos de desarrollo con Homestead

    04:07 min
  • 6
    Creación y Configuración de un Proyecto Symfony con Homestead

    Creación y Configuración de un Proyecto Symfony con Homestead

    02:44 min
  • 7
    Creación de Entidades y Migraciones en Symfony

    Creación de Entidades y Migraciones en Symfony

    04:04 min
  • 8
    Creación de Controladores y Rutas en Symfony

    Creación de Controladores y Rutas en Symfony

    04:14 min
  • 9
    Listado y Creación de Empresas en Symfony

    Listado y Creación de Empresas en Symfony

    03:44 min
  • 10
    Control de Acceso y Creación de Usuarios en Symfony

    Control de Acceso y Creación de Usuarios en Symfony

    06:12 min
  • 11
    Creación de usuarios en Symfony para administradores

    Creación de usuarios en Symfony para administradores

    02:41 min
  • 12
    Listado y Postulación a Ofertas de Trabajo en Symfony

    Listado y Postulación a Ofertas de Trabajo en Symfony

    Viendo ahora
  • 13
    Layouts y herencia de templates en Twig

    Layouts y herencia de templates en Twig

    03:06 min
  • 14
    Envío de Correos en Symfony con Mailer y Transport

    Envío de Correos en Symfony con Mailer y Transport

    02:01 min
  • 15
    Despliegue de Aplicaciones Symfony en Producción

    Despliegue de Aplicaciones Symfony en Producción

    05:16 min
  • 16
    Comparativa de Frameworks PHP: Symfony, Laravel y Más

    Comparativa de Frameworks PHP: Symfony, Laravel y Más

    02:08 min
  • 17
    Symfony proyecto terminado: certifica y planifica

    Symfony proyecto terminado: certifica y planifica

    00:38 min
Tomar examen

Escuelas

  • Desarrollo Web
    • Fundamentos del Desarrollo Web Profesional
    • Diseño y Desarrollo Frontend
    • Desarrollo Frontend con JavaScript
    • Desarrollo Frontend con Vue.js
    • Desarrollo Frontend con Angular
    • Desarrollo Frontend con React.js
    • Desarrollo Backend con Node.js
    • Desarrollo Backend con Python
    • Desarrollo Backend con Java
    • Desarrollo Backend con PHP
    • Desarrollo Backend con Ruby
    • Bases de Datos para Web
    • Seguridad Web & API
    • Testing Automatizado y QA para Web
    • Arquitecturas Web Modernas y Escalabilidad
    • DevOps y Cloud para Desarrolladores Web
  • English Academy
    • Inglés Básico A1
    • Inglés Básico A2
    • Inglés Intermedio B1
    • Inglés Intermedio Alto B2
    • Inglés Avanzado C1
    • Inglés para Propósitos Específicos
    • Inglés de Negocios
  • Marketing Digital
    • Fundamentos de Marketing Digital
    • Marketing de Contenidos y Redacción Persuasiva
    • SEO y Posicionamiento Web
    • Social Media Marketing y Community Management
    • Publicidad Digital y Paid Media
    • Analítica Digital y Optimización (CRO)
    • Estrategia de Marketing y Growth
    • Marketing de Marca y Comunicación Estratégica
    • Marketing para E-commerce
    • Marketing B2B
    • Inteligencia Artificial Aplicada al Marketing
    • Automatización del Marketing
    • Marca Personal y Marketing Freelance
    • Ventas y Experiencia del Cliente
    • Creación de Contenido para Redes Sociales
  • Inteligencia Artificial y Data Science
    • Fundamentos de Data Science y AI
    • Análisis y Visualización de Datos
    • Machine Learning y Deep Learning
    • Data Engineer
    • Inteligencia Artificial para la Productividad
    • Desarrollo de Aplicaciones con IA
    • AI Software Engineer
  • Ciberseguridad
    • Fundamentos de Ciberseguridad
    • Hacking Ético y Pentesting (Red Team)
    • Análisis de Malware e Ingeniería Forense
    • Seguridad Defensiva y Cumplimiento (Blue Team)
    • Ciberseguridad Estratégica
  • Liderazgo y Habilidades Blandas
    • Fundamentos de Habilidades Profesionales
    • Liderazgo y Gestión de Equipos
    • Comunicación Avanzada y Oratoria
    • Negociación y Resolución de Conflictos
    • Inteligencia Emocional y Autogestión
    • Productividad y Herramientas Digitales
    • Gestión de Proyectos y Metodologías Ágiles
    • Desarrollo de Carrera y Marca Personal
    • Diversidad, Inclusión y Entorno Laboral Saludable
    • Filosofía y Estrategia para Líderes
  • Diseño de Producto y UX
    • Fundamentos de Diseño UX/UI
    • Investigación de Usuarios (UX Research)
    • Arquitectura de Información y Usabilidad
    • Diseño de Interfaces y Prototipado (UI Design)
    • Sistemas de Diseño y DesignOps
    • Redacción UX (UX Writing)
    • Creatividad e Innovación en Diseño
    • Diseño Accesible e Inclusivo
    • Diseño Asistido por Inteligencia Artificial
    • Gestión de Producto y Liderazgo en Diseño
    • Diseño de Interacciones Emergentes (VUI/VR)
    • Desarrollo Web para Diseñadores
    • Diseño y Prototipado No-Code
  • Contenido Audiovisual
    • Fundamentos de Producción Audiovisual
    • Producción de Video para Plataformas Digitales
    • Producción de Audio y Podcast
    • Fotografía y Diseño Gráfico para Contenido Digital
    • Motion Graphics y Animación
    • Contenido Interactivo y Realidad Aumentada
    • Estrategia, Marketing y Monetización de Contenidos
  • Desarrollo Móvil
    • Fundamentos de Desarrollo Móvil
    • Desarrollo Nativo Android con Kotlin
    • Desarrollo Nativo iOS con Swift
    • Desarrollo Multiplataforma con React Native
    • Desarrollo Multiplataforma con Flutter
    • Arquitectura y Patrones de Diseño Móvil
    • Integración de APIs y Persistencia Móvil
    • Testing y Despliegue en Móvil
    • Diseño UX/UI para Móviles
  • Diseño Gráfico y Arte Digital
    • Fundamentos del Diseño Gráfico y Digital
    • Diseño de Identidad Visual y Branding
    • Ilustración Digital y Arte Conceptual
    • Diseño Editorial y de Empaques
    • Motion Graphics y Animación 3D
    • Diseño Gráfico Asistido por Inteligencia Artificial
    • Creatividad e Innovación en Diseño
  • Programación
    • Fundamentos de Programación e Ingeniería de Software
    • Herramientas de IA para el trabajo
    • Matemáticas para Programación
    • Programación con Python
    • Programación con JavaScript
    • Programación con TypeScript
    • Programación Orientada a Objetos con Java
    • Desarrollo con C# y .NET
    • Programación con PHP
    • Programación con Go y Rust
    • Programación Móvil con Swift y Kotlin
    • Programación con C y C++
    • Administración Básica de Servidores Linux
  • Negocios
    • Fundamentos de Negocios y Emprendimiento
    • Estrategia y Crecimiento Empresarial
    • Finanzas Personales y Corporativas
    • Inversión en Mercados Financieros
    • Ventas, CRM y Experiencia del Cliente
    • Operaciones, Logística y E-commerce
    • Gestión de Proyectos y Metodologías Ágiles
    • Aspectos Legales y Cumplimiento
    • Habilidades Directivas y Crecimiento Profesional
    • Diversidad e Inclusión en el Entorno Laboral
    • Herramientas Digitales y Automatización para Negocios
  • Blockchain y Web3
    • Fundamentos de Blockchain y Web3
    • Desarrollo de Smart Contracts y dApps
    • Finanzas Descentralizadas (DeFi)
    • NFTs y Economía de Creadores
    • Seguridad Blockchain
    • Ecosistemas Blockchain Alternativos (No-EVM)
    • Producto, Marketing y Legal en Web3
  • Recursos Humanos
    • Fundamentos y Cultura Organizacional en RRHH
    • Atracción y Selección de Talento
    • Cultura y Employee Experience
    • Gestión y Desarrollo de Talento
    • Desarrollo y Evaluación de Liderazgo
    • Diversidad, Equidad e Inclusión
    • AI y Automatización en Recursos Humanos
    • Tecnología y Automatización en RRHH
  • Finanzas e Inversiones
    • Fundamentos de Finanzas Personales y Corporativas
    • Análisis y Valoración Financiera
    • Inversión y Mercados de Capitales
    • Finanzas Descentralizadas (DeFi) y Criptoactivos
    • Finanzas y Estrategia para Startups
    • Inteligencia Artificial Aplicada a Finanzas
    • Domina Excel
    • Financial Analyst
    • Conseguir trabajo en Finanzas e Inversiones
  • Startups
    • Fundamentos y Validación de Ideas
    • Estrategia de Negocio y Product-Market Fit
    • Desarrollo de Producto y Operaciones Lean
    • Finanzas, Legal y Fundraising
    • Marketing, Ventas y Growth para Startups
    • Cultura, Talento y Liderazgo
    • Finanzas y Operaciones en Ecommerce
    • Startups Web3 y Blockchain
    • Startups con Impacto Social
    • Expansión y Ecosistema Startup
  • Cloud Computing y DevOps
    • Fundamentos de Cloud y DevOps
    • Administración de Servidores Linux
    • Contenerización y Orquestación
    • Infraestructura como Código (IaC) y CI/CD
    • Amazon Web Services
    • Microsoft Azure
    • Serverless y Observabilidad
    • Certificaciones Cloud (Preparación)
    • Plataforma Cloud GCP

Platzi y comunidad

  • Platzi Business
  • Live Classes
  • Lanzamientos
  • Executive Program
  • Trabaja con nosotros
  • Podcast

Recursos

  • Manual de Marca

Soporte

  • Preguntas Frecuentes
  • Contáctanos

Legal

  • Términos y Condiciones
  • Privacidad
  • Tyc promociones
Reconocimientos
Reconocimientos
Logo reconocimientoTop 40 Mejores EdTech del mundo · 2024
Logo reconocimientoPrimera Startup Latina admitida en YC · 2014
Logo reconocimientoPrimera Startup EdTech · 2018
Logo reconocimientoCEO Ganador Medalla por la Educación T4 & HP · 2024
Logo reconocimientoCEO Mejor Emprendedor del año · 2024
De LATAM conpara el mundo
YoutubeInstagramLinkedInTikTokFacebookX (Twitter)Threads

      ¿Qué puede hacer el candidato?

      Lo primero que debe poder hacer un candidato es ver las ofertas que hay disponibles, de ese modo, si encuentra alguna que sea de su agrado podrá aplicar a ella.

      Claro que, para que la postulación sea útil, deberá incluir su información de contacto.

      En ese momento necesitaremos que se registre si no lo ha hecho, o que se identifique si ya posee un usuario en el sistema.

      El listado de ofertas

      El método OfferController::index es un buen lugar para colocar un listado de todas las ofertas que tenemos.

      Dentro del archivo src/Controller/OfferController.php lo crearemos de esta forma:

      /** * @Route("/", name="offers") */ public function index(EntityManagerInterface $entityManager) { $offers = $entityManager->getRepository(Offer::class)->findAll(); return $this->render('offer/index.html.twig', [ 'offers' => $offers, ]); }

      Y armemos el template así:

      {% extends 'base.html.twig' %} {% block title %}Ofertas disponibles {% endblock %} {% block body %} <style> .example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; } .example-wrapper code { background: #F5F5F5; padding: 2px 6px; } </style> <div class="example-wrapper"> <h1>Ofertas disponibles</h1> {% if offers|length > 0 %} <ul> {% for offer in offers %} <li>{{ offer.title }}</li> {% endfor %} </ul> {% else %} <p>No hay ofertas aún</p> {% endif %} </div> {% endblock %}

      Sencillo pero servirá.

      ¿Qué nos falta?

      Sería bueno poder aplicar a una oferta, ¿cierto?

      Comencemos por crear el método que nos permitirá hacerlo:

      ¿Qué tal OfferController::apply?

      /** * @Route("/offer/{id}/apply", name="offer_apply") * @IsGranted("ROLE_APPLICANT") */ public function apply(Offer $offer, EntityManagerInterface $entityManager) { $user = $this->getUser(); $applicant = $entityManager->getRepository(Applicant::class)->findOneBy( [ 'user' => $user, ] ); $offer->addApplicant($applicant); $entityManager->persist($offer); $entityManager->flush(); return $this->redirectToRoute('offers'); }

      Como puede verse este método solo estará disponible para usuarios de tipo Candidato (Applicant).

      Una vez finalizado el proceso de aplicación el usuario será redirigido al listado (por si quiere aplicar a otras ofertas).

      Ahora, si ejecutamos esto, el pobre usuario se quedará con la duda de si su solicitud ha sido recibida o no... No podemos permitir que eso pase.

      Para enviar estos mensajes efímeros, Symfony pone a nuestra disposición lo que se conoce como mensajes flash.

      Modifiquemos ligeramente el método para que genere alguna indicación de lo que sucedió:

      try { $entityManager->flush(); $this->addFlash('success', 'Solicitud recibida!'); } catch (\Exception $exception) { $this->addFlash('danger', 'La solicitud no pudo almacenarse. Por favor intente nuevamente.'); }

      De este modo la información será almacenada en la sesión hasta que alguien la levante.

      ¿Quién mejor que un template para comunicar algo al usuario?

      Agreguemos entonces esto en templates/offer/index.html.twig:

      <div id="flash-messages"> {% for messages in app.flashes %} {% for message in messages %} <p>{{ message }}</p> {% endfor %} {% endfor %} </div>

      Y ahora nos falta agregar un link para que el usuario pueda ejecutar la acción de postularse.

      Para ello solo se requiere agregar un elemento tipo &lt;a> en el template.

      Para generarlo correctamente, usa el helper url.

      Un efecto sumamente interesante de haber puesto el annotation @IsGranted es que, si el visitante aún no ha iniciado sesión será redireccionado automáticamente a la pantalla de login.

      Claro que si se trata de la primera vez que nos visita deberá poder registrarse.

      El mecanismo de registro

      Un mecanismo de registro implica crear algún formulario, un método controlador y un template por lo menos. Es demasiado para hacerlo todo desde cero.

      Mejor usar el comando php bin/console make:registration-form.

      En nuestro caso, como la entidad User ya existía ha sido actualizada.

      Esto implica que antes que nada, debemos crear y ejecutar la migración para que la base de datos pueda darnos el soporte adecuado.

      Si ejecutas el comando php bin/console debug:router te encontrarás con una ruta nueva: app_register (/register).

      Si diriges tu navegador hacia allí te encontrarás con:

      Nada mal, ¿eh? Ya tenemos un mecanismo de registro de usuarios casi listo.

      ¿Casi? ¿Qué falta?

      Hay un detalle importante… piénsatelo un poco.

      Los usuarios que se registren deben tener el rol ROLE_APPLICANT.

      Para ello, ve directo a src/Controller/RegistrationController y justo antes del $entityManager->persist($user); coloca:

      $user->setRoles(array_merge($user->getRoles(), ['ROLE_APPLICANT']));

      Lo que nos queda ahora es completar los datos de contacto.

      Eso lo haremos como primer paso luego de un login exitoso.

      Completando los datos de contacto

      Nuevamente debemos ir a tocar el método onAuthenticationSuccess de la clase LoginFormAuthenticator.

      En este caso estamos buscando completar qué debe suceder cuando el usuario que se ha autenticado es un postulante.

      Nos quedaría pues completar el último else:

      } else { return new RedirectResponse($this->urlGenerator->generate('offers')); }

      Un único detalle: con este código resolvimos el caso de que el usuario ingrese directamente a través del login.

      Eso está muy bien, pero no nos servirá para resolver el caso que tenemos en frente.

      Nota que antes de ese if que permitirá redirigir a cada quién según su rol, hay algo que evitamos nombrar hasta ahora:

      if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) { return new RedirectResponse($targetPath); }

      Este código es el que permite que el usuario regrese a donde estaba antes de realizar la autenticación.

      En nuestro caso será el método OfferController::apply.

      De modo que puede haber un pequeño supuesto que no se cumpla: podemos encontrarnos con que no exista un Applicant para el usuario logeado (aunque su rol sea postulante).

      ¿Cómo solucionamos este inconveniente? Empecemos por detectar la situación encerrando todo el código en un if:

      if ( $applicant = $entityManager->getRepository(Applicant::class)->findOneBy( [ 'user' => $user, ] ) ) { $offer->addApplicant($applicant); $entityManager->persist($offer); try { $entityManager->flush(); $this->addFlash('success', 'Solicitud recibida!'); } catch (\Exception $exception) { $this->addFlash('danger', 'La solicitud no pudo almacenarse. Por favor intente nuevamente.'); } return $this->redirectToRoute('offers'); }

      Lo que nos falta es crear un formulario para que el usuario pueda ingresar sus datos personales y regresar aquí.

      La parte de crear el formulario y el controlador te la dejo a tí, no debería ser compleja con todo lo que aprendiste hasta aquí.

      Asumiré que contamos con un controlador ApplicantController.

      Dentro de él debemos crear un método que permita cargar los datos personales del postulante. Por ejemplo:

      /** * @Route("/applicant/new", name="applicant_new") * @param Request $request * @param EntityManagerInterface $entityManager */ public function new(Request $request, EntityManagerInterface $entityManager) { $applicant = new Applicant(); $applicant->setUser($this->getUser()); $form = $this->createForm(ApplicantType::class, $applicant); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()){ $entityManager->persist($applicant); $entityManager->flush(); return $this->redirectToRoute('offer_apply', [ 'id' => $request->get('offerId'), ]); } return $this->render('applicant/new.html.twig', [ 'form' => $form->createView(), ]); }

      Cuando esta incorporación finalice querremos que el usuario sea redirigido nuevamente a donde estaba para poder completar su postulación.

      Es por ello que hacemos un redirect a la URL correspondiente a offer_apply pasando como parámetro el id de oferta que esperamos recibir como parámetro.

      Claro que para recibirlo alguien deberá haberlo enviado…

      Es hora de completar la modificación de OfferController::apply agregando la cláusula else:

      } else { return $this->redirectToRoute('applicant_new', [ 'offerId' => $offer->getId(), ]); }

      Y ahora sí, nuestros visitantes ya pueden postularse a puestos de trabajo.

      Meme de bebe orgulloso

      Está todo casi listo, nos queda hacer un pequeño ajuste: si bien el mecanismo de registro está en su lugar y funciona, es un poco difícil de acceder.

      ¿Qué mejor lugar para poner un link directo que en el formulario de login?

      En el template templates/security/login.html.twig agrega:

      <p><a href="{{ url('app_register') }}">Sign up!</a></p>

      Perfecto, ahora sí :)

      Veamos nuevamente cómo es el flujo por si no ha quedado del todo claro:

      Flujo de la  la aplicacion

      ¡Excelente! Ahora tenemos una aplicación bastante funcional… es hora de afinar algunos detalles menores para hacer más profesional nuestro sitio.

      El primero que podemos solucionar de forma sencilla es poner una página inicial diferente de la que viene con Symfony:

      Pantalla de bienvenida de Symfony

      El modo de lograrlo está bastante explícito, ¿no?

      El mensaje dice “You're seeing this page because you haven't configured any homepage URL” (Estás viendo esta página porque no has configurado ninguna URL de página de inicio).

      Podemos asumir sin mucho riesgo que tendremos más postulantes que empresas o administradores, con lo cual, el listado de ofertas parece un buen lugar para que arranque nuestra aplicación.

      Basta con quitar de OfferController el annotation @Route:

      /** * Class OfferController * @package App\Controller * @Route("/offer") */ class OfferController extends AbstractController

      Listo. Cada vez que un visitante llegue a nuestro sitio será recibido con un listado de ofertas de trabajo.

      Ahora seguramente nos gustaría agregar un logo, tal vez algún menú o quizás algún otro elemento que nos acompañe por toda la aplicación.

      Por supuesto que podríamos duplicar el código en cada template pero… ¿quién quiere hacer eso?

      En la próxima clase aprenderás a hacerlo de la manera correcta: mediante Layouts.

      ¡Acompáñame!

      Comentarios

        Carlos Eduardo Gomez García

        Carlos Eduardo Gomez García

        teacher•
        hace 5 años

        "La parte de crear el formulario y el controlador te la dejo a tí, no debería ser compleja con todo lo que aprendiste hasta aquí."

        ¿REALLY? Pero si apenas se ha explicado esto!

          Jimmy Buriticá Londoño

          Jimmy Buriticá Londoño

          student•
          hace 5 años

          Me siento igual de frustrado.

          Mariano Gastón Paduani

          Mariano Gastón Paduani

          student•
          hace 4 años

          Muy malo realmente

        Martin Campos

        Martin Campos

        student•
        hace 5 años

        Recuerden que el link a la postulación de la oferta debe contener como parametro la id de la oferta

        <a href="{{ url('offer_apply', {id: offer.id}) }}">Apply</a>