Este foro ya no está activo, así que no puedes publicar nuevas preguntas ni responder a las preguntas existentes.

Problema con los namespaces de las clases de PHP

2 de julio de 2014

Buenas amigos, tengo un problema al trabajar con clases de dos bundles diferentes. A continuación dejo la estructura básica:

src/Empresa/SEIPBundle/....
src/Empresa/CoreBundle/....

EL problema radica que en un listener llamado RegistrationListener.php y localizado en src/Empresa/SEIPBundle/EventListener/ quiero hacer uso de una clase (entity) ubicada en CoreBundle y me da este error:

ClassNotFoundException:
 
Attempted to load class "C_Rol" from namespace
"Empresa\CoreBundle\Entity" in /var/www/seip/src/Empresa/SEIPBundle
/EventListener/RegistrationListener.php
line 43. Do you need to "use" it from another namespace?

Ya me aseguré de que el Bundle esta en app/AppKernel.php:

// ...
new Empresa\CoreBundle\EmpresaCoreBundle(),
new Empresa\SEIPBundle\EmpresaSEIPBundle(),
// ...

Y en app/config/routing.yml:

empresa_core:
    resource: "@EmpresaCoreBundle/Controller/"
    type:     annotation
    prefix:   /
 
empresa_seip:
    resource: "@EmpresaSEIPBundle/Controller/"
    type:     annotation
    prefix:   /

Cualquier sugerencia será bien recibida.


Respuestas

#1

Según el mensaje de error, en la clase RegistrationListener tienes la siguiente instrucción:

use Empresa\CoreBundle\Entity\C_Rol;

Y según esa instrucción, deberías tener una clase llamada C_Rol en el archivo /var/www/seip/src/Empresa/CoreBundle/Entity/C_Rol.php. ¿Has comprobado si el archivo se llama exactamente así y está exactamente en esa localización?

@javiereguiluz

2 julio 2014, 21:50
#2

Hola Javier, gracias por responder. En efecto, esa fue mi primera acción, revisar el nombre y la ubicación. Inclusive comentando la línea del error más abajo hago uso de:

$em = $this->container->get('doctrine')->getManager();
$personal = $em->getRepository('\Empresa\CoreBundle\Entity\C_Personal');

Y también me da error. En este caso de que desconoce la clase.

Por otro lado hasta colocando la entidad como servicio y obteniéndolo a través del container, me dice más bien es que el servicio no lo reconoce. De momento seguiré debugueando...

@matjimdi

2 julio 2014, 22:09
#3

Respecto al código de ejemplo que muestras, en realidad con Symfony es mucho más fácil obtener el repositorio de una entidad. Sólo tienes que poner el nombre del bundle y el de la entidad separados con dos puntos:

$em = $this->container->get('doctrine')->getManager();
$personal = $em->getRepository('CoreBundle:C_Personal');

Con respecto al error original que comentas, me temo que sin ver el código de la clase que te da error es muy difícil descubrir la causa del problema. Necesitamos saber todos los use que has puesto y la llamada exacta que está provocando el error.

@javiereguiluz

2 julio 2014, 22:48
#4

OK, gracias por el dato Bundle:Entity. Por otro lado, acá va el código:

// src/Empresa/SEIPBundle/EventListener/RegistrationListener.php
 
namespace Empresa\SEIPBundle\EventListener;
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
use Tecnocreaciones\Bundle\AjaxFOSUserBundle\Event\FormEvent;
use Tecnocreaciones\Bundle\AjaxFOSUserBundle\FOSUserEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
//use Symfony\Component\EventDispatcher\GenericEvent;
//use Doctrine\ORM\EntityManager;
use Empresa\CoreBundle\Entity\C_Rol;
//use Empresa\CoreBundle\Entity\C_Personal;
/**
 * Description of RegistrationListener
 *
 * @author matias
 */
class RegistrationListener implements EventSubscriberInterface {
    //put your code here
    protected $container;
 
    public function setContainer(ContainerInterface $container = null) {
        $this->container = $container;
    }
 
     static public function getSubscribedEvents()
    {
        return array(
            FOSUserEvents::REGISTRATION_SUCCESS => 'onRegistrationSuccess',
        );
    }
 
    function onRegistrationSuccess(FormEvent $event) {
        /** @var $user \FOS\UserBundle\Model\UserInterface */
        $user = $event->getForm()->getData();
        $role = $event->getRequest()->get('role');
        //$rol = $this->container->get('empresa_core.entity.c_rol'); La prueba que tenia, de tipo servicio
        $rol = new C_Rol();
 
        $em = $this->container->get('doctrine')->getManager();
        $personal = $em->getRepository('CoreBundle:C_Personal');
        $num_personal = $user->getNumPersonal();
 
        //Consultamos si el usuario registrado se encuentra en la tabla maestra "personal"
        if(is_array($results = $personal->getByNumPersonal($num_personal)) && count($results) > 0){
            foreach($results as $result){
                //TODO: Hacer llamado a función (por crear) para determinar el rol del usuario registrado automáticamente
                var_dump($result->getNomPersonal());
            }
        } else{
            //$user->addRole($rol->rol_name[C_Rol::ROLE_DEFAULT]);//Asignamos el Rol por defecto
            $user->addRole('ROLE_WORKER_PQV');//Asignamos el Rol por defecto
        } 
 
        var_dump($user.'<br>');
die(); } }

