How can I call a console command in web application in Yii 2.0 - yii2

I have a console command to generate user report. I want to call the same from my web application. I am using Yii 2.0.0 beta version.I tried to follow answers given in this post How to call a console command in web application action in Yii?
Since Yii 2.0 structure is very different from Yii 1.1 ,I get errors if I try to include command/userReportController.php .Can someone guide me on this?

You should use an extension like https://github.com/vova07/yii2-console-runner-extension

I think this is the simplest solution:
$controller = new YourConsoleController(Yii::$app->controller->id, Yii::$app);
$controller->actionYourConsoleAction();

use this code:
$application = new yii\console\Application($config);
$application->runAction('controller/action');
I'm using this method instead of yii console command, because I'm running Yii on managed VPS where unix commands are not supported in cron, only php scripts.
To run it this way instead of console, the yii configuration must be initialized first, of course:
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');
require(__DIR__ . '/vendor/autoload.php');
require(__DIR__ . '/vendor/yiisoft/yii2/Yii.php');
require(__DIR__ . '/common/config/bootstrap.php');
require(__DIR__ . '/console/config/bootstrap.php');
$config = yii\helpers\ArrayHelper::merge(
require(__DIR__ . '/common/config/main.php'),
require(__DIR__ . '/common/config/main-local.php'),
require(__DIR__ . '/console/config/main.php'),
require(__DIR__ . '/console/config/main-local.php')
);

Let's say your action is called file/convert, and you want to run it in the background:
$cmd = "cd /home/site.com/public_html/yii && nohup php yii file/convert >/dev/null &";
shell_exec( $cmd );

yii2-console-runner-extension keeps loading.
Try this:
It's yii (without ext, not yii.bat)
Make sure that php folder added to PATH variable (Windows)
$op = shell_exec ( 'absolute/path/to/yii ' . 'cache/flush-all' );
\yii\helpers\VarDumper::dump($op, 10, 1);
Output:
The following cache components were processed:
* cache (yii\\caching\\FileCache)

If you really want to run Console controller by Web controller likes migrate:
public function actionMigrate()
{
// Keep current application
$oldApp = \Yii::$app;
// Load Console Application config
$config = require \Yii::getAlias('#app'). '/config/console.php';
new \yii\console\Application($config);
$result = \Yii::$app->runAction('migrate', ['migrationPath' => '#app/migrations/', 'interactive' => false]);
// Revert application
\Yii::$app = $oldApp;
return;
}
Above sample code is for yii2-app-basic template, you could change path for yii2-app-advanced template.

Related

how to import json file from https web page into a mariadb or mysql database?

