2010-02-06 9 views
47

Tengo este código. ¿Es posible que un constructor de objetos User falle de alguna manera para que a $this->LoggedUser se le asigne un valor de NULL y el objeto se libere después de que el constructor vuelva?Constructor PHP para devolver un NULL

$this->LoggedUser = NULL; 
if ($_SESSION['verbiste_user'] != false) 
    $this->LoggedUser = new User($_SESSION['verbiste_user']);  
+7

Gran primera pregunta por el camino. –

+0

He visto un cierto CMS popular que devuelve FALSE en un constructor. ¡¿¡¿Que pasa con eso?!?! – loungerdork

+1

Sólo pensé en tocar aquí por razones de documentación. Dado que la fecha es muy remota, es posible que el CMS que está viendo esté diseñado para PHP4. PHP4 solía permitir muchas cosas malas, una de las cuales permitía al usuario sobreescribir $ this en el constructor nombrado (por ejemplo, $ this = false). – techdude

Respuesta

62

Suponiendo que está usando PHP 5, puede lanzar una excepción en el constructor:

class NotFoundException extends Exception {} 

class User { 
    public function __construct($id) { 
     if (!$this->loadById($id)) { 
      throw new NotFoundException(); 
     } 
    } 
} 

$this->LoggedUser = NULL; 
if ($_SESSION['verbiste_user'] != false) { 
    try { 
     $this->LoggedUser = new User($_SESSION['verbiste_user']); 
    } catch (NotFoundException $e) {} 
} 

Para mayor claridad, usted podría terminar con esto de forma estática método de fábrica:

class User { 
    public static function load($id) { 
     try { 
      return new User($id); 
     } catch (NotFoundException $unfe) { 
      return null; 
     } 
    } 
    // class body here... 
} 

$this->LoggedUser = NULL; 
if ($_SESSION['verbiste_user'] != false) 
    $this->LoggedUser = User::load($_SESSION['verbiste_user']); 

Como acotación al margen, algunas versiones de PHP 4 le permitió establecer los $ a esta NUL L dentro del constructor, pero no creo que haya sido sancionado oficialmente y la 'característica' finalmente se eliminó.

+4

+1 IMO, esta es la forma correcta de OO para indicar que no se construyó un objeto. –

+1

Depende de la naturaleza de la falla. Si fue una excepción, sí. Si un parámetro para el constructor no cumple con un criterio, en mi opinión no. –

+5

Pekka, no estoy seguro de qué tipo de "malos parámetros" no serían una excepción. Si no puede crear un objeto válido con un cierto conjunto de params seguramente eso es excepcional, ¿y debería arrojar una excepción? ¿Puedes dar un ejemplo para aclarar la distinción en la que estás pensando? (Veo que lo hace en la respuesta a continuación, eso sería útil aquí, ¡pero no puedo editar su comentario!) –

11

yo sepa esto no se puede hacer, siempre habrá new devolver una instancia del objeto.

Lo que suelo hacer para evitar este es:

  • Adición de una bandera booleana ->valid al objeto que determina si un objeto se cargó con éxito o no. El constructor entonces fijará la bandera

  • Creación de una función de contenedor que se ejecuta el comando new, devuelve el nuevo objeto en el éxito o el fracaso lo destruye y devuelve false

-

function get_car($model) 
     { 
     $car = new Car($model); 
     if ($car->valid === true) return $car; else return false; 
    } 

Me interesaría saber acerca de enfoques alternativos, pero no conozco ninguno.

+0

Gracias por aclarar. Así que, básicamente, podría simplemente envolver el nuevo comando en el intento ...atrapar y luego plantear una excepción en un constructor? – Tibor

+1

¡Buena pregunta! Creo que * puedes *, pero realmente no me suena bien. Si creo un carro de objetos con el modelo "Ford", simplemente podría ser que ningún carro de ese modelo está en la base de datos. Eso no es realmente para lo que * las excepciones * fueron diseñadas. Es más una condición esperada. Me interesaría ver qué otras respuestas surgen, qué se ve como la forma "correcta" de manejar esto. –

+0

esto está haciendo las cosas de manera sucia, compruebe la respuesta de @jaz303 – minhajul

3

Cuando un constructor falla por algún motivo desconocido, no devolverá un valor NULO o FALSO pero arroja una excepción. Como con todo con PHP5. Si no maneja la excepción, el script dejará de ejecutarse con un error de excepción no detectada.

+1

¿Cuándo lanza un constructor una excepción? Cuando devuelve falso? ¿O quiere decir que un constructor debe lanzar una excepción si una determinada condición no puede cumplirse? –

+1

Su constructor debe lanzar la excepción. – Tom

5

Considérelo de esta manera. Cuando usa new, obtiene un objeto nuevo. Período. Lo que hace es tener una función que busca un usuario existente y lo devuelve cuando lo encuentra. Lo mejor para expresar esto es probablemente una función de clase estática como User :: findUser(). Esto también es extensible a cuando deriva sus clases de una clase base.

+0

Eso suena el más lógico, sí. Acabo de comenzar la programación OO en PHP, así que no estoy completamente seguro de cómo manejar las cosas de una manera "adecuada". – Tibor

3

tal vez algo como esto:

class CantCreateException extends Exception{ 
} 

class SomeClass { 
    public function __construct() { 
     if (something_bad_happens) { 
      throw (new CantCreateException()); 
     } 
    } 
} 

try{ 
    $obj = new SomeClass(); 
} 
catch(CantCreateException $e){ 
    $obj = null; 
} 
if($obj===null) echo "couldn't create object"; 
//jaz303 stole my idea an wrap it into a static method 
4

Una fábrica podría ser útil aquí:

class UserFactory 
{ 
    static public function create($id) 
    { 
     return (
      filter_var( 
       $id, 
       FILTER_VALIDATE_INT, 
       [ 'options' => [ 'min_range' => 1, ] ] 
      ) 
       ? new User($id) 
       : null 
     ); 
    } 
} 
Cuestiones relacionadas