<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>cakebaker &#187; vendor</title>
	<atom:link href="http://cakebaker.42dh.com/tags/vendor/feed/" rel="self" type="application/rss+xml" />
	<link>http://cakebaker.42dh.com</link>
	<description>baking cakes with CakePHP</description>
	<lastBuildDate>Tue, 20 Dec 2011 15:29:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Reusable code and the import of vendors files</title>
		<link>http://cakebaker.42dh.com/2009/08/25/reusable-code-and-the-import-of-vendors-files/</link>
		<comments>http://cakebaker.42dh.com/2009/08/25/reusable-code-and-the-import-of-vendors-files/#comments</comments>
		<pubDate>Tue, 25 Aug 2009 15:23:23 +0000</pubDate>
		<dc:creator>cakebaker</dc:creator>
				<category><![CDATA[cakephp]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[vendor]]></category>

		<guid isPermaLink="false">http://cakebaker.42dh.com/?p=1239</guid>
		<description><![CDATA[If you write reusable code with CakePHP (e.g. a component) you often forget (or at least I do) that the code could be used either in applications or in plugins. In most cases though, this doesn&#8217;t really matter, as your code will work fine in both &#8220;environments&#8221;. However, consider the following snippet: public function example() [...]]]></description>
			<content:encoded><![CDATA[<p>If you write reusable code with CakePHP (e.g. a component) you often forget (or at least I do) that the code could be used either in applications or in plugins. In most cases though, this doesn&#8217;t really matter, as your code will work fine in both &#8220;environments&#8221;. However, consider the following snippet:</p>
<pre>
<code>public function example() {
    App::import('Vendor', 'example', array('file' =&gt; 'Example.php'));
    $example = new Example();
    ...
}</code>
</pre>
<p>This snippet works fine if it is used in an application, but it will fail with a &#8220;Class not found&#8221; error if the snippet and the corresponding vendors file (&#8220;Example.php&#8221;) are put into a plugin. The reason for the failure is that you have to use the plugin name as a prefix when importing something from a plugin, even if you use App::import() from within the respective plugin:</p>
<pre>
<code>// test is the plugin name
App::import('Vendor', 'test.example', array('file' =&gt; 'Example.php'));</code>
</pre>
<p>The consequence of this behavior is that your code has to know in which &#8220;environment&#8221; it runs if you want to make it really reusable. An alternative is to &#8220;circumvent&#8221; the application &#8220;environment&#8221; and to distribute your code, and the required vendors files, as a plugin. </p>
<p>In the <a href="http://code.42dh.com/openid">OpenID component</a> I solved this problem by determining in which &#8220;vendors&#8221; directory the required library is. And if it is in the plugin&#8217;s &#8220;vendors&#8221; directory, I set an instance variable $importPrefix with the plugin name. This prefix is then used whenever a file is imported. </p>
<p>Here is the relevant code:</p>
<pre>
<code>class OpenidComponent extends Object {
    private $importPrefix = '';

    public function __construct() {
        parent::__construct();

        $pathToVendorsFolder = $this-&gt;getPathToVendorsFolderWithOpenIDLibrary();
		
        if ($pathToVendorsFolder == '') {
            exit('Unable to find the PHP OpenID library');
        }
		
        if ($this-&gt;isPathWithinPlugin($pathToVendorsFolder)) {
            $this-&gt;importPrefix = $this-&gt;getPluginName() . '.';
        }

        $this-&gt;importCoreFilesFromOpenIDLibrary();
    }

    private function getPathToVendorsFolderWithOpenIDLibrary() {
        $pathToVendorsFolder = '';
		
        if ($this-&gt;isPathWithinPlugin(__FILE__)) {
            $pluginName = $this-&gt;getPluginName();
			
            if (file_exists(APP.'plugins'.DS.$pluginName.DS.'vendors'.DS.'Auth')) {
                $pathToVendorsFolder = APP.'plugins'.DS.$pluginName.DS.'vendors'.DS;
            }
        }

        if ($pathToVendorsFolder == '') {
            if (file_exists(APP.'vendors'.DS.'Auth')) {
                $pathToVendorsFolder = APP.'vendors'.DS;
            } elseif (file_exists(VENDORS.'Auth')) {
                $pathToVendorsFolder = VENDORS;
            }
        }
		
        return $pathToVendorsFolder;
    }
	
    private function getPluginName() {
        $result = array();
        if (preg_match('#'.DS.'plugins'.DS.'(.*)'.DS.'controllers#', __FILE__, $result)) { 
            return $result[1];
        }

        return false;
    }

    private function importCoreFilesFromOpenIDLibrary() {
        App::import('Vendor', $this-&gt;importPrefix.'consumer', array('file' =&gt; 'Auth'.DS.'OpenID'.DS.'Consumer.php'));
        App::import('Vendor', $this-&gt;importPrefix.'sreg', array('file' =&gt; 'Auth'.DS.'OpenID'.DS.'SReg.php'));
    }

    private function isPathWithinPlugin($path) {
        return strpos($path, DS.'plugins'.DS) ? true : false;
    }
}</code>
</pre>
<p>This code is meant to give you an idea of how it could be solved in that specific situation, and not as a solution you can copy 1:1&#8230;</p>
<p>Happy baking!</p>
]]></content:encoded>
			<wfw:commentRss>http://cakebaker.42dh.com/2009/08/25/reusable-code-and-the-import-of-vendors-files/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Auto-loading vendor files (or any other file)</title>
		<link>http://cakebaker.42dh.com/2008/11/28/auto-loading-vendor-files-or-any-other-file/</link>
		<comments>http://cakebaker.42dh.com/2008/11/28/auto-loading-vendor-files-or-any-other-file/#comments</comments>
		<pubDate>Fri, 28 Nov 2008 16:47:47 +0000</pubDate>
		<dc:creator>cakebaker</dc:creator>
				<category><![CDATA[cakephp]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[tip]]></category>
		<category><![CDATA[vendor]]></category>

		<guid isPermaLink="false">http://cakebaker.42dh.com/?p=979</guid>
		<description><![CDATA[If you use classes which do not fit into CakePHP&#8217;s structure (i.e. they are no components, helpers, etc.), you have to import those classes manually with App::import(&#8216;Vendor&#8217;, &#8216;ClassName&#8217;), at least if your classes are in the &#8220;vendors&#8221; folder. This means, every time you want to use such a class, you first have to import it [...]]]></description>
			<content:encoded><![CDATA[<p>If you use classes which do not fit into CakePHP&#8217;s structure (i.e. they are no components, helpers, etc.), you have to import those classes manually with App::import(&#8216;Vendor&#8217;, &#8216;ClassName&#8217;), at least if your classes are in the &#8220;vendors&#8221; folder. This means, every time you want to use such a class, you first have to import it before you can use it. And that&#8217;s a bit of a pain ;-)</p>
<p>Fortunately, PHP5 provides a solution for this &#8220;problem&#8221;: auto-loading. The explanation from the <a href="http://www.php.net/manual/en/language.oop5.autoload.php">manual</a>: &#8220;You may define an __autoload function which is automatically called in case you are trying to use a class/interface which hasn&#8217;t been defined yet. By calling this function the scripting engine is given a last chance to load the class before PHP fails with an error.&#8221;</p>
<p>In CakePHP a good place for this function is app/config/bootstrap.php. The function to auto-load vendor files looks like:</p>
<pre>
<code>function __autoload($className) {
    App::import('Vendor', $className);
}</code>
</pre>
<p>If you want to use a custom function or a method of a class, you simply have to register your auto-load implementation. The example from above realized with a static method looks like:</p>
<pre>
<code>class AutoLoader {
    public static function load($className) {
        App::import('Vendor', $className);
    }
}

spl_autoload_register(array('AutoLoader', 'load'));</code>
</pre>
<p>You can find more information about auto-loading in the PHP manual: <a href="http://www.php.net/manual/en/language.oop5.autoload.php">Autoloading objects</a> and <a href="http://www.php.net/manual/en/function.spl-autoload-register.php">spl_autoload_register</a>.</p>
<p>Happy baking!</p>
]]></content:encoded>
			<wfw:commentRss>http://cakebaker.42dh.com/2008/11/28/auto-loading-vendor-files-or-any-other-file/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Loading vendor files</title>
		<link>http://cakebaker.42dh.com/2008/03/26/loading-vendor-files/</link>
		<comments>http://cakebaker.42dh.com/2008/03/26/loading-vendor-files/#comments</comments>
		<pubDate>Wed, 26 Mar 2008 10:49:17 +0000</pubDate>
		<dc:creator>cakebaker</dc:creator>
				<category><![CDATA[cakephp]]></category>
		<category><![CDATA[tip]]></category>
		<category><![CDATA[vendor]]></category>

		<guid isPermaLink="false">http://cakebaker.42dh.com/2008/03/26/loading-vendor-files/</guid>
		<description><![CDATA[The traditional way to load files from the &#8220;vendors&#8221; folders &#8212; using the vendor() function &#8212; 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 &#8220;example.php&#8221;, you have to use the following snippet: [...]]]></description>
			<content:encoded><![CDATA[<p>The traditional way to load files from the &#8220;vendors&#8221; folders &#8212; using the vendor() function &#8212; has been deprecated a while ago in the development branch (you get a warning if you use this function). </p>
<p>The new way is to use App::import(). To load a file named &#8220;example.php&#8221;, you have to use the following snippet:</p>
<pre>
App::import('Vendor', 'example');
</pre>
<p>Unfortunately, there&#8217;s a snag to it: it only works if the name is in lowercase, i.e. the following snippet <strong>won&#8217;t load</strong> the file &#8220;Example.php&#8221;:</p>
<pre>
App::import('Vendor', 'Example');
</pre>
<p>Instead you have to use:</p>
<pre>
App::import('Vendor', 'example', array('file' =&gt; 'Example.php'));
</pre>
<p>The second parameter can be any string except an empty string or null, but I don&#8217;t know what the meaning of this parameter is in this context&#8230;</p>
<p>The same also applies for folder names:</p>
<pre>
App::import('Vendor', 'example'.DS.'example'); // loads example/example.php
App::import('Vendor', 'example', array('file' =&gt; 'Example'.DS.'example.php')); // loads Example/example.php
</pre>
<p>It&#8217;s quite illogical, but according to some <a href="https://trac.cakephp.org/changeset/6600">newly added tests</a> it is supposed to work in this way&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://cakebaker.42dh.com/2008/03/26/loading-vendor-files/feed/</wfw:commentRss>
		<slash:comments>30</slash:comments>
		</item>
	</channel>
</rss>

