how to create console command in a module? - yii2

console command, like ./yii hello/world.
I'm using yii-app-basic.
what I want is not create console command in the dir commands/ but in a module.

1) Your module should implements BootstrapInterface :
class Module extends \yii\base\Module implements \yii\base\BootstrapInterface
{
public function bootstrap($app)
{
if ($app instanceof \yii\console\Application) {
$this->controllerNamespace = 'app\modules\my_module\commands';
}
}
}
2) Create your console controller in your module commands folder :
namespace app\modules\my_module\commands;
class ConsoleController extends \yii\console\Controller
{
public function actionIndex()
{
echo "Hello World\n";
}
}
3) Add your module to your app console configuration config/console.php :
'bootstrap' => [
// ... other bootstrap components ...
'my_module',
],
'modules' => [
// ... other modules ...
'my_module' => [
'class' => 'app\modules\my_module\Module',
],
],
4) You can now use your command :
yii my_module/console/index

Here is a good Tutorial and Discussion.
Follow Below Steps on Tutorial:
1) Create a new module in your application.
2) Edit the Module.php.
3) Create your folder and command inside your module.
4) Add your module to app configurations.

Related

Manipulating the controller map for an API application

I have a set of extensions in my application (yii2-advanced) that have to be maintained in their own repos. To make them as detached as possible, they register as modules on their own and adds to the menu and migrations like this:
vendor\ext\Ext.php
namespace vendor\ext;
use yii\base\BootstrapInterface;
class ext implements BootstrapInterface
{
public function bootstrap($app)
{
$this->addToMenu($app);
$this->addToModules($app);
$app->params['migrations'] = array_merge($app->params['migrations'], ['#vendor/ext/migrations']);
}
private function addToMenu($app)
{
...
}
private function addToModules($app)
{
$app->setModule('ext', ['class' => 'vendor\ext\Module']);
}
}
vendor\ext\composer.json
"extra": {
"bootstrap": "vendor\\ext\\Ext"
},
This works very well, with the controllers in vendor\ext\controllers\. I have an extra application created as a REST API, and I need that application to access vendor\ext\api\ instead of vendor\ext\controllers\.
So if you'd access example.com/ext/controller you'd get vendor\ext\controllers\controller::index(), but if you'd access api.example.com/ext/controller you'd get vendor\ext\api\controller::index().
I've read trough the docs a lot to solve the bootstrapping functionalities that I have, but I can't seem to figure out this one.
Perhaps you can map the controller:
https://www.yiiframework.com/doc/guide/2.0/en/rest-routing#routing
As per example in that documentation:
[
'class' => 'yii\rest\UrlRule',
'controller' => ['u' => 'user'],
]
You could use bootstrapping to create the rules in the UrlManager.
Usually I use strict parsing in Rest API's, so we have to define our rules explicitly anyway.
I solved it by adding each API version as another module and register it with the corresponding version module of my API application.
Now I can develop each module with its supported api versions in a separate repository and everything registers automatically.
Posting the bootstrap code below if anyone needs do do something similar.
public $supported_api_versions = [];
public function bootstrap($app)
{
$this->addToMenu($app);
if($app->id == 'app-frontend')
{
$this->addToModules($app);
}
elseif($app->id == 'app-backend')
{
// Add code here if the module should be available in backend application
}
elseif($app->id == 'app-api')
{
foreach ( $this->supported_api_versions as $api ) {
$module = $app->getModule($api);
$module->setModule($this->name, ['class' => 'vendor\\'.$this->name.'\api\\'.$api.'\Module']);
}
}
elseif($app->id == 'app-console')
{
$app->params['migrations'] = array_merge($app->params['migrations'], ['#vendor/'.$this->name.'/migrations']);
}
}

Running PHPUnit TestCase( not the framework native) on Yii2

I am trying to run PHPUnit_Framework_TestCase on Yii2-advanced. Installed it via composer in folder PHPUnit in the root directory. From there I tried to test with simple test but what I get is an error:
phpunit TestLogin.php
PHP Fatal error: Class 'dektrium\user\models\LoginForm' not found in Z:\toma\toma-metropizza\htdocs\frontend\models\LoginForm.php on line 8
Fatal error: Class 'dektrium\user\models\LoginForm' not found in Z:\toma\toma-metropizza\htdocs\frontend\models\LoginForm.php on line 8
This my TestLogin.php file from the PHPUnit directroy:
<?php
require_once "vendor/autoload.php";
require_once "../frontend/models/LoginForm.php";
class TestLogin extends PHPUnit\Framework\TestCase
{
public function setUp()
{
$login = new LoginForm();
}
public function testStatic()
{
$this->assertClassHasStaticAttribute('test', 'LoginForm');
}
}
This is my LoginForm.php:
<?php
namespace frontend\models;
use Yii;
use \dektrium\user\models\LoginForm as BaseLoginForm;
class LoginForm extends BaseLoginForm
{
public static $test = [];
public function attributeLabels()
{
return [
'login' => Yii::$app->OutData->getLabel(208),
'password' => Yii::$app->OutData->getLabel(98),
'rememberMe' => Yii::t('app','app.Remember me'),
];
}
}
It extends the base dektrium user model. But it seems like the test can't find the base model or something. Can you give me advice? I don't want to use the Yii2 build in tests. Want to write my own. Thank you in advance!
EDIT Directroy structure:
app/
/frontned
/models
LoginForm.php
/PHPUnit
/vendor
composer.json
conposer.lock
TestLogin.php
/vendor
etc.

