I want to build an OpenBadges module for Yii2 for a site I am building, but there were two things I struggled with. Firstly, how do you make a module and get some custom URLs setup and second, how do I build it Composer style for the future without having to publish a Dev version - that might not even work - to Packagist (or elsewhere).

Using Composer to develop locally:

  1. Create a folder somewhere for your package
  2. Make sure you have a composer.json etc. as if a real project
  3. git init to create a repo and put your files in there, commit etc.
  4. Modify your composer.json in the project you want to bring it into (e.g. my Yii2 project) and add a repository: 
  5. "repositories": [
    {
    "type": "composer",
    "url": "https://asset-packagist.org"
    },
    {
    "type": "vcs",
    "url": "../packages/lukos/yii2-openbadge",
    "options": {
    "symlink": true
    }
    }],
  6. The url is a relative or absolute path to the directory that contains your composer.json (not its parent directory)
  7. Run
    composer require "yourname/your-package @dev"
    in the folder of your main project. Don't get confused here, the yourname bit should match what is in your package composer.json and may or may not match the folder it is in!
  8. Running require should update your local vendor folder with the contents of your package but on Windows, it does NOT create symlinks, it will simply copy the files, which is a shame. At this point, however, you can edit them in the vendor folder and once you are happy, copy them back to the package folder and commit the changes to git.
  9. There is a "path" type for a composer repository, which shouldn't need git but I couldn't get that to work so I've used vcs instead.

How to bootstrap a Yii2 module

I wanted a URL rule that was neater than /openbadge/openbadge/badge or whatever but this requires a URL rule, which must be added in Bootstrap, which is not enabled by default in modules.
  1. make sure your Module class implements yii\base\BootstrapInterface, which defines a single method: public function bootstrap($app)
  2. Inside this method, add something like:
  3. $app->getUrlManager()->addRules([
    new GroupUrlRule([
    'prefix' => $this->pattern,
    'rules' => [
    '' => 'openbadge/'
    ],
    ])
    ], false);
  4. $this->pattern (in my case) is simply 'openbadge' but allows it to be overridden in config if required. False in the method makes sure it is the first rule! so my rule will route all requests to /openbadge/action to my (only) controller, called OpenbadgeController
  5. You then need to ensure you have a bootstrap entry in your project config so that it will run the bootstrap for the module: $config['bootstrap'][] = 'openbadge';