@matjimdi

2 julio 2014, 23:59
#5

Tu código lo veo bien, así que sólo faltaría comprobar si la clase C_Rol tiene asignado el siguiente namespace:

<?php
// /var/www/seip/src/Empresa/CoreBundle/Entity/C_Rol.php
 
namespace Empresa\CoreBundle\Entity;
 
class C_Rol
{
    // ...
}

@javiereguiluz

3 julio 2014, 8:29
#6

Es correcto. Acá el código en C_Rol:

// /var/www/seip/src/Empresa/CoreBundle/Entity/C_Rol.php
namespace Empresa\CoreBundle\Entity;
 
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Gedmo\Mapping\Annotation as Gedmo;
 
/**
 * C_Rol
 *
 * @ORM\Table(name="seip_c_rol")
 * @ORM\Entity(repositoryClass="Empresa\CoreBundle\Model\C_RolRepository")
 */
class C_Rol
{
    const ROLE_DEFAULT = 0;
    const ROLE_WORKER_PQV = 1;
    // ...
 
    public $rol_name = array();
 
    public function __construct() {
        $this->rol_name[self::ROLE_DEFAULT] = 'ROLE_WORKER_PQV';
        $this->rol_name[self::ROLE_WORKER_PQV] = 'ROLE_WORKER_PQV';
        // ...
    }
 
    // propiedades ...
 
    // getters y setters ... 
}

@matjimdi

3 julio 2014, 13:25
#7

No soy capaz de ver el error que se está produciendo, así que quizás podemos probar con una solución más drástica. Si puedes, ejecuta el siguiente comando dentro del directorio del proyecto:

$ composer dump-autoload --optimize
 
Generating optimized autoload files

Una vez ejecutado ese comando, abre el archivo vendor/composer/autoload_classmap.php. Verás un array gigantesco de unas 2.000 líneas de longitud. Esas son todas las clases PHP de tu proyecto. Dime si encuentras ahí la clase Empresa\CoreBundle\Entity\C_Rol o si C_Rol no aparece por ninguna parte o está asociada a una ruta diferente.

@javiereguiluz

3 julio 2014, 14:52
#8

Ok, ya lo hice y sí está:

// ...
'Empresa\MasterBundle\Entity\C_Rol' => $baseDir . '/src/Empresa/MasterBundle/Entity/C_Rol.php',
// ...

Inclusive, creé otro bundle, llamado Objetive, y no hay problema con la importación de la entidad. Y como puedes notar en el nombre del bundle, hasta borró el CoreBundle y cambié C_Rol a MasterBundle (uno nuevo creado, a ver si había algún problema con palabra reservada o que sé yo je je) y me sigue saliendo el error sólo con MasterBundle\Entity\C_Rol

Y C_Rol, sólo esta en esas líneas, o sea, que no hay problema de ambigüedad en cuanto al nombre de la entidad.

@matjimdi

3 julio 2014, 15:14
#9

Mira, creo que ya vi el porque aunque no lo entiendo, si me pudieses ayudar o indicarme qué leer sería fenomenal.

Creé la misma Entidad C_Rol en Objetive que si me carga, y me lanzaba el mismo error sólo para C_Rol, entonces estaba obvio que era el nombre.

Así que cambie a Rol a secas y ya no tengo problema, así que la duda sería, por qué no me reconoce la sintaxis C_XXXX, o en dónde podría configurar para que lo acepte (en caso de ser posible, si no muero con esta je je)

@matjimdi

3 julio 2014, 15:21
#10

Bueno javier, gracias por la ayuda, de verdad que este error sirvió para adentrarme mucho más en la documentación del framework y entender otras cosas je je.

Por otro lado, al Symfony2 (por lo menos mi versión 2.4.6) manejarse bajo el estándar psr-0, ya vi el porque del error je je. Acá dejó el link a quien pueda interesar del estándar PSR-0.

@matjimdi

3 julio 2014, 15:36
#11

@matjimdi gracias por explicarnos cómo has solucionado el problema. Ahora entiendo por qué he sido tan torpe y no he visto el problema: nunca uso guiones bajos en los nombres de las clases y por eso no asociaba que Composer en realidad entiende la clase C_Rol como C\Rol.

De todas formas, si te fijas un poco, verás que ningún proyecto moderno de PHP utiliza guiones bajos. Solamente los siguen usando las librerías que quieren mantener la compatibilidad con sistemas muy antiguos (por ejemplo Twig y SwiftMailer).

@javiereguiluz

3 julio 2014, 16:27