Yii2 How to enable default assets only in certain modules

I am using basic yii2 app, I have disabled the boostrap css and js in web.php config but i want to enable it inside the module called admin.
I tried adding like this, for component section in config.php under admin module folder, but no luck!
'assetManager' => [
'bundles' => [
'yii\bootstrap\BootstrapPluginAsset' => [
'js'=> ['js/boostrap.js']
],
'yii\bootstrap\BootstrapAsset' => [
'css' => ['css/boostrap.min.css']
]
],
],
How can i achieve this?
In your module's init() method, you can override an exist asset bundle like below:
public function init() {
\Yii::$app->assetManager->bundles['yii\bootstrap\BootstrapAsset'] = [
'css' => ['css/bootstrap_NEW.css']
];
parent::init();
}
In above example, we override yii\bootstrap\BootstrapAsset CSS file in our module. So, in this module, it uses bootstrap_NEW.css instead of its default.
Please note that, you can do this in application globally, not specially in module's init() method. It was just a suggestion to solve this specific case.
You should use asset bundles to handle this, no need to modify assetManager.
To disable Bootstrap, simply remove it from $depends in AppAsset :
public $depends = [
'yii\web\YiiAsset',
];
Create a ModuleAsset class in your module :
class ModuleAsset extends \yii\web\AssetBundle
{
public $depends = [
'yii\bootstrap\BootstrapAsset',
];
}
Make sure to register it in your module's views (you could use a custom layout) :
ModuleAsset::register($this);
Read more : http://www.yiiframework.com/doc-2.0/guide-structure-assets.html

Namespaced helper won't load in Laravel 4

I have a controller that calls a helper class in my app/helpers directory and then that helpers calls another class within it's namespace, but it can't find that class.
So here is my controller:
<?php
namespace App\Controllers\Dash;
use \App\Models\SalesFlyer;
use \App\Helpers\MyPdf;
class FlyerBuilderController extends BaseController {
public function getPdf($flyerId = null) {
$flyer = new SalesFlyer();
$flyerData = $flyer->getSalesFlyerName($flyerId);
$flyerPath = public_path().'/assets/media/flyers/'.Session::get('userid').'/'.$flyerData->name.'-'.$flyerId.'.html';
return MyPdf::downloadPdf($flyerPath, $flyerData->name);
}
}
It catches MyPdf class perfectly fine. Here is MyPdf class:
<?php
namespace App\Helpers;
class MyPdf {
public static function downloadPdf($filePath, $filename) {
$client = new PdfCrowd("anthonythomas", "1ebd0d6e3ec1dfa83a6c5f3dd32906f0");
// other code here
}
}
The PdfCrowd class is within App\Helpers namespace like so:
<?php
namespace App\Helpers;
//
// Pdfcrowd API client.
//
class PdfCrowd { }
Class 'App\Helpers\PdfCrowd' not found
Here is my start/global.php file:
<?php
ClassLoader::addDirectories(array(
app_path().'/commands',
app_path().'/controllers',
app_path().'/controllers/dash',
app_path().'/controllers/dash/product',
app_path().'/models/Product',
app_path().'/models',
app_path().'/database/seeds',
app_path().'/helpers',
));
Then here is my composer:
"autoload": {
"classmap": [
"app/commands",
"app/controllers",
"app/controllers/dash",
"app/controllers/dash/product",
"app/models",
"app/models/Product",
"app/helpers",
"app/database/migrations",
"app/database/seeds",
"app/tests/TestCase.php"
]
}
Any idea why I'm getting that error?..
Everything looks fine but you also have to remember to
composer dump-autoload
Every time you create a new class. Also, check the file
vendor/composer/autoload_classmap.php
You must see your Helper class there.
But if you use PSR-4, you can use the same namespace and you won't have execute composer dump-autoload again:
"autoload": {
"psr-4": {
"App\\Helpers\\": "app/helpers"
}
},
Just remember to remove "app/helpers", from the classmap.
Ok for a shared hosting provider... EVERYTIME you add a new namespace and update composer even with psr-4 it seems, you have to replace the vendor directory with the current one on your local machine for it to actually go through! This saved me so much hours of time after I realized I had to replace the vendor directory everytime a composer dump-autoload was issued locally.

Errors after namespace addition. Unable to access models

I had to incorporate namespacing into my project because I need to use a model named 'Event', and so to avoid errors with the pre-defined 'Event' used by Laravel.
Composer.json:
"autoload": {
"classmap": [
"app/commands",
"app/controllers",
"app/models",
"app/database/migrations",
"app/database/seeds",
"app/tests/TestCase.php"
]
},
"psr-0": {
"App": "app/models/"
},
User model:
<?php
namespace App;
use Eloquent;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Eloquent implements UserInterface, RemindableInterface {
Directory structure pointing towards models:
models/app/User.php
Error on trying to 'sign-in' (This was working before the need for namespacing):
Symfony \ Component \ Debug \ Exception \ FatalErrorException
Class '\User' not found
Sign-in function:
public function postSignin(){
if (Auth::attempt(array('email'=>Input::get('email'), 'password'=>Input::get('password')))) {
$title = Auth::user()->title;
$surname = Auth::user()->surname;
I have run the command 'composer dump-autload' after editing the composer.json file.
Any help would be hugely appreciated as to why this isn't working any more.
If you are following psr-0 then your directory structure of your models should be:
app/
models/
App/
User.php
and try to set the model in config, go to: app/config/auth.php
change the model
'model' => '\App\User'
Good Luck !.