[英]Opencart Admin Cron Jobs
我了解 CRON 以及如何创建/管理它。 但这个问题不同。
我想开发一个模块来删除超过给定时间范围的任何(未付款)订单。 例如:我想删除下订单后 2 天内未付款的任何未付款订单。
我想在 opencart 中使用现有模型(而不是使用新模型)。 假设模块 URL 将是: http://www.yourstore.com/admin/index.php?route=module/modulename/function并且将从 CRON 调用,然后所有未支付的订单都将消失。
但主要问题是:当 CRON 想要访问该 URL 时,它需要一个安全令牌,否则它将永远不会被执行。
我的问题是:如何在没有安全令牌的情况下从 CRON 执行该模块(以防仅用于该模块)?
请帮助我,如果您有更好的主意或更干净的方法,我会非常感谢您。
更新:对于 Opencart 版本 <= 1.5.6.4
对于与管理相关的 cron 作业,请这样做。
将admin/index.php
复制到admin/index_for_cron.php
现在,在admin/index_for_cron.php
,搜索这两行并将它们注释掉,它们负责登录和权限。
// Login // $controller->addPreAction(new Action('common/home/login')); // Permission // $controller->addPreAction(new Action('common/home/permission'));
现在将此 url 用于您的 cron 作业。
http://www.yourstore.com/admin/index_for_cron.php?route=module/modulename/function
注意:出于安全原因,强烈建议将index_for_cron.php
的名称更改为丑陋的、不可预测的名称。
希望这可以帮助 :)
我做过类似 IJas 的事情。 在管理员和目录旁边,我创建了一个名为“cli”的新文件夹。
该文件夹包含一个由 cli 执行的特定功能的 php 文件(通过 crontab 按设定的时间表执行脚本,或在命令行中手动执行),以及这些类型的脚本的各种“引导程序”。 引导程序本质上是在目录或管理员中找到的“索引”的副本,包括一些检查和删除权限检查和一些其他不必要的项目。 它调用在调用特定函数脚本中设置的任何控制器/操作(在下面的示例中,它调用 /admin/controller/common/cli_some_function.php 中定义的类的 index 方法)。
功能特定脚本:
<?php
$cli_action = 'common/cli_some_function';
require_once('cli_dispatch.php');
?>
CLI“引导程序”/调度程序:
<?php
// CLI must be called by cli php
if (php_sapi_name() != 'cli') {
syslog(LOG_ERR, "cli $cli_action call attempted by non-cli.");
http_response_code(400);
exit;
}
// Ensure $cli_action is set
if (!isset($cli_action)) {
echo 'ERROR: $cli_action must be set in calling script.';
syslog(LOG_ERR, '$cli_action must be set in calling script');
http_response_code(400);
exit;
}
// Handle errors by writing to log
function cli_error_handler($log_level, $log_text, $error_file, $error_line) {
syslog(LOG_ERR, 'CLI Error: ' . $log_text . ' in ' . $error_file . ': ' . $error_line);
echo 'CLI Error: ' . $log_text . ' in ' . $error_file . ': ' . $error_line;
}
set_error_handler('cli_error_handler');
// Configuration not present in CLI (vs web)
chdir(__DIR__.'/../admin');
set_include_path(get_include_path() . PATH_SEPARATOR . realpath(dirname(__FILE__)) . '../admin/');
$_SERVER['HTTP_HOST'] = '';
// Version
define('VERSION', '1.5.1');
// Configuration (note we're using the admin config)
require_once('../admin/config.php');
// Configuration check
if (!defined('DIR_APPLICATION')) {
echo "ERROR: cli $cli_action call missing configuration.";
$log->write("ERROR: cli $cli_action call missing configuration.");
http_response_code(400);
exit;
}
// Startup
require_once(DIR_SYSTEM . 'startup.php');
// Application Classes
require_once(DIR_SYSTEM . 'library/currency.php');
require_once(DIR_SYSTEM . 'library/user.php');
require_once(DIR_SYSTEM . 'library/weight.php');
require_once(DIR_SYSTEM . 'library/length.php');
// Registry
$registry = new Registry();
// Loader
$loader = new Loader($registry);
$registry->set('load', $loader);
// Config
$config = new Config();
$registry->set('config', $config);
// Database
$db = new DB(DB_DRIVER, DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DATABASE);
$registry->set('db', $db);
// Settings
$query = $db->query("SELECT * FROM " . DB_PREFIX . "setting WHERE store_id = '0'");
foreach ($query->rows as $setting) {
if (!$setting['serialized']) {
$config->set($setting['key'], $setting['value']);
} else {
$config->set($setting['key'], unserialize($setting['value']));
}
}
// Url
$url = new Url(HTTP_SERVER, HTTPS_SERVER);
$registry->set('url', $url);
// Log
$log = new Log($config->get('config_error_filename'));
$registry->set('log', $log);
function error_handler($errno, $errstr, $errfile, $errline) {
global $log, $config;
switch ($errno) {
case E_NOTICE:
case E_USER_NOTICE:
$error = 'Notice';
break;
case E_WARNING:
case E_USER_WARNING:
$error = 'Warning';
break;
case E_ERROR:
case E_USER_ERROR:
$error = 'Fatal Error';
break;
default:
$error = 'Unknown';
break;
}
if ($config->get('config_error_display')) {
echo "\n".'PHP ' . $error . ': ' . $errstr . ' in ' . $errfile . ' on line ' . $errline."\n";
}
if ($config->get('config_error_log')) {
$log->write('PHP ' . $error . ': ' . $errstr . ' in ' . $errfile . ' on line ' . $errline);
}
return true;
}
set_error_handler('error_handler');
$request = new Request();
$registry->set('request', $request);
$response = new Response();
$response->addHeader('Content-Type: text/html; charset=utf-8');
$registry->set('response', $response);
$cache = new Cache();
$registry->set('cache', $cache);
$session = new Session();
$registry->set('session', $session);
$languages = array();
$query = $db->query("SELECT * FROM " . DB_PREFIX . "language");
foreach ($query->rows as $result) {
$languages[$result['code']] = $result;
}
$config->set('config_language_id', $languages[$config->get('config_admin_language')]['language_id']);
$language = new Language($languages[$config->get('config_admin_language')]['directory']);
$language->load($languages[$config->get('config_admin_language')]['filename']);
$registry->set('language', $language);
$document = new Document();
$registry->set('document', $document);
$registry->set('currency', new Currency($registry));
$registry->set('weight', new Weight($registry));
$registry->set('length', new Length($registry));
$registry->set('user', new User($registry));
$controller = new Front($registry);
$action = new Action($cli_action);
$controller->dispatch($action, new Action('error/not_found'));
// Output
$response->output();
?>
使用此方案,我可以确保不会从网络调用脚本,并且我可以使用 cron 作业从服务器本身自动触发它(例如:0 1 0 0 0 /path/to/php /path /to/opencart/cli/cli_some_function.php)
请注意, error_handler 函数使用了一些非现成的配置选项。 您可以设置它们或将自己的支票放在那里。
编辑对错误处理进行了一些更改
在 2.3.0.2 中,我发现一种非常简单的方法是将您的控制器函数路径添加到登录和权限限制的忽略路径设置中。 然后只需在该控制器功能中添加一个 url 密码或其他检查来锁定它。
所以首先在 admin/controller/startup/login.php 中将你的控制器函数路径添加到 $ignore 数组中,例如 'common/cron/action'
然后在 admin/controller/startup/permissions.php 中你只需要控制器路径,例如“common/cron”
然后最后在你的 action() 函数开始时这样做:
if(!isset($_GET['pass']) || $_GET['pass'] != 'secretpassword')return;
然后我只是将它添加到我的 cron 中:
php-cli -r 'echo file_get_contents("https://www.website.com/admin/index.php?route=common/cron/action&pass=secretpassword");'
由于我多次有类似的需求,我将我的想法放入一个名为OCOK的轻量级命令行工具中。
特别是 Cli 任务命令允许您通过命令行调用 Opencart 控制器,从而让您将它们称为 cron 作业。 只需像这样创建一个控制器并将其保存为admin/controller/task/example.php
:
class ControllerTaskExample extends Controller {
public function index() {
if (isset($this->is_cli) && $this->is_cli === true) {
// work done by the controller
if (isset($this->request->get['param1'])) {
echo "param1 is " . $this->request->get['param1'] . "\n";
}
if (isset($this->request->get['param2'])) {
echo "param2 is " . $this->request->get['param2'] . "\n";
}
}
}
}
通过命令行可以使用参数调用它:
ocok run task/example param1=foo param2=bar
上述命令将输出:
param1 is foo
param2 is bar
将此添加到 crontab 就像将以下行添加到您的 cron 文件一样简单:
* * * * * (cd /path/to/opencart/folder; /path/to/ocok run task/example param1=foo param2=bar)
当然需要正确设置相应的路径。
我知道这是一个非常古老的问题,但我花了很长时间试图弄清楚如何在不同的 opencart 版本 2.x 中做同样的事情。 所以我在这里分享我的解决方案。(基于 Mike T 方法)
1 - 在 admin 和 catalog 旁边创建 cli 文件夹。
2 - 在同一个文件夹中创建一个文件,您将通过 cron 或命令行运行该文件,例如 runcron.php
#!/usr/bin/php
<?php
require_once('cli_dispatch.php');
3 - 在同一文件夹中创建 cli_dispatch.php 文件,该文件是 admin 文件夹中 index.php 文件的副本,并进行了一些更改(注意在此安装中激活了 VQMOD,这可能不是您的情况)
<?php
// CLI must be called by cli php
if (php_sapi_name() != 'cli') {
syslog(LOG_ERR, "cli $cli_action call attempted by non-cli.");
http_response_code(400);
exit;
}
// Ensure $cli_action is set
if (!isset($cli_action)) {
echo 'ERROR: $cli_action must be set in calling script.';
syslog(LOG_ERR, '$cli_action must be set in calling script');
http_response_code(400);
exit;
}
// Handle errors by writing to log
function cli_error_handler($log_level, $log_text, $error_file, $error_line) {
syslog(LOG_ERR, 'CLI Error: ' . $log_text . ' in ' . $error_file . ': ' . $error_line);
echo 'CLI Error: ' . $log_text . ' in ' . $error_file . ': ' . $error_line;
}
set_error_handler('cli_error_handler');
// Configuration (note we're using the admin config)
require_once __DIR__.('/../admin/config.php');
// Configuration not present in CLI (vs web)
chdir(__DIR__.'/../admin');
set_include_path(get_include_path() . PATH_SEPARATOR . realpath(dirname(__FILE__)) . '../admin/');
$_SERVER['HTTP_HOST'] = '';
if (!defined('DIR_APPLICATION')) {
echo "ERROR: cli $cli_action call missing configuration.";
http_response_code(400);
exit;
}
// Version
define('VERSION', '2.3.0.3_rc');
// Configuration
if (is_file('config.php')) {
require_once('config.php');
}
// Install
if (!defined('DIR_APPLICATION')) {
header('Location: ../install/index.php');
exit;
}
//VirtualQMOD
require_once('../vqmod/vqmod.php');
VQMod::bootup();
// VQMODDED Startup
require_once(VQMod::modCheck(DIR_SYSTEM . 'startup.php'));
start('cli');
4 - 现在创建文件upload/system/config/cli.php,它将是opencart 用来从文件upload/system/framework.php 读取新cli bootrasp 配置的文件
<?php
// Site
$_['site_base'] = HTTP_SERVER;
$_['site_ssl'] = HTTPS_SERVER;
// Database
$_['db_autostart'] = true;
$_['db_type'] = DB_DRIVER; // mpdo, mssql, mysql, mysqli or postgre
$_['db_hostname'] = DB_HOSTNAME;
$_['db_username'] = DB_USERNAME;
$_['db_password'] = DB_PASSWORD;
$_['db_database'] = DB_DATABASE;
$_['db_port'] = DB_PORT;
// Session
//$_['session_autostart'] = true;
// Autoload Libraries
$_['library_autoload'] = array(
'openbay'
);
// Actions
$_['action_pre_action'] = array(
'startup/startup',
'startup/error',
'startup/event',
'startup/sass',
// 'startup/login',
// 'startup/permission'
);
// Actions
$_['action_default'] = 'sale/croninvoices';
// Action Events
$_['action_event'] = array(
'view/*/before' => 'event/theme'
);
正如你所看到的,我已经评论了所有与权限相关的会话和操作行。
您将需要编辑该行
$_['action_default'] = 'sale/yourscript';
使用控制器的路径和文件名更改“销售/您的脚本”。
在示例中,runnunig runcron.php 文件将执行索引函数
upload/admin/controller/sale/yourscript.php file
在 opencart 2.1.0.2 中。 如果您在 cron 作业中需要 db ,但不需要任何 opencart 模型。 您可以创建文件 system/mycron/cron_task.php。 并将这样的代码添加到这个文件中:
// CLI
include_once 'config.php';
include_once DIR_SYSTEM.'library/db/mysqli.php';
include_once DIR_SYSTEM.'helper/general.php';
mb_internal_encoding('UTF-8');
if (php_sapi_name() != 'cli') { error_log('NOT CLI CALL');print 'NOT CLI CALL';http_response_code(400);exit; }
$db = new DB\MySQLi(DB_HOSTNAME,DB_USERNAME,DB_PASSWORD,DB_DATABASE,DB_PORT);
// END CLI
// Your actual code, and you CAN use opencart DB!
foreach ($db->query("SELECT * FROM oc_product")->rows as $row) {
//...
}
现在你可以从你的 cron 工作中运行它:
12 7 * * * cd /path/to/opencart/root/folder && php system/mycron/cron_task.php
默认情况下,opencart 不允许在未登录的情况下访问管理页面。 在admin/controller/common/home.php
中的login()
方法中检查登录和令牌验证。
it cant be set on frontend coz the model is in admin area.
- 您可以在管理面板中为前端创建一个具有相同功能的新控制器和模型,并将其用于 cronjob。
Opencart 有为用户设置访问权限的用户组。 因此,未经许可,不会为用户加载管理页面。 因此,您可能需要大量修改核心文件以在管理面板中设置 cronjob,这可能会导致严重的安全问题。
我建议为 cronjob 使用前端控制器和模型文件。 为了获得额外的安全性,您可以在 url 中传递一个特定的关键参数并编写一个条件来验证它。
祝你今天过得愉快 !!
“我想开发一个模块来删除任何超出给定时间范围的(未付款)订单。例如:我想删除在下订单后 2 天内未付款的任何未付款订单。” “我想在 opencart 中使用现有模型(而不是使用新模型)。”
所以,我相信你知道,问题是你必须登录到管理员才能访问它的控制器和模型,但运行时不会登录 cron 作业。
您可以查看目录模型是否可以满足您的需求,在这种情况下没有问题:
catalog/model/checkout/order.php
您可以在此处遵循其他答案 - 即找到一些登录方法。
或者您可以编写一个独立的 PHP 脚本来运行一个简单的 SQL 查询。
您是对的,使用系统模型通常是正确的做法,但是 OpenCart 非常简单,它应该是一个非常简单的查询(只有几行),可以满足您的需要,因此这也是一个可以接受的选择在我看来,在这种情况下。
include_once($_SERVER['DOCUMENT_ROOT'].'/admin/model/module/ModelYourModel.php');
$mym = new ModelYourModel($this->registry);
$mym->yourFunction();
对于 2.1 版,可能更高。 使用目录文件夹中 admin 文件夹中的模型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.