Loading vendor files

Published on March 26, 2008 and tagged with cakephp  tip  vendor

The traditional way to load files from the “vendors” folders — using the vendor() function — has been deprecated a while ago in the development branch (you get a warning if you use this function).

The new way is to use App::import(). To load a file named “example.php”, you have to use the following snippet:

App::import('Vendor', 'example');

Unfortunately, there’s a snag to it: it only works if the name is in lowercase, i.e. the following snippet won’t load the file “Example.php”:

App::import('Vendor', 'Example');

Instead you have to use:

App::import('Vendor', 'example', array('file' => 'Example.php'));

The second parameter can be any string except an empty string or null, but I don’t know what the meaning of this parameter is in this context…

The same also applies for folder names:

App::import('Vendor', 'example'.DS.'example'); // loads example/example.php
App::import('Vendor', 'example', array('file' => 'Example'.DS.'example.php')); // loads Example/example.php

It’s quite illogical, but according to some newly added tests it is supposed to work in this way…

24 comments baked

  • nao March 26, 2008 at 15:20

    “CakePHP: the rapid development php framework.”

    lol

  • nao March 26, 2008 at 15:21

    “CakePHP: the rapid development php framework.”

    App::import(‘Vendor’, ‘example’, array(‘file’ => ‘Example’.DS.’example.php’)); // loads Example/example.php

    lol

  • Brendon Kozlowski March 26, 2008 at 16:43

    nao, you apparently haven’t seen how the Zend Framework imports files into its bootstrap. It’s about the same as Cake’s long example above (last I’ve seen it anyhow, they may have updated it). Cake truly does make development much more rapid, regardless of some nuances that Dan will tell us about (so that we do not run into the same problems that he does).

  • cakebaker March 27, 2008 at 08:30

    @nao, Brendon: Thanks for your comments!

    @nao: *g*

    @Brendon: I think the problem is not necessarily that you have to write more, the problem is that the current solution is inconsistent. And that’s what slows you down, not the typing of some more characters.

  • Nik Chankov March 27, 2008 at 11:24

    Daniel, thanks for the info. Hope the development team correct this. I don’t experience problems with this but I really wont like to see app crashing while I upgrade the framework.

  • luke March 27, 2008 at 13:26

    to be fair, I think you should include the offical trac mentions of this – it seems to point to a naming convention (dot syntax?) being implemented in this re-mixed vendor import code.

    https://trac.cakephp.org/changeset/6600

  • cakebaker March 27, 2008 at 19:52

    @Nik: Yes, I also hope it will get corrected, but I think it won’t happen as recently two respective tickets were closed and tests were added to verify this behavior…

    @luke: Yes, it is mentioned that the failing approaches don’t follow the naming conventions for file and directory names. But according to the manual there are no conventions for vendors ;-)

  • luke March 28, 2008 at 12:34

    ah, didnt know that… but doesnt that just mean it is a problem with the manual therefore ;)

  • blueballoon March 28, 2008 at 18:20

    What happend to the good old vendor inclusion function ?
    vendor(‘Example’);

    For cake 1.2 couldn’t it be made like this :
    App::import(‘Vendor’, array(‘file’ => ‘Example.php’));

  • Mark Story March 30, 2008 at 17:30

    this definitely makes vendor imports far more difficult to use than they used be. But looking at how App::import works. There isn’t a lot of room for adapting something simpler without having to rewrite the entire app:import. Another option is to always specify the 3rd parameter. That would at least keep your vendor imports looking clean and predictable.

  • cakebaker March 31, 2008 at 16:35

    @luke: The explanation in the manual makes sense to me :)

    @blueballoon: Personally I would prefer the same syntax as you could use with the vendor function:

    App::import('Vendor', array('Example1', 'Example2'));
    

    @Mark: Yes, specifying always the 3rd parameter is a possible option. Another option is to copy the code of the vendor() function and to create your own “vendor” function in bootstrap.php.

    But those are only workarounds, the main problem remains. I think it wouldn’t be that difficult to refactor App::import() accordingly. In the simplest case you could check whether the type is “Vendor” and then call a method which handles the import of vendor files.

  • Migrating from CakePHP 1.2beta to RC1 - cakebaker June 05, 2008 at 19:59

    [...] which don’t follow the cake conventions have to be treated differently (see also Loading vendor files). [...]

  • Luizz » Blog Archive » Vendors e App::import nella nuova release June 25, 2008 at 11:23

    [...] non è uno di quelli segnalati da Cakebaker nei suoi post Migrating from CakePHP 1.2beta to RC1 e Loading vendor files, bensì legato alla logica di funzionamento di questi [...]

  • Alejandro García December 09, 2008 at 19:39

    The manual has documented a bit more the App::import method. If the class you’re importing has the same filename (example: class Dog, file dog.php) then you use: App::import(‘Vendors’, ‘dog’). If the class has a different filename or a filename with dots or file inside folder (example: class PHPMailer, file class.phpmailer.php inside phpmailer folder in vendors dir) then you use: App::import(‘Vendors’, ‘PHPMailer’, array(‘file’ => ‘phpmailer’.DS.’class.phpmailer.php’). Note that when you specify the filename, you must include the file extension.
    Seems to work this way because everything gets automagically configured, class name and file name.
    Cheers.

  • cakebaker December 10, 2008 at 18:09

    @Alejandro: Thanks for your comment! Yes, in principle you can say that the short form can be used if you follow the cake naming conventions, and in the other cases you have to use the array with the “file” key.

  • Anand March 16, 2009 at 07:09

    helped me a lot.Thanks

  • cakebaker March 17, 2009 at 17:02

    @Anand: I’m glad this article was helpful for you!

  • Justin March 27, 2009 at 18:16

    Thanks for this, the DOCS never mentioned anything about it needing to be lower case. Was pulling my hair out until finding this.

  • cakebaker March 31, 2009 at 16:55

    @Justin: You are welcome!

  • francis June 16, 2009 at 09:53

    hi there, is it possible to import just the folder name and it automatically import all the files that the folder contains?

  • cakebaker June 16, 2009 at 16:37

    @francis: Thanks for your comment!

    As far as I know App::import() doesn’t provide such a feature. And so you have to do it manually by looping over the file names of the respective folder and calling App::import() for each file. To make this functionality reusable, you might want to put it into its own method.

    Hope that helps!

  • francis June 17, 2009 at 03:14

    i thought so.. thanks for the suggestion.. i did it and i think it worked fine.. ill post the code here.. maybe it’ll be helpful to others too.. :)

    // Recursively adds a whole folder as a vendor.
    function importVendorFolder($dir)
    {
    	//store ".php" files in current directory
    	$files = Configure::__list($dir, ".php");
    	foreach($files as $file)
    	{
    		//import php file.
    		app::import("Vendor", $file);
    	}
    	//store folders in current directory
    	$folders = Configure::__list($dir);
    	foreach($folders as $folder)
    	{
    		read_my_dir("{$dir}/{$folder}");
    	}	
    }

    in here i used the built in cake function “Configure::__list” to check if the file is a folder or a file..

    and to call it:

    //parameter is path to the vendor folder.
    importVendorFolder("../vendors/lib");

    hope this will be useful to you guys.. :D

  • francis June 17, 2009 at 05:24

    correction..

    //store folders in current directory
    	$folders = Configure::__list($dir);
    	foreach($folders as $folder)
    	{
    		read_my_dir("{$dir}/{$folder}");
    	}

    “read_my_dir” was supposed to be “importVendorFolder”

  • cakebaker June 17, 2009 at 16:52

    @francis: Thanks for sharing your solution!

    An idea to simplify your function is to use CakePHP’s Folder::findRecursive() to get the file names (as a side effect you would also get rid of using the “private” method Configure::__list()).

Bake a comment




(for code please use <code>...</code> [no escaping necessary])

© daniel hofstetter. Licensed under a Creative Commons License