I need to use PHPExcel with a Symfony2 project. Anyone know how to set up the project correctly to use the library? Should i put it in the vendor directory? What should be changed in the configuration files etc?
Actually, to do it right you need to follow next steps:
Edit your deps file and add dependency from the PHPExcel
[PHPExcel]
git=http://github.com/PHPOffice/PHPExcel.git
target=/phpexcel
version=origin/master
Run php bin/vendors install in order to install all missing dependencies (PHPExcel in our case)
Update prefixes section in app/autoload.php:
$loader->registerPrefixes(array(
// ...
'PHPExcel' => __DIR__.'/../vendor/phpexcel/Classes',
));
Done. Now, you can use it in your bundle's controller (code based on PHPExcel example from Tests/01simple-download-xls.php):
<?php
namespace Demo\MyBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use PHPExcel;
use PHPExcel_IOFactory;
class DemoController extends Controller
{
public function demoAction()
{
$response = new Response();
// Create new PHPExcel object
$objPHPExcel = new PHPExcel();
// Set document properties
$objPHPExcel->getProperties()->setCreator("Me")
->setLastModifiedBy("Someone")
->setTitle("My first demo")
->setSubject("Demo Document");
// Add some data
$objPHPExcel->setActiveSheetIndex(0)
->setCellValue('A1', 'Hello')
->setCellValue('B2', 'world!')
->setCellValue('C1', 'Hello')
->setCellValue('D2', 'world!');
// Set active sheet index to the first sheet
$objPHPExcel->setActiveSheetIndex(0);
// Redirect output to a client’s web browser (Excel5)
$response->headers->set('Content-Type', 'application/vnd.ms-excel');
$response->headers->set('Content-Disposition', 'attachment;filename="demo.xls"');
$response->headers->set('Cache-Control', 'max-age=0');
$response->prepare();
$response->sendHeaders();
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
$objWriter->save('php://output');
exit();
}
}
Copy the library to your vendors directory.
Configure autoloader in your bootstrap file:
$loader->registerPrefixes(array(
// Swift, Twig etc.
'PHPExcel' => __DIR__ . '/../vendor/phpexcel/lib/PHPExcel'
));
That's all.
actually the best solution is to use https://github.com/liuggio/ExcelBundle.
I tried to use #Crozin's solution but I was still getting an error about IOFactory::createWriter.
Hope this helps,
Simone
As of Symfony 2.3, you can now do this:
...
"require": {
...
"phpoffice/phpexcel": "dev-master"
...
},
...
Then just run composer update and dependencies will resolve automatically.
Or you can do composer require phpoffice/phpexcel:dev-master if you don't want to mess with the composer.json file.
If you are using composer to manage your project, you can just change the composer.json file:
"autoload": {
"psr-4": {
"": "src/",
"": "vendor/phpoffice/phpexcel/Classes/"
},
"classmap": [
"app/AppKernel.php",
"app/AppCache.php"
]
},
Then add
use PHPExcel;
use PHPExcel_IOFactory;
to your controller file, and you can use the PHPExcel like this:
$objPHPExcel = new PHPExcel();
Hope it helps.
With composer (since Symfony2.1) it's really easy, you only have to modify the composer.json.
You don't need to register the namespace anymore!
Only two things, to notice:
refer to github tags, I only found a soltion with the package type
when changing something in the composer.json related to the class autoloading stuff, you have to remove the whole directory in the vendor dir
Here is the related link: use PHPExcel with composer and Symfony2.2
Related
I'm having significant amount of troubles trying figure out how to install and use DOMPDF with Composer and Symfony. It is a project written a few years ago and I am completely new to Composer, Symfony and DOMPDF...somebody else told me we were using Composer and Symfony.
I've installed DOMPDF using the puTTy command line interface by:
1. going to the folder where my composer.json is (vendor)
2. running the command "Install dompdf/dompdf" It completed successfully with no errors.
3. Then running the command composer "require dompdf/dompdf" which also completed successfully with no errors.
Then I get lost/confused...
I see instructions that say to edit composer.json with :
{
"require": {
"squizlabs/php_codesniffer": "2.0.*",
}
So here is the new contents of composer.json
{
"require": {
"spipu/html2pdf": "^5.0",
"dompdf/dompdf": "^0.8.1"
}
I've tried using DOMPDF by putting the following line in my PHP code and all I get is a blank page
use Dompdf\Dompdf;
There is also an autoload.php which looks like this:
//autoload.php #generated by Composer
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit********************************::getLoader();
Following the rabbit hole, autoload_real.php looks like this:
// autoload_real.php #generated by Composer
class ComposerAutoloaderInit987ec9019a1b2f978bf00ce76684ede0
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit987ec9019a1b2f978bf00ce76684ede0', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit987ec9019a1b2f978bf00ce76684ede0', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit987ec9019a1b2f978bf00ce76684ede0::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
$loader->register(true);
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInit987ec9019a1b2f978bf00ce76684ede0::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire987ec9019a1b2f978bf00ce76684ede0($fileIdentifier, $file);
}
return $loader;
}}function composerRequire987ec9019a1b2f978bf00ce76684ede0($fileIdentifier, $file){if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file;$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;}}
Additionally, I have 14 folders in the vendor file, which I assume are all packages used with Composer, but I don't see them being required in the composer.json file, and, after installing DOMPDF, I don't see a vendor folder for it. I'd like to remove them, but I don't know what is and is not being used.
I've read the "getting started guides" and I still don't know what I've done wrong.
I'm sure I will have a thousand more questions...thank you for your patience.
a) your composer.json file should be in the root of your project directory and not in the vendor directory.
b) just typing the command
composer require dompdf/dompdf
in your project directory should be enough to install the libraries in the vendor directory AND to add the line
"dompdf/dompdf": "^0.8.1"
in your composer.json.
c) Follow instructions on https://github.com/dompdf/dompdf how to use dompdf.
d) In general when working with composer you have to include the vendor/autoload.php file but in the Symfony framework that will already happen in the app/autoload.php.
require 'vendor/autoload.php';
e) dompdf does use namespaces. Little example:
require "../vendor/autoload.php"; // change path if you need to
use Dompdf\Dompdf;
// instantiate and use the dompdf class
$dompdf = new Dompdf();
$dompdf->loadHtml('hello world');
// (Optional) Setup the paper size and orientation
$dompdf->setPaper('A4', 'landscape');
// Render the HTML as PDF
$dompdf->render();
// Output the generated PDF to Browser
$dompdf->stream();
f) Lot of packages that can be installed with composer use other packages too. If you take a look at the composer.json from dompdf you will see that it requires some other packages which composer will automaticly install for you.
[edit]
Your composer.json is in the root directory of your project. Same for your vendor directory. In your vendor directory there will be a composer directory, that is normal. But execute any commands from your root directory. structure:
- [project root] (execute commands here)
|
|- composer.json
|- [vendor]
|
|- [composer]
If you got stuck just delete the whole vendor directory and composer.json file and again use the command
composer require dompdf/dompdf
I have a new bundle MyBundle under
src/MyVendor/Bundle/MyBundle/
and in the default controller I wish to use class MyClass which resides in namespace called MyVendor\MyComponent
which is located under src/MyVendor/Component/MyComponent/src/MyVendor/MyComponent/MyClass.php
I've tried to do
use Symfony\Component\ClassLoader\UniversalClassLoader;
$myLoader = new UniversalClassLoader();
$myLoader->registerNamespace(
'MyVendor\\MyComponent\\',
__DIR__.'/../src/MyVendor/Component/MyComponent/src'
);
in app/autoload.php but I'm still getting the ClassNotFoundException error.
Either I'm missing something subtle, or my idea is completely wrong (wrong psr-0 dir structure) or should this be done solely via composer's autoload e.g.
"autoload": {
"psr-0": {
"MyVendor\\MyComponent\\":
"src/MyVendor/Component/MyComponent/src"
}
}
and
composer dump-autoload --optimize
In either case, I'd appreciate any help.
thank you
OK, I think I've figured it out:
registerNamespace should not have trailing \\ in the namespace
I need to add $myLoad->register();
so the whole thing looks like
use Symfony\Component\ClassLoader\UniversalClassLoader;
$myLoader = new UniversalClassLoader();
$myLoader->registerNamespace(
'MyVendor\\MyComponent',
__DIR__.'/../src/MyVendor/Component/MyComponent/src'
);
$myLoader->register();
I'd still like to see how to do this with the composer and dump-autoload
I want to use some of the builtin symfony2 extensions(e.g:humanize,yaml_dump) for twig for a website not developed in symfony but using a twig engine.how can I do that?
The symfony/twig-bridge package provides the symfony-specific twig extensions.
These include i.e. the YamlExtension that provides the yaml_dump filter and the FormExtension that provides the humanize filter.
The extensions can be found in the Extension folder.
I strongly advise you to install the package via composer to get the package's dependencies automatically.
composer require symfony/twig-bridge:~2.3
Further composer will automatically register the classes in the autoloader (vendor/autoload.php) for you.
Now you just need to add the extensions to twig as described in the documentation.
$twig->addExtension(new \Symfony\Bridge\Twig\Extension\YamlExtension());
// ...
A complete example, with an extension class and a quick extension (a new filter) :
<?php
require_once("vendor/autoload.php");
$loader = new Twig_Loader_String();
$twig = new Twig_Environment($loader);
// here we add the extension class (taken from #nifr answer)
$twig->addExtension(new \Symfony\Bridge\Twig\Extension\YamlExtension());
// here we add a new filter quickly
$filter = new Twig_SimpleFilter('paragraph', function ($argument) {
return "<p>{$argument}</p>";
}, array('pre_escape' => 'html', 'is_safe' => array('html')));
$twig->addFilter($filter);
// demo
echo $twig->render('{{ "hello" | paragraph }}');
This post is dedicated to the easy solution that seems to exist to add your own namespaces, the solution with the loader in app/autoload.php.
There is a lot of documentations talking about the magic methods like registerNamespace or registerPrefix.
The problem is that those methods exist for a UniversalClassLoader object.
I downloaded the Symfony standard edition 2.2, and the app/autoload.php looks more like that (pretty much the same with Symfony standard edition 2.1) :
use Doctrine\Common\Annotations\AnnotationRegistry;
$loader = require __DIR__.'/../vendor/autoload.php';
// intl
if (!function_exists('intl_get_error_code')) {
require_once __DIR__.'/../vendor/symfony/symfony/src/Symfony/Component/Locale/Resources/stubs/functions.php';
}
AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
return $loader;
the loader used in fact is the composer loader. The only method you could use is the 'add' method like this if you hope to add 'seculibs/collections' namespace for example:
$loader->add("seculibs\\collections", __DIR__.'/../vendor/seculibs/collections/');
But it does not seem to work : when I execute programm I have the same classNotFound for /seculibs/collections/xx.php
So I changed the autoload.php like that :
require_once ('/../vendor/symfony/symfony/src/Symfony/Component/ClassLoader/UniversalClassLoader.php');
use Doctrine\Common\Annotations\AnnotationRegistry;
use Symfony\Component\ClassLoader\UniversalClassLoader;
$loader = require __DIR__.'/../vendor/autoload.php';
$universalLoader = new UniversalClassLoader();
$universalLoader->registerNamespace("seculibs\\collections", __DIR__.'/../vendor/seculibs/collections/');
$universalLoader->register();
// intl
if (!function_exists('intl_get_error_code')) {
require_once __DIR__.'/../vendor/symfony/symfony/src/Symfony/Component/Locale/Resources/stubs/functions.php';
}
AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
return $loader;
Nothing...
But obviously it works for a lot of persons so.. what am I doing wrong ? Do they have some other Symfony version that would be found on secret websites ?
one of the classes is like that :
namespace seculibs\collections;
class LinkedMap {
private $items;
public function __construct() {
$this->items = array();
}
public function __destruct() {
unset($this->items);
}
....
$loader->add('seculibs\\collections',__DIR__ . '/../vendor');
new LinkedMap();
Assuming you have file: vendor/seculibs/collections/LinkedMap.php
Normally, you would have another level in your library. Something like:
vendor/MyStuff/seculibs/collections
And then the add line would point to vendor/MyStuff
You can add your own libraries to the composer.json autoload config, so even though they aren't loaded by composer, they will be in the generated autloader.
"autoload": {
"psr-0": {
"": "src/",
"MyLib_": "/home/sites/MyLib"
}
},
i followed this doc to install SonataMediaBundle but i got this error:
PHP Fatal error: Class 'Application\Sonata\MediaBundle\ApplicationSonataMediaBundle' not found in /var/www/znata.com/app/AppKernel.php on line 47
After using the sonata command t generate the app:
php app/console sonata:easy-extends:generate SonataMediaBundle
new directory was generated under:
apps/Application/Sonata/MediaBundle
everything was done but when i registred the generated application in my AppKernel.php i got that error.
public function registerbundles()
{
return array(
...
new Application\Sonata\MediaBundle\ApplicationSonataMediaBundle(),
...
);
}
Have you any idea how to fix this issue ?
By default project root directory is not in the autoload path, only "src" dir.
You can use
php app/console sonata:easy-extends:generate --dest=src SonataMediaBundle
to generate bundle in the src or simple copy it to the src.
After debug this problem, i found that the namspace Application is not registred.
In SF2.0, the documentation said that we should register this namespace like:
<?php
$loader->registerNamespaces(array(
...
'Application' => __DIR__,
'Imagine' => __DIR__.'/../vendor/imagine/lib',
'Gaufrette' => __DIR__.'/../vendor/gaufrette/src',
'Buzz' => __DIR__.'/../vendor/buzz/lib',
...
));
but in SF2.1 they did talked about this.
So i registred the namespace Application in autoload.php and it works fine.
so, the autoload.php look like this:
<?php
// file: app/autoload.php
use Doctrine\Common\Annotations\AnnotationRegistry;
$loader = require __DIR__.'/../vendor/autoload.php';
//custom for Application
$loader->add("Application", __DIR__);
// intl
if (!function_exists('intl_get_error_code')) {
require_once __DIR__.'/../vendor/symfony/symfony/src/Symfony/Component/Locale/Resources/stubs/functions.php';
$loader->add('', __DIR__.'/../vendor/symfony/symfony/src/Symfony/Component/Locale/Resources/stubs');
}
AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
return $loader;
With this new config everything is fine.But in SF2.0, they talked also about "Imagine", "Guffrette" and "Buzz" namespaces. So perhapes, when using them, we should register them also like Application namespace.
I hope that this helps you.
Using composer I did this in composer.json:
"autoload": {
"psr-0": {
"": "src/",
"Application": "app/"
}
},
I added the mapping "Application": "app/".
And then run
composer update
This generated extra autoloading needed.
inside your composer.json file, have:
"autoload": {
"psr-4": {
"AppBundle\\": "src/AppBundle",
"Application\\": "src/Application"
},
}
do a simple:
composer dump-autoload
to re-generate the autoload files.
new Application\Sonata\MediaBundle\MediaBundle(),
or
new Application\Sonata\MediaBundle\SonataMediaBundle(),
As skonsoft mentioned, you need to load the namespaces in autoload.php. I had the same issue with FOQ.Elastica and resolved it by adding the following.
$loader->add('FOQ', __DIR__.'/../vendor/bundles');
You can also use your app namespace prefix so the package falls under your namespace
bin/console sonata:easy-extends:generate --dest=src SonataMediaBundle --namespace_prefix=App