extension/module is almost an application but it must be used within application. of course you can make application from extension and vise versa but you need extension.
When you have developed your extension, and are ready to test composer deploy/install/update then add it to your applications composer.json, but use a source map:
I wanted to point out, that you can mimic a Composer 3rd party library, locally. It does not need to be under version control, have live edits, and still works with Gii
For example, I want to create a new extension. I plan to put it on Github and Packagist so it can be installed easily via Composer. However, I donât want to commit my changes to my version control system (Git) in order for it to work. I donât want to have to run âcomposer updateâ after every change. I want to make a change and see it live instantly. And this is TOTALLY POSSIBLE!
This is the best way to develop new extensions for Yii!
First, create a new directory for your new extension in your htdocs, then init Composer:
mkdir yii2-myextension
cd yii2-myextension
composer init
Follow the interactive wizard. Now, open "composer.json", either with your editor, vim, or nano.
Here is an example of mine (I removed keywords, description, ect because they arenât important. You should have them, but my description isnât relevant to you.
Name: The name is <vendor>/yii2-<extension>. I use my GitHub username (WadeShuler), all lowercase and no spaces (wadeshuler). It would help if you create a GitHub account first, and also create a Packagist account. Packagist uses your GitHub username Keep those 3 in sync and you will reduce issues. You should also prefix your extensions with âyii2-â. It is a Yii standard practice, helps others know it is for Yii2 and not Yii1.
Type: You must use "yii2-extension" for the type, this tells Yii to load it into your extensions file for internal use. Click here to read more.
Min Stability: it is important to use "dev" here during testing. We have no version control (yet) and we will force our main Yii2 composer.json to accept a "dev" dependency even though Yii2 requires stable, by using "@dev" for the repo (shown later).
Autoload: I use PSR-4 and you probably should too. Most Yii2 packages I have encountered are PRS4. I feel it is better an easier, I donât just follow suit to be a sheep Notice how it has my vendor name, âwadeshulerâ then double backslashes. These are important. If you donât know about the double backslashes, then read here. It then has the name of my extension. However, there is no âyii2â in it. This is actually the namespace we are going to use, we can call it whatever we want, so we can omit the âyii2-â to be cleaner and easier to write later. This is the namespace that defines where your extension is located. Here in Composer, we are saying âwadeshuler/whateveriwantâ is going to be our namespace, and it is located ââ <-- root dir of the loaded extension. You could do âwadeshuler\\myextension\\â: â/srcâ <-- in your extensions src directory if you want to put everything in a âsrcâ dir and just have your âREADMEâ, âLICENSEâ and âcomposer.jsonâ in your extensions root dir.
Ok, so here, your Yii2 extension is ready for use in Composer. We will add files later, using Gii. Right now, there is nothing but âcomposer.jsonâ in our directory. Gii will whip up the namespace, Module class, BaseController, all that for us
Open your Yii2 appâs âcomposer.jsonâ file, lets add our extension.
You probably donât have a ârepositoriesâ section, so add it. Notice we use âpathâ for the type, this does not require any version control For the url, I use the full path to the extension I am currently working on. This will actually create a symbolic link to the directory, which is key for live editing! I added my extension to the ârequire-devâ section, because it is development. Just in case this was pushed to the server, I donât want to break anything. When itâs all done and on Packagist, I would put it where it belongs and remove the entry in ârepositoriesâ so it loads from Packagist and not my local computer.
Now we are ready to run:
composer update
If everything is correct, you should see Composer load your library when watching your terminal output. Open your Yii2 app in your editor and view the "vendor" directory, look for your namespace dir (wadeshuler for me), then under it you should see a directory for your extension. Now, it is empty. If it loaded fine, you are ready to start building your extension. All changes are live in your main Yii app so you can test while coding!
So lets get our extension up and running. Now, if you donât need any controller routes or views (it isnât directly accessed via a route), you should use an Object. It loads less files in the backend than a Module. This would work for say a helper class.
namespace wadeshuler\myextension;
Class Helper extends \yii\base\Object
{
public static function _die($data)
{
die( '<pre>' . print_r($data, true) . '</pre>' );
}
}
Then to use it:
use wadeshuler\myextension\Helper; //Helper is name of the class we made above
$test = [ 'one', 'two', 'three' ];
Helper::_die($test);
Ok, so thats a base of an Object for some helper class you want to build. What if you need more than that? Lets first break down when to use an Object, Component, or Module. It is important to know that ALL 3 can accept default configurations by adding it to your Yii2 config.
So this tells us that an Object is a stripped down Component. A Component is an Object with âeventâ and âbehaviorâ abilities. Now, a Module is a mini-app that have MVC, bootstrapping, and dependency injection. If you wanted to create a plug-n-play forum or blog, you would create a Module. You could perfect it, put it on GitHub and Packagist, and load the whole forum or blog feature into your apps in literally, seconds. Do not create a module just to create a simple helper class. It takes extra memory and CPU to do these. Actually, if you trace a Module back, you will see it is an Object at heart too Module extends âyii\di\ServiceLocatorâ which extends âyii\base\Componentâ which extends âyii\base\Objectâ.
If you need routes, controllers, views: Module
If you need events and behaviors: Component
If you donât need any of that extra jazz: Object
So what about Gii? Gii can create a Module for you and it also has a âextensionâ generator. Now, I find the extension generator useless. It puts it in your runtime directory, does the composer for you (not the way I showed above though), and creates an âAutoloadExampleâ that extends a Widget. 3 files total. I donât want them in my runtime dir, and I donât want a widget 99% of the time, and I like to have my extension that is under dev in another text editor (Atom) window for separation. So that is 3 strikes. Even if I did want a widget, I could easily add the few lines to setup the Class myself.
For Modules though, Gii is nice. It will build the controller and views for us. The beautiful thing, when you input your namespace into Gii properly, it will actually put the files into your directory outside of Yii because Composer made the path a symbolic link! So i have a separate Atom editor open for my new extension, and the module files are instantly in there for me to edit, even though it is outside of my actual Yii app!
After generating a module, all you have to do is add it to your Yii config:
So what about an Object? There is no "object" section for our config! Well, you have 2 options.
I normally just put it under âcomponentsâ, because an Object is almost identical to a Component, except a Component has event and behavior support. I think it is fair game to place an Object under your âcomponentsâ config, however they guys at Yii frowned upon it and cried about using DI. I have seen many many public extensions put an Object under âcomponentsâ.
Another option, is to use DI. You could put it under the âbootstrapâ section of your Yii config and pass config params that way. You would have to implement the BootstrapInterface for this. Not too difficult, but an extra hoop to jump through.
I hope this helps someone. I am going to add a page to the Yii wiki "how-to" section for the Composer steps.