Nueva pregunta

Pregunta:

 
  1  
 
Fecha: 09-03-2017 06:29:09 (En Español)

Objeto dentro de objeto[Resuelta]

Hola amig@s,

tengo un problema, he creado una clase PHP, dentro de esta clase PHP se me devuelve un objeto, (nativo de PHP), pero cuando instancio el objeto hecho por mí, tengo problemas, me explico:

Yo tengo esta clase hecha por mi:

class cURL{

	public $referer;
	public $linkAnalizar;
	public $agents;
	private $ch;
	private $cReferer;
	private $cUrl;
	private $cAgents;
	private $errorCurl;
	private $cHttp;
	private $cTime;
	private $cLocation;
	private $cRetTrans;
	private $cBinari;
	private $data;
	private $doc;
	private $xpath;
	private $muestraError;
	
	//Constructor
	public function __construct($portal, $enlaceAnalisis, $navegadores = ''){
		$this->referer      = $portal;
		$this->linkAnalizar = $enlaceAnalisis;
		if($navegadores != ''){
			$this->agents = $navegadores;
		}else{
			$this->agents = 'Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204 Safari/534.16';
		}
		$this->curlSession();
	}
	
	//Función de CURL Session
	private function curlSession(){
		//Inicializo a CURL session
		$this->ch = curl_init();
		$this->cReferer = curl_setopt($this->ch, CURLOPT_REFERER, $this->referer);
		$this->cUrl = curl_setopt($this->ch, CURLOPT_URL, urldecode($this->linkAnalizar)); 
		$this->cAgents = curl_setopt($this->ch, CURLOPT_USERAGENT, $this->agents);
		$this->cHttp = curl_setopt($this->ch, CURLOPT_HTTPHEADER, array("Accept-Language: es-es,en")); 
		$this->cTime = curl_setopt($this->ch, CURLOPT_TIMEOUT, 10); 
		$this->cLocation = curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, 1); 
		$this->cRetTrans = curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, 1); 
		$this->cBinary = curl_setopt($this->ch, CURLOPT_BINARYTRANSFER, 1); 
		$this->data = curl_exec($this->ch);
		$this->errorCurl = curl_error($this->ch);
		curl_close($this->ch);  
		@$this->doc = new DOMDocument();
		@$this->xpath = new DOMXPath($this->doc);
		
		return $this->xpath;
		
	}

}


Para instanciar mi objeto hago lo sigiuiente:

$ch3 = new cURL($referer, $enlaceMapa2, $agents);
$xpath3 = $ch3;				


Esto me devolvería un objeto XML nativo de PHP, y para acceder a sus nodos se hace mediante $objeto->query('query a comprobar');

El problema es que $xpath es la instancia del objeto hecho por mi, y al acceder medainte $xpath->query(); lo busca en mi objeto y no en el devuelto, por lo tanto me da el siguiente error:

PHP Fatal error: Uncaught Error: Call to undefined method cURL::query() in /home/.........


Alguien me puede ayudar por favor?
Etiquetas: PHP - PHP Avanzado - Pregunta - Programación Orientada a Objetos Votos: 1 - Respuestas: 5 - Vistas: 15 Compartir en: Google Facebook Twitter LinkedIn Link
 

Respuestas:

  • Fecha: 09-03-2017 08:16:16 Hola Fran, interesante pregunta/aporte, aquí te adjunto la clase modificada (la hice funcionar) con un ejemplo de uso.

    class cURL {
    
        public $referer;
        public $linkAnalizar;
        public $agents;
        private $ch;
        private $cReferer;
        private $cUrl;
        private $cAgents;
        private $errorCurl;
        private $cHttp;
        private $cTime;
        private $cLocation;
        private $cRetTrans;
        private $cBinari;
        private $data;
        private $doc;
        private $xpath;
        private $muestraError;
    
        //Constructor
        public function __construct($portal, $enlaceAnalisis, $navegadores = '') {
            $this->referer = $portal;
            $this->linkAnalizar = $enlaceAnalisis;
            if ($navegadores != '') {
                $this->agents = $navegadores;
            } else {
                $this->agents = 'Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204 Safari/534.16';
            }
            $this->curlSession();
        }
    
        //Función de CURL Session
        private function curlSession() {
            //Inicializo a CURL session
            $this->ch = curl_init();
            $this->cReferer = curl_setopt($this->ch, CURLOPT_REFERER, $this->referer);
            $this->cUrl = curl_setopt($this->ch, CURLOPT_URL, urldecode($this->linkAnalizar));
            $this->cAgents = curl_setopt($this->ch, CURLOPT_USERAGENT, $this->agents);
            $this->cHttp = curl_setopt($this->ch, CURLOPT_HTTPHEADER, array("Accept-Language: es-es,en"));
            $this->cTime = curl_setopt($this->ch, CURLOPT_TIMEOUT, 10);
            $this->cLocation = curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, 1);
            $this->cRetTrans = curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, 1);
            $this->cBinary = curl_setopt($this->ch, CURLOPT_BINARYTRANSFER, 1);
            $this->data = curl_exec($this->ch);
            $this->errorCurl = curl_error($this->ch);
            curl_close($this->ch);
            $this->doc = new DOMDocument();
            @$this->doc->loadHTML($this->data);
            $this->xpath = new DOMXPath($this->doc);
    
            return $this->xpath;
        }
    
        public function query($expression) {
            return $this->xpath->query($expression);
        }
    
    }
    


    Observa que la clave fue cargar la data con $this->doc->loadHTML($this->data); y luego crear el método query que básicamente delega la $expression al método query de DOMXPath.

    Ejemplo de uso:
    $referer = 'http://www.phpcentral.com/';
    $enlaceAnalisis = 'http://www.phpcentral.com/la_comunidad';
    $ch3 = new cURL($referer, $enlaceAnalisis);
    
    $xpathResultset = $ch3->query('//div[@class=\'lista_usuarios\']');
    echo '<pre>';
    foreach ($xpathResultset as $item) {
        print_r($item->nodeValue);
    }
    


    Saludos y buen código!

    PD: no hice otro ajuste más que hacer que funcione tu idea, tal vez alguien con un poco más de tiempo pueda tomar la clase y mejorar el constructor, atributos sin uso, etc... y compartir su aporte aquí mismo.
      Votos: 3 - Link respuesta
     
  • Fecha: 09-03-2017 09:47:54 Hola Fran,
    Me imagino que andas empezando con OOP.
    Los constructores devuelven por defecto la instancia que se está creando, en tu caso lo que estabas esperando es que al instanciar la clase cURL el mismo constructor ejecutara una serie de acciones y te regresara el resultado de la lógica que pusiste.

    Hay varias cosas que puedes aprender de este error:
    1. Las propiedades de una clase de preferencia deben ser protegidas o privadas. Si la visibilidad es pública debe haber una razón sumamente poderosa, de lo contrario puedes romper el concepto de caja negra. Si necesitas acceder/modificar una propiedad utiliza su setter/getter correspondiente.
    2. Los constructores se utilizan para generar una instancia de la clase.
    3. Se considera mala práctica poner cualquier lógica dentro del constructor que no sea para inicializar el estado del objeto.
    4. El método curlSession hace demasiado, tiene dependencias innecesarias y estás suprimiendo errores. Esto convierte a tu método en una futura pesadilla de mantenimiento.
    5. En la medida de lo posible no utilices sentencias else.

    Muchas veces menos líneas no es lo mejor para tu código.

    Te dejo el código un poco más limpio.
    La clase cURL ahora tiene una sola responsabilidad y no tiene dependencias.
    La clase MiBuscador es la que se encarga de realizar la búsqueda y tiene las dependencias necesarias.
    No hay sentencias else.
    Eliminé variables no utilizadas.

    De esta manera si más adelante decides utilizar SimpleXML u otra clase para manipular el DOM es muy fácil reemplazarlas modificando MiBuscador::query()

    Espero te sirva

    <?php
    
    class cURL
    {
        private $referer;
        private $linkAnalizar;
        private $agents;
        private $ch;
        private $cReferer;
        private $cUrl;
        private $cAgents;
        private $errorCurl;
        private $cHttp;
        private $cTime;
        private $cLocation;
        private $cRetTrans;
        private $data;
    
        /**
         * cURL constructor.
         *
         * @param string $portal
         * @param string $enlaceAnalisis
         * @param null   $navegadores
         */
        public function __construct($portal, $enlaceAnalisis, $navegadores = null)
        {
            $this->referer      = $portal;
            $this->linkAnalizar = $enlaceAnalisis;
            $this->agents       = 'Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204 Safari/534.16';
            if ($navegadores !== '') {
                $this->agents = $navegadores;
            }
        }
    
        /**
         * Obtiene los datos de la URL
         *
         * @return string
         * @throws Exception
         */
        public function getData()
        {
            $this->ch        = curl_init();
            $this->cReferer  = curl_setopt($this->ch, CURLOPT_REFERER, $this->referer);
            $this->cUrl      = curl_setopt($this->ch, CURLOPT_URL, urldecode($this->linkAnalizar));
            $this->cAgents   = curl_setopt($this->ch, CURLOPT_USERAGENT, $this->agents);
            $this->cHttp     = curl_setopt($this->ch, CURLOPT_HTTPHEADER, ['Accept-Language: es-es,en']);
            $this->cTime     = curl_setopt($this->ch, CURLOPT_TIMEOUT, 10);
            $this->cLocation = curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, 1);
            $this->cRetTrans = curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, 1);
            $this->cBinary   = curl_setopt($this->ch, CURLOPT_BINARYTRANSFER, 1);
            $this->data      = curl_exec($this->ch);
            $this->errorCurl = curl_error($this->ch);
            curl_close($this->ch);
            if (!empty($this->errorCurl)) {
                throw new \Exception("cURL error: {$this->errorCurl}");
            }
    
            return $this->data;
        }
    }
    
    class MiBuscador
    {
        /**
         * Encuentra los nodos con la info requerida
         *
         * @param string $data Código HTML sobre el que se va a buscar la info
         * @param string $expression
         *
         * @return DOMNodeList
         */
        public static function query($data, $expression)
        {
            $doc = new DOMDocument();
            if (!empty($data) && !empty($expression) && @$doc->loadHTML($data)) {
                $xpath = new DOMXPath($doc);
    
                return $xpath->query($expression);
            }
    
            return new DOMNodeList();
        }
    }
    
    $referer        = 'http://www.phpcentral.com/';
    $enlaceAnalisis = 'http://www.phpcentral.com/la_comunidad';
    
    $curl = new cURL($referer, $enlaceAnalisis);
    $html = $curl->getData();
    
    $resultSets = MiBuscador::query($html, '//div[@class=\'lista_usuarios\']');
    
    foreach ($resultSets as $item) {
        print_r($item->nodeValue);
    }
    
      Votos: 3 - Link respuesta
     
  •  
      0  
     
    Fecha: 10-03-2017 06:57:38 Muchísimas gracias Fernando por tu ayuda, ahora mismo voy a probarlo.
    Muchísimas gracias Ernesto también por tu ayuda y a parte gracias por las correcciones, intentaré mejorar mi código. Voy a probar también tu aprte.

    Por otro lado, como funciona throw new \Exception("cURL error: {$this->errorCurl}");?

    he buscado información pero lo que he encontrado está implementado de manera distinta, con catch y tal...

    Si no es mucho pedir me lo puedes explicar por favor?
      Votos: 0 - Link respuesta
     
  •  
      1  
     
    Fecha: 10-03-2017 09:58:41 Tras probar las 2 modificaciones he de decir que Fernando tu modificación si funciona, trabajaré con ella e intentaré mejorarla.

    Ernesto, la modificación que me has pasado falla, el error que da es el siguiente:

    PHP Fatal error: Uncaught Exception: cURL error: Operation timed out after 10001 milliseconds with 0 bytes received in......
    Stack trace:
    #0 busca.php(107): cURL->getData()
    #1 {main}
    thrown in clase.php on line 61

    La línea 61 es la siguiente:

    throw new \Exception("cURL error: {$this->errorCurl}");


    Gracias de todos modos.
      Votos: 1 - Link respuesta
     
  • Fecha: 11-03-2017 08:15:10 Hola Fran,
    Te explico un poco el tema de excepciones.

    Las expcepciones se utilizan para capturar eventos anómalos en tu programa, escenarios que pueden romper el funcionamiento de tu código pero que pueden ser capturados.

    En el caso del código que te mandé si la petición cURL tiene algún error, como que no se puede conectar, el recurso no está disponible, etc. La excepción captura el error y lo arroja.

    Como programador puedes capturar ese evento y hacer que tu aplicación reaccione de diferente manera al mismo, por ejemplo:

    Levantar un log del evento
    Reintentar la operación
    Crear un mensaje de error seguro y amigable para el usuario, etc

    En el caso del código que te pasé lo modifiqué un poco para que veas cómo puedes sacar provecho del mismo

    Saludos

    <?php
    class cURL
    {
        private $referer;
        private $linkAnalizar;
        private $agents;
        private $ch;
        private $cReferer;
        private $cUrl;
        private $cAgents;
        private $errorCurl;
        private $cHttp;
        private $cTime;
        private $cLocation;
        private $cRetTrans;
        private $data;
        /**
         * cURL constructor.
         *
         * @param string $portal
         * @param string $enlaceAnalisis
         * @param null   $navegadores
         */
        public function __construct($portal, $enlaceAnalisis, $navegadores = null)
        {
            $this->referer      = $portal;
            $this->linkAnalizar = $enlaceAnalisis;
            $this->agents       = 'Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204 Safari/534.16';
            if ($navegadores !== '') {
                $this->agents = $navegadores;
            }
        }
        /**
         * Obtiene los datos de la URL
         *
         * @return string
         * @throws Exception
         */
        public function getData()
        {
            $this->ch        = curl_init();
            $this->cReferer  = curl_setopt($this->ch, CURLOPT_REFERER, $this->referer);
            $this->cUrl      = curl_setopt($this->ch, CURLOPT_URL, urldecode($this->linkAnalizar));
            $this->cAgents   = curl_setopt($this->ch, CURLOPT_USERAGENT, $this->agents);
            $this->cHttp     = curl_setopt($this->ch, CURLOPT_HTTPHEADER, ['Accept-Language: es-es,en']);
            $this->cTime     = curl_setopt($this->ch, CURLOPT_TIMEOUT, 10);
            $this->cLocation = curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, 1);
            $this->cRetTrans = curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, 1);
            $this->cBinary   = curl_setopt($this->ch, CURLOPT_BINARYTRANSFER, 1);
            $this->data      = curl_exec($this->ch);
            $this->errorCurl = curl_error($this->ch);
            curl_close($this->ch);
            if (!empty($this->errorCurl)) {
                throw new \Exception("cURL error: {$this->errorCurl}");
            }
            return $this->data;
        }
    }
    class MiBuscador
    {
        /**
         * Encuentra los nodos con la info requerida
         *
         * @param string $data Código HTML sobre el que se va a buscar la info
         * @param string $expression
         *
         * @return DOMNodeList
         */
        public static function query($data, $expression)
        {
            $doc = new DOMDocument();
            if (!empty($data) && !empty($expression) && @$doc->loadHTML($data)) {
                $xpath = new DOMXPath($doc);
                return $xpath->query($expression);
            }
            return new DOMNodeList();
        }
    }
    
    $referer        = 'http://www.phpcentral.com/';
    $enlaceAnalisis = 'http://www.phpcentral.com/la_comunidad';
    
    try {
        $curl = new cURL($referer, $enlaceAnalisis);
        $html = $curl->getData();
    } catch (\Exception $e) {
        echo "Ocurrió un error al ejecutar el programa, el valor de la variable \$html es ''";
    }
    $resultSets = MiBuscador::query($html, '//div[@class=\'lista_usuarios\']');
    foreach ($resultSets as $item) {
        print_r($item->nodeValue);
    }
    
      Votos: 3 - Link respuesta
     
Para participar activamente de la comunidad primero debes autenticarte, ingresa al sistema.Iniciar Sesión
 
frjcbbae garagebible.com