I am trying to import a file into a mariadb (mysql), database. A proof of concept file is in .json format on the web at this location. https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson
I know how to do this on db2 for i.
select * from JSON_TABLE(
SYSTOOLS.HTTPGETCLOB('https://earthquake.usgs.gov' ||
'/earthquakes/feed/v1.0/summary/all_week.geojson',null),
'$.features[*]'
COLUMNS( MILLISEC BIGINT PATH '$.properties.time',
MAG DOUBLE PATH '$.properties.mag',
PLACE VARCHAR(100) PATH '$.properties.place'
)) AS X;
This reads a from the web and lists 3 fields. Surrounding it with an insert clause will put it into a database file for me.
I would like to do exactly the same thing on my home server using mariadb. Ultimately a script will run unattended on a hosted server.
A .json segment of the earthquake data looks like this:
… "features":[
{"type":"Feature",
"properties":{
"mag":1.1,
"place":"58 km WNW of Anchor Point, Alaska",
"time":1640472257402,
"updated":1640472615410,
"tz":null,
"url":"https://earthquake.usgs.gov/earthquakes/eventpage/ak021gi3al5x",
"detail":"https://earthquake.usgs.gov/earthquakes/feed/v1.0/detail/ak021gi3al5x.geojson",
"felt":null,
"cdi":null,
"mmi":null,
"alert":null,
"status":"automatic",
"tsunami":0,
"sig":19,
"net":"ak",
"code":"021gi3al5x",
"ids":",ak021gi3al5x,",
"sources":",ak,",
"types":",origin,",
"nst":null,
"dmin":null,
"rms":0.79,
"gap":null,
"magType":"ml",
"type":"earthquake",
"title":"M 1.1 - 58 km WNW of Anchor Point, Alaska"},
"geometry":{
"type":"Point",
"coordinates":[-152.8406,59.9119,89.7]
},
"id":"ak021gi3al5x"
}, ...
Just a thought, but you could maybe just write a BASH script, e.g.
#!/bin/sh
cd "$(dirname "$0")"
export PATH=/bin:/usr/bin:/usr/local/bin
TODAY=`date +"%d%b%Y-%H%M"`
MYSQL_HOST='127.0.0.1'
MYSQL_PORT='3306'
MYSQL_USER='root'
MYSQL_PASSWORD='root'
url=https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson
DATA=$(curl ${url} 2>/dev/null)
printf '%s' "$DATA" | awk '{print $0}'
exit
...
...
...
and then use a tool like https://webinstall.dev/jq/, Python and whatever other tools you have on your system to extract the data that you want and then update the DB.
I am more familiar with PHP, which would work also. You could tidy that up a bit, but seems to work actually.
earthquake.php
<?php
$database = false;
try {
$options = array(PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ, PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING, PDO::ATTR_EMULATE_PREPARES => true );
$conn = new PDO('mysql:host=127.0.0.1;dbname=test;port=3306;charset=utf8','root','root', $options);
} catch (PDOException $e) {
// Echo custom message. Echo error code gives you some info.
echo '[{"error":"Database connection can not be estabilished. Please try again later. Error code: ' . $e->getCode() . '"}]';
exit;
}
$url = "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson";
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
$result = curl_exec($ch);
$features = json_decode($result)->features;
foreach ($features as $feature) {
echo 'Mag: '.$feature->properties->mag.', Place: '.$feature->properties->place.', '.gmdate("Y-m-d H:i:s", $feature->properties->time/1000).PHP_EOL;
$query = 'INSERT INTO features (mag, place, time) VALUES (?, ?, ?)';
$params = [$feature->properties->mag, $feature->properties->place, gmdate("Y-m-d H:i:s", $feature->properties->time/1000)];
$stmt = $conn->prepare($query) or die ('["status":{"error":"Prepare Statement Failure","query":"' .$query . '"}]');
$stmt->execute($params) or die('[{"error":"' . $stmt->errorInfo()[2] . '","query":"' .$query . '","params":' .json_encode($params) . '}]');
}
?>
create a local DB called features with mag, place and time columns. If you have php on your system just run it from the CLI, php earthquake.php
e.g. Insert into mysql from Bash script
I use Laravel a bit, and would probably actually build my own model and use Eloquent and a little UI to handle that, but using a script seems like an option.

I can't access the Gii interface from my yii framework backend

Someone else has configured my computer and I don't know how. The script to run my application is not in web/index.php but public_html/index.php. I don't know if that makes a difference. The application uses a mysql database and a react front end and is hosted on aws. Here is the code from the public_html/index.php file:
<?php
require(__DIR__ . '/../vendor/autoload.php');
if (file_exists(__DIR__ . '/../.env')) {
(new \Dotenv\Dotenv(__DIR__ . '/../'))->load();
}
$yii_env = 'test';
switch (getenv('ENVIRONMENT')) {
case 'local': $yii_env = 'dev'; break;
case 'qa': $yii_env = 'test'; break;
case 'prod': $yii_env = 'prod'; break;
}
defined('YII_DEBUG') or define('YII_DEBUG', getenv('DEBUG'));
defined('YII_ENV') or define('YII_ENV', $yii_env);
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
require(__DIR__ . '/../common/config/bootstrap.php');
require(__DIR__ . '/../api/config/bootstrap.php');
$config = yii\helpers\ArrayHelper::merge(
require(__DIR__ . '/../common/config/main.php'),
require(__DIR__ . '/../api/config/main.php')
);
$application = new yii\web\Application($config);
$application->run();
How do I access gii?
If you're using apache2. Please check to make sure you have ".htaccess" file in public_html/ folder.

How to import a module in a Azure PowerShell Function?

Im trying to query an azure table from a function ( using Get-AzTableRow ) . Works very well from my laptop but the module "aztable' is not present in the azure function, and therefore all i get is a red screen :(
Is there a way to install it ?
Thanks !
David
You do not need to install the AzTable module in the Azure Function yourself. When you run the command, it will install the corresponding module for you.
Here are the screenshots:
The example of the AzTable module:
$location = "eastus"
$resourceGroup = "charlesTable11"
New-AzResourceGroup -ResourceGroupName $resourceGroup -Location $location
$storageAccountName = "pshtablestorage1122"
$storageAccount = New-AzStorageAccount -ResourceGroupName $resourceGroup `
-Name $storageAccountName `
-Location $location `
-SkuName Standard_LRS `
-Kind Storage
$ctx = $storageAccount.Context
$tableName = "pshtesttable"
New-AzStorageTable –Name $tableName –Context $ctx
Get-AzStorageTable –Context $ctx | select Name
Azure PowerShell is installed or updated, you must install module AzTable, which has the commands for managing the entities. To install this module, run PowerShell as an administrator and use the Install-Module command.
You may refer to the suggestion mentioned in this article. https://learn.microsoft.com/en-us/azure/storage/tables/table-storage-how-to-use-powershell
Please see https://learn.microsoft.com/en-us/azure/azure-functions/supported-languages
AzTable module:Supported languages in Azure Functions powershellgallery.com/packages/AzTable/2.0.1
Kindly let us know if the above helps or you need further assistance on this issue.

Can't resolve target of expression 'str_replace('\\', '/', realpath(dirname(__FILE__)))/system/initialize.php'

This is what I have in my config file:
define('BASE_DIR', str_replace('\\', '/', realpath(dirname(__FILE__))) . '/', false);
// output: C:/xampp/htdocs/myweb/
define('BASE_URL', $protocol . $_SERVER['HTTP_HOST'] . rtrim(dirname($_SERVER['SCRIPT_NAME']), '/.\\') . '/', false);
//output: http://localhost/myweb/
define('APP_DIR', BASE_DIR . 'app/', false);
// output: C:/xampp/htdocs/myweb/app/
define('TEMP_DIR', BASE_DIR . 'app/view/template/', false);
//output: C:/xampp/htdocs/myweb/app/view/template/
define('LIBRARY_DIR', BASE_DIR . 'library/', false);
//output: C:/xampp/htdocs/myweb/library/
define('SYSTEM_DIR', BASE_DIR . 'system/', false);
//output: C:/xampp/htdocs/myweb/system/
I include the above file in my index file and then include a file initialize.php like
index.php
// Include the config file. If file not found throw error and exit.
if (!file_exists('config.php')) {
header('Location: error/404.php');
exit();
} else {
include_once 'config.php';
}
// Load startup file to check, set environment plus a few core files
require_once SYSTEM_DIR . 'initialize.php';
The initialize.php conducts a few checks and sets a few parameters required by the application.
This works fine but recently I switched to PhpStorm and the IDE says
Can't resolve target of expression 'str_replace('\\', '/', realpath(dirname(__FILE__)))/system/initialize.php' (at line 27).
What is this problem? and if the target of expression isn't resolved, as per the IDE, how is it still including the initialize file.
The warning you see is just an IDE warning, it doesn't cause any problem. The IDE can not get to know what files you want to include because the expression is too complicated.
IDE usually scans all PHP files in your project. so even if the include/require are not parsed correctly, the IDE still knows all the classes/functions in all your PHP files.

Yii2. Invalid path alias

I've seen similiar questions but haven't found a working solution. Here is my index.php file:
<?php
// comment out the following two lines when deployed to production
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');
require(__DIR__ . '/../vendor/autoload.php');
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
$config = require(__DIR__ . '/../config/web.php');
(new yii\web\Application($config))->run();
require(__DIR__ . '/../config/aliases.php');
As you can see, it requires config/aliases.php file, whose contents are:
<?php
Yii::setAlias('message_files_root', '#webroot/message_files');
Yii::setAlias('message_files', '#web/message_files');
CallingYii::getAlias('#message_files_root') works fine within the index.php, but when it is in a controller file, it says Invalid path alias: #message_files_root.
Here is my controller's action (the rest of the code is fully commented):
public function actionIndex()
{
var_dump(Yii::getAlias('#message_files_root'));
$message = new Message();
if you invoke Yii::getAlias() static method from controller, Yii::setAlias(#web) does not get register yet.
you may refer to the web/index file.
web/index.php
require(__DIR__ . '/../../vendor/autoload.php');
require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
require(__DIR__ . '/../../common/config/bootstrap.php'); --> Yii::setAlias(#web) are not listed here
require(__DIR__ . '/../config/bootstrap.php');
$config = yii\helpers\ArrayHelper::merge(
require(__DIR__ . '/../../common/config/main.php'),
require(__DIR__ . '/../../common/config/main-local.php'),
require(__DIR__ . '/../config/main.php'),
require(__DIR__ . '/../config/main-local.php')
);
$application = new yii\web\Application($config);
//var_dump(Yii::getAlias('#web'));die; --> imitate invoke #web alias fail
$application->run(); --> here both #web alias and aliases from $config got registered.
//var_dump(Yii::getAlias('#web'));die; --> imitate invoke #web alias success
my guess is, the config got registered first before the default #web aliases being register. Thats why invoking #web aliases from bootrap config fail.
thus, u need to use absolute path for the second paramter. use this..
yii2 advanced template
Yii::setAlias('#message_files_root', dirname(dirname(__DIR__)) . '/frontend/web/message_files');
yii2 basic template
Yii::setAlias('#message_files_root', dirname(__DIR__) . '/web/message_files');
I am NOT claiming that is the nicest way to do that, but it works the way I wanted it to work – when an alias can include other aliases.
<?php
// comment out the following two lines when deployed to production
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');
require(__DIR__ . '/../vendor/autoload.php');
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
$config = require(__DIR__ . '/../config/web.php');
$app = new class($config) extends yii\web\Application
{
protected function bootstrap()
{
parent::bootstrap();
require(__DIR__ . '/../config/aliases.php');
}
};
$app->run();