[Resuelto] Problemas de inclusion de libreria

El problema que tengo solo me da en linux porque en windows me funciona correctamente, y es que dentro de la carpeta protected yo cree una nueva carpeta llamada vendor dentro de la cual puse la libreria FPDF, donde la ruta hacia la clase fpdf.php es

"vendor/FPDF/fpdf153/fpdf.php", entonces dentro de la carpeta components se encuentra la clase Controller.php y en esta puse lo siguiente

Yii::import(‘application.vendor.FPDF.fpdf153.*’);

require_once(‘fpdf.php’);

require_once(‘reportes.php’); //esta clase se encuentra en el misma carpeta que fpdf.php

Algo que en windows me funciona a la perfeccion pero en linux me da el error


PHP Error

Description

include(FPDF.php): failed to open stream: No such file or directory

Source File

/var/www/yii-1.1.4.r2429/framework/YiiBase.php(341)

00329: * @param string class name

00330: * @return boolean whether the class has been loaded successfully

00331: */

00332: public static function autoload($className)

00333: {

00334: // use include so that the error PHP file may appear

00335: if(isset(self::$_coreClasses[$className]))

00336: include(YII_PATH.self::$_coreClasses[$className]);

00337: else if(isset(self::$_classes[$className]))

00338: include(self::$_classes[$className]);

00339: else

00340: {

00341: include($className.’.php’);

00342: return class_exists($className,false) || interface_exists($className,false);

00343: }

00344: return true;

00345: }

00346:

00347: /**

00348: * Writes a trace message.

00349: * This method will only log a message when the application is in debug mode.

00350: * @param string message to be logged

00351: * @param string category of the message

00352: * @see log

00353: */

Stack Trace

#0 /var/www/yii-1.1.4.r2429/framework/YiiBase.php(341): autoload()

#1 unknown(0): autoload()

#2 unknown(0): spl_autoload_call()

#3 /var/www/testdrive/protected/vendor/FPDF/fpdf153/fpdf.php(12): class_exists()

#4 /var/www/testdrive/protected/components/Controller.php(25): require_once()

#5 /var/www/yii-1.1.4.r2429/framework/web/CWebApplication.php(323): UserController->init()

#6 /var/www/yii-1.1.4.r2429/framework/web/CWebApplication.php(121): CWebApplication->runController()

#7 /var/www/yii-1.1.4.r2429/framework/base/CApplication.php(135): CWebApplication->processRequest()

#8 /var/www/testdrive/index.php(13): CWebApplication->run()

Bueno, antes que nada solo recordarte que linux es case-sensitive y por lo que veo el error de yii va por ahi…

Utilizas fpdf.php en minusculas


require_once('fpdf.php');

Y el error muestra que usas en algun otro lugar FPDF.php en mayusculas


include(FPDF.php): failed to open stream: No such file or directory

Empieza probando donde estan esas diferencias…

Ya te lo ha respondido Jack, en Windows el hecho de que llames a Index.php o index.php da igual, pero en Linux no… tienes que tener mucho cuidado con los nombres de carpetas y documentos.

En el caso de que utilices mucho esas clases a lo largo de tu aplicacion te recomiendo que las importes de otra forma. Un ejemplo seria a traves de config/main.php

Un saludo

Bueno ya me di cuenta que en linux tenia que poner el archivo fpdf.php con la primera letra en mayuscula por lo menos para que no me diera el error, pero ahora tengo otro problema de inclusion, el problema es que descargue la libreria (PHPExcel 1.7.4) de http://phpexcel.codeplex.com/releases/view/26478, entonces la copio dentro de mi carpeta vendor y en la clase Controller.php que esta en la carpeta components pongo esto.

Yii::import(‘application.vendor.PHPExcel.Classes.*’);

require_once(‘PHPExcel.php’);

y me da error, y no se porque yo pruebo la libreria directamente, es decir en mi navegador voy directamente a ella http://localhost/testdrive/protected/vendor/PHPExcel/Tests y pruebo los ejemplos de muestra y me corren perfectamente,

PHP Error

Description

include(PHPExcel_Shared_ZipStreamWrapper.php): failed to open stream: No such file or directory

Source File

/var/www/yii-1.1.4.r2429/framework/YiiBase.php(341)

00329: * @param string class name

00330: * @return boolean whether the class has been loaded successfully

00331: */

00332: public static function autoload($className)

00333: {

00334: // use include so that the error PHP file may appear

00335: if(isset(self::$_coreClasses[$className]))

00336: include(YII_PATH.self::$_coreClasses[$className]);

00337: else if(isset(self::$_classes[$className]))

00338: include(self::$_classes[$className]);

00339: else

00340: {

00341: include($className.’.php’);

00342: return class_exists($className,false) || interface_exists($className,false);

00343: }

00344: return true;

00345: }

00346:

00347: /**

00348: * Writes a trace message.

00349: * This method will only log a message when the application is in debug mode.

00350: * @param string message to be logged

00351: * @param string category of the message

00352: * @see log

00353: */

Stack Trace

#0 /var/www/yii-1.1.4.r2429/framework/YiiBase.php(341): autoload()

#1 unknown(0): autoload()

#2 /var/www/testdrive/protected/vendor/PHPExcel/Classes/PHPExcel.php(34): spl_autoload_call()

#3 /var/www/testdrive/protected/components/Controller.php(58): require_once()

#4 /var/www/yii-1.1.4.r2429/framework/web/CWebApplication.php(323): SiteController->init()

#5 /var/www/yii-1.1.4.r2429/framework/web/CWebApplication.php(121): CWebApplication->runController()

#6 /var/www/yii-1.1.4.r2429/framework/base/CApplication.php(135): CWebApplication->processRequest()

#7 /var/www/testdrive/index.php(13): CWebApplication->run()

chequea y mira como carga las classes PHPExcel, a qué dirección se refiere para cargar el resto de sus clases…

#2 /var/www/testdrive/protected/vendor/PHPExcel/Classes/PHPExcel.php(34): spl_autoload_call()

A ver realmente si la libreria sin el yii trabaja bien, no entiendo porque al incluirsela al yii no funciona, no obstante estuve mirando el codigo de PHPExcel y ellos para hacer las inclusiones utilizan




class PHPExcel_Autoloader

{

	public static function Register() {

               	return spl_autoload_register(array('PHPExcel_Autoloader', 'Load'));

	}	//	function Register()




	public static function Load($pObjectName){

                if ((class_exists($pObjectName)) || (strpos($pObjectName, 'PHPExcel') === False)) {

			return false;

		}


		$pObjectFilePath =	PHPEXCEL_ROOT.

							str_replace('_',DIRECTORY_SEPARATOR,$pObjectName).

							'.php';

                

             	if ((file_exists($pObjectFilePath) === false) || (is_readable($pObjectFilePath) === false)) {

			return false;

		}


		require($pObjectFilePath);

            }	//	function Load()


}

[size="4"][size="3"]Y en el archivo principal es decir PHPExcel.php ponen[/size][/size]


if (!defined('PHPEXCEL_ROOT')) {

	define('PHPEXCEL_ROOT', dirname(__FILE__) . '/');

	require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');

        PHPExcel_Autoloader::Register();

        PHPExcel_Shared_ZipStreamWrapper::register();

	// check mbstring.func_overload

	if (ini_get('mbstring.func_overload') & 2) {

		throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).');

	}

}

Realmente no logro entender mucho su codigo pero empeze hacer print_r a las variable $pObjectFilePath y coje bien los otros archivos cuando corro la libreria sola

Tus problemas al parecer son ocasionados por los path’s que seguramente no estan bien direccionados…

Yo te recomendaria imprimir cada incusion de archivos

Si ves esta linea


require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');

Prueba haciendo


echo PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php';

Dices que ya probaste haciendo print del $pObjectFilePath, pero con la aplicacion sola… trata de hacerlo cuando Yii carga la libreria… ya para empezar a descartar motivos

Yo realmente pienso que el programador no tiene porque estar preocupandose por esos problemas de inclusion, ademas es que todavia no entiendo si yo incluyo en el yii el unico archivo que hace falta para correr un ejemplo que es PHPExcel.php y me pincha con la biblioteca sola porque no con el yii. No obstante probe y al final nada las variables que puedo imprimir con la libreria sola con el yii no las puedo imprimir, por favor alguien que pruebe a ver si puede incluirle PHPExcel al yii y postear como, descargar PHPExcel no se lleva nada, http://phpexcel.codeplex.com/ de veras que me hace falta.

La libreria de phpexcel utiliza algo que creo que se le llama "lazy loading" y no estoy seguro de si el framework pueda manejar las clases cargadas mediante esa fx. No me pondre a revisar que esta bien o que esta mal entre el framework y la libreria… aunque me parece que algunos metodos de la libreria no ha seguido una denotacion de codigo estandar…

Por ahi en los errores que posteaste veo que se hace un llamado a la clase


include(PHPExcel_Shared_ZipStreamWrapper.php)

Y estoy casi seguro de que el nombre de esa clase es otro, Yii por omision carga archivos cuyo nombre de la clase es el mismo nombre del archivo… ese puede ser otra razon por la cual tengas problemas al cargar la libreria.

De todas maneras si no funciona y si el "lazy loading" no va con yii… siempre puedes crear una extension que simplemente es un wrapper de la clase original implementando una carga de archivos mas sencilla.

Bueno trate de hacer una extencion guiandome por la extencion de TCPDF: ETcPdf.php que descargue del sitio de yii,entonces dentro de la carpeta extensions de mi aplicacion puse una carpeta de nombre PHPExcel y dentro de ella tengo la clase es decir el wrapper que le llame EPHPExcel.php y la libreria PHPExcel que es una carpeta con ese mismo nombre

[size="4"]archivo[/size] [size="4"]EPHPExcel.php[/size]


<?php

require_once(dirname(__FILE__).'/PHPExcel/Classes/PHPExcel.php');


class EPHPExcel

{

   private $myPHPExcel = null;	

   public function __construct()

    {

		$this->myPHPExcel = new PHPExcel();

	}  	

}

y en mi clase controladora en la vista del reporte puse el codigo


$excel = Yii::createComponent('application.extensions.PHPExcel.EPHPExcel');

y bueno el mismo error de siempre

PHP Error

Description

include(PHPExcel_Shared_ZipStreamWrapper.php): failed to open stream: No such file or directory

Source File

/var/www/yii-1.1.4.r2429/framework/YiiBase.php(341)

00329: * @param string class name

00330: * @return boolean whether the class has been loaded successfully

00331: */

00332: public static function autoload($className)

00333: {

00334: // use include so that the error PHP file may appear

00335: if(isset(self::$_coreClasses[$className]))

00336: include(YII_PATH.self::$_coreClasses[$className]);

00337: else if(isset(self::$_classes[$className]))

00338: include(self::$_classes[$className]);

00339: else

00340: {

00341: include($className.’.php’);

00342: return class_exists($className,false) || interface_exists($className,false);

00343: }

00344: return true;

00345: }

00346:

00347: /**

00348: * Writes a trace message.

00349: * This method will only log a message when the application is in debug mode.

00350: * @param string message to be logged

00351: * @param string category of the message

00352: * @see log

00353: */

Stack Trace

#0 /var/www/yii-1.1.4.r2429/framework/YiiBase.php(341): autoload()

#1 unknown(0): autoload()

#2 /var/www/testdrive/protected/extensions/PHPExcel/PHPExcel/Classes/PHPExcel.php(34): spl_autoload_call()

#3 /var/www/testdrive/protected/extensions/PHPExcel/EPHPExcel.php(2): require_once()

#4 /var/www/yii-1.1.4.r2429/framework/YiiBase.php(258): require()

#5 /var/www/yii-1.1.4.r2429/framework/YiiBase.php(184): import()

#6 /var/www/testdrive/protected/controllers/UserController.php(174): createComponent()

#7 /var/www/yii-1.1.4.r2429/framework/web/actions/CInlineAction.php(50): UserController->actionReporteExcel()

#8 /var/www/yii-1.1.4.r2429/framework/web/CController.php(300): CInlineAction->run()

#9 /var/www/yii-1.1.4.r2429/framework/web/filters/CFilterChain.php(133): UserController->runAction()

#10 /var/www/yii-1.1.4.r2429/framework/web/filters/CFilter.php(41): CFilterChain->run()

#11 /var/www/yii-1.1.4.r2429/framework/web/CController.php(1049): CAccessControlFilter->filter()

#12 /var/www/yii-1.1.4.r2429/framework/web/filters/CInlineFilter.php(59): UserController->filterAccessControl()

#13 /var/www/yii-1.1.4.r2429/framework/web/filters/CFilterChain.php(130): CInlineFilter->filter()

#14 /var/www/yii-1.1.4.r2429/framework/web/CController.php(283): CFilterChain->run()

#15 /var/www/yii-1.1.4.r2429/framework/web/CController.php(257): UserController->runActionWithFilters()

#16 /var/www/yii-1.1.4.r2429/framework/web/CWebApplication.php(324): UserController->run()

#17 /var/www/yii-1.1.4.r2429/framework/web/CWebApplication.php(121): CWebApplication->runController()

#18 /var/www/yii-1.1.4.r2429/framework/base/CApplication.php(135): CWebApplication->processRequest()

#19 /var/www/testdrive/index.php(13): CWebApplication->run()

creo que el problema esta en la funcion spl_autoload_register.

Voy hacer una prueba y te comento…

Estuve jugando con esta libreria y el framework y evidentemente si hay un problema y esta relacionado con la carga de archivos… quienes desarrollaron PHPExcel no titularon los archivos de la misma manera que sus clases (reglas basicas).

El error que aparece de

include(PHPExcel_Shared_ZipStreamWrapper.php): failed to open stream: No such file or directory

es porque no hay un archivo llamado ‘PHPExcel_Shared_ZipStreamWrapper.php’ sino una clase llamada como tal… el archivo que contiene esta clase tiene otro nombre y se llama ZipStreamWrapper.php

Aqui es donde empiezan los problemas… ya que hay muchos archivos asi…

Ahora, yii en su clase base YiiBase.php genera el error porque no esta accediendo correctamente a la ruta donde se encuentra el archivo de clase. Aqui no se deque manera forzar a yii a decirle que recorra todo un directorio en busca de esas clases para que se puedan crear objetos y acceder a sus métodos.

De todas maneras intente incluir todos los archivos que se usan en la libreria de manera manual ya que a diferencia de spl_autoload_register este los carga dinamicamente… y funciono solo que no es una manera muy elegante de hacer funcionar la libreria con el framework.

Bueno pues tenemos un problema con esta libreria amigo mio… Y tenemos que hackear un poquito el codigo… aquí te expongo la solución:

  1. primero cuando lo pongas en tu carpeta, debes confirmar que puedas tener acceso a ella. La carpeta por defecto está sin acceso!

  2. como yo pensaba tenemos un problema con el autoload aplicado en las librerias. Los nombres de las classes son en realidad definiciones del path a cargar:

$pObjectFilePath = PHPEXCEL_ROOT.str_replace(’_’,DIRECTORY_SEPARATOR,$pObjectName).’.php’;

Como puedes comprobar la clase PHPExcel_ no existe, PHPExcel es en realidad la carpeta. Por lo tanto, aquí la solucion puesto que Yii solo carga los nombres en si:





//

// recogemos el vinculo de la direccion de la clase PHPExcel

//

$phpExcelPath = Yii::getPathOfAlias('ext.phpexcel.Classes');


//

// vamos a desactivar la forma en la que Yii carga las clases

spl_autoload_unregister(array('YiiBase','autoload'));


        

// 

// Cuando PHPExcel es incluido, registra su propio autoload

include($phpExcelPath . DIRECTORY_SEPARATOR . 'PHPExcel.php');


// AHORA HACEMOS LO QUE NOS DE LA GANA CON PHPEXCEL

// ESTE ES EN REALIDAD EL CODIGO DE UNO DE SUS EJEMPLOS

// CREAR UN PDF


// Create new PHPExcel object

$objPHPExcel = new PHPExcel();


// Set properties

$objPHPExcel->getProperties()->setCreator("Maarten Balliauw")

							 ->setLastModifiedBy("Maarten Balliauw")

							 ->setTitle("PDF Test Document")

							 ->setSubject("PDF Test Document")

							 ->setDescription("Test document for PDF, generated using PHP classes.")

							 ->setKeywords("pdf php")

							 ->setCategory("Test result file");




// Add some data

$objPHPExcel->setActiveSheetIndex(0)

            ->setCellValue('A1', 'Hello')

            ->setCellValue('B2', 'world!')

            ->setCellValue('C1', 'Hello')

            ->setCellValue('D2', 'world!');


// Miscellaneous glyphs, UTF-8

$objPHPExcel->setActiveSheetIndex(0)

            ->setCellValue('A4', 'Miscellaneous glyphs')

            ->setCellValue('A5', 'éàèùâêîôûëïüÿäöüç');


// Rename sheet

$objPHPExcel->getActiveSheet()->setTitle('Simple');




// Set active sheet index to the first sheet, so Excel opens this as the first sheet

$objPHPExcel->setActiveSheetIndex(0);




// Redirect output to a client’s web browser (Excel2007)

header('Content-Type: application/pdf');

header('Content-Disposition: attachment;filename="01simple.pdf"');

header('Cache-Control: max-age=0');


$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'PDF');

$objWriter->save('php://output');


// HEMOS TERMINADO?

Yii::app()->end();


// DEVOLVEMOS EL PODER A YII

spl_autoload_register(array('YiiBase','autoload'));



Como comprobaras esto funciona… es la unica forma (a no ser que haya otra de implementar un diferente autoload)

De esta forma te funcionara de maravilla…

Un saludo my friend

De hecho me ha gustado tanto jugar con esto que voy a escribir un artículo en el Wiki y en mi blog acerca de esta librería…

Un abrazo

Excelente post… :D

Bueno Antonio muchas gracias, me haz quitado un buen dolor de cabezas jejeje, donde se le pone al tema como resuelto?

De nada hombre… para poner el tema como resuelto lo único que has de hacer es ‘editar’ tu primer post, y luego darle al boton ‘Full Editor’, ahí podrás cambiar el título.

Un saludo

Muchas Gracias… aun a este tiempo me sirvio de mucho sus respuestas!!!