OpenCartのCronプログラムを作成

らら
らら

はじめに

今回は、OpenCart用Cronをプログラムを作成してみる

一応、既存のライブラリを利用できるようにする。

既存ソースみてみる

system/framework.php,admin/controller/startup/startup.phpあたりを拝借してなんとかなりそう。そのままファイルを使ってもよいがきっといらないものもある感じなので

今回は夜間基幹連動を想定して作成します。

実際のコード

想定は、OpenCartのルートの置くようにしています、ただ、セキュリティに配慮する場合は、別の箇所をお勧めします。現在はディレクトリ構造の兼ね合いで説明できるようにしています。

コードのほとんどがframework.php、startup.phpの内容です。不要なもの、必要なものは別途追記すれば問題ないと思います。

ファイル名は適当に決めて保存してください。実際のcronに設定する実行ファイルになります。


<?php
define('DEF_ADMIN_PATH', 'admin/');
	if (!empty($argv)) {
		array_shift($argv);
		parse_str(implode('&', $argv), $_GET);
	} else if (empty($_GET)) {
		die('No parameter found');
	}
	ini_set('memory_limit', -1);
	set_time_limit(36000);
	#index.php
	// Version
	define('VERSION', '3.0.3.7');
	// Configuration
	if (file_exists(DEF_ADMIN_PATH.'config.php')) {
		require_once(DEF_ADMIN_PATH.'config.php');
	}
	// Install
	if (!defined('DIR_APPLICATION')) {
		die('Incorrect DEF_ADMIN_PATH - , please specify it manually in cron.php');
	}
	#framework.php
	// Startup
	require_once(DIR_SYSTEM . 'startup.php');
	// Registry
	$registry = new Registry();
	// Config
	$config = new Config();
	$config->load('default');
	$config->load('admin');
	$registry->set('config', $config);
	// Event
	$event = new Event($registry);
	$registry->set('event', $event);
	// Event Register
	if ($config->has('action_event')) {
		foreach ($config->get('action_event') as $key => $value) {
			foreach ($value as $priority => $action) {
				$event->register($key, new Action($action), $priority);
			}
		}
	}
	// Loader
	$loader = new Loader($registry);
	$registry->set('load', $loader);
	// Request
	$registry->set('request', new Request());
	// Response
	$response = new Response();
	$response->addHeader('Content-Type: text/html; charset=utf-8');
//	$response->setCompression($config->get('config_compression'))
	$registry->set('response', $response);
	// Database
	if ($config->get('db_autostart')) {
		$registry->set('db', new DB($config->get('db_engine'), $config->get('db_hostname'), $config->get('db_username'), $config->get('db_password'), $config->get('db_database'), $config->get('db_port')));
	}
	// Session
	if ($config->get('session_autostart')) {
		$session = new Session($config->get('session_engine'), $registry);
		$session->start();
		$registry->set('session', $session);
	}
	// Cache 
	$registry->set('cache', new Cache($config->get('cache_engine'), $config->get('cache_expire')));
	// Url
	if ($config->get('url_autostart')) {
		$registry->set('url', new Url($config->get('site_url'), $config->get('site_ssl')));
	}
	// Language
	$language = new Language($config->get('language_default'));
	$language->load($config->get('language_default'));
	$registry->set('language', $language);
	// Document
	$registry->set('document', new Document());
	// Config Autoload
	if ($config->has('config_autoload')) {
		foreach ($config->get('config_autoload') as $value) {
			$loader->config($value);
		}
	}
	// Language Autoload
	if ($config->has('language_autoload')) {
		foreach ($config->get('language_autoload') as $value) {
			$loader->language($value);
		}
	}
	// Library Autoload
	if ($config->has('library_autoload')) {
		foreach ($config->get('library_autoload') as $value) {
			$loader->library($value);
		}
	}
	// Model Autoload
	if ($config->has('model_autoload')) {
		foreach ($config->get('model_autoload') as $value) {
			$loader->model($value);
		}
	}
	// Route
	$controller = new Router($registry);
	// Pre Actions
//	if ($config->has('action_pre_action')) {
//		foreach ($config->get('action_pre_action') as $value) {
//			$controller->addPreAction(new Action($value));
//		}
//	}
	$pre_actions = array('startup/startup');
	foreach ($pre_actions as $value) {
		$controller->addPreAction(new Action($value));
	}
	// Settings
	$db = $registry->get('db');
	$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'], json_decode($setting['value'], true));
		}
	}
	// Dispatch
	//admin/controller/test/crontest/cron
	$controller->dispatch(new Action('test/crontest/cron'), new Action($config->get('action_error')));
	// Output
	$response->output();

Dispatchの部分を作ります。

admin/controller配下にtestというフォルダーを作ります。

crontest.phpという名前で下記コードを保存します。関数名はdispatchでcronを指定したので関数名をcronにします。

/コントローラー内フォルダー名/phpファイル名/関数名でdispatchを呼び出ししています。/test/crontest/cron

クラス名も同様ControllerTestCrontestと先頭大文字で命名します。実際に使用する場合は、セキュリティ的にディレクトリ名、ファイル名は変更してください。dispatchで記載したパスも変更してください。

記載しているコード自体はテストコードです。メンテナンスフラグを立てて。各SQLを読み込み表示します。表示後メンテナンスフラグを解除します。

これで、OpenCartのソース内のコードをコピーしてそのまま。ここで使用できるようになったと思います。


<?php
ini_set('memory_limit', -1);
@set_time_limit(3600);
class ControllerTestCrontest extends Controller {
	const PID_PATH = '/var/www/xxxxx/opencart/hogebatch.pid';
	public function __construct($registry) {
		parent::__construct($registry);
		//yum install php-process
		// 既に同一タスクが起動中の場合
//		if (file_exists(static::PID_PATH)) {
//			exit(1);
//		}
//		file_put_contents(static::PID_PATH, posix_getpid());
		// Ctrl+C等で中断されたときにメッセージを表示し、pidファイルが削除されるようにする
//		pcntl_async_signals(true);
//		pcntl_signal(SIGINT, function() {
//			exit;
//		});
	}
	public function __destruct() {
//		unlink(static::PID_PATH);
	}
	public function cron($params = '') {
		# maintenance on
		$this->db->query("UPDATE " . DB_PREFIX . "setting SET `value` = '1', serialized = '0'  WHERE `code` = 'config' AND `key` = 'config_maintenance' AND store_id = '0'");
		#order
		$sql = "SELECT ".'*'." FROM `" . DB_PREFIX . "order`";
		$query = $this->db->query($sql);
		foreach ($query->rows as &$row) {
			echo $row['order_id'].$row['payment_firstname'].$row['total']."\n";
		}
		#customer
		$sql = "SELECT ".'*'." FROM `" . DB_PREFIX . "customer`";
		$query = $this->db->query($sql);
		foreach ($query->rows as &$row) {
			echo $row['customer_id'].$row['firstname'].$row['lastname'].$row['email']."\n";
		}
		#product
		$sql = "SELECT ".'*'." FROM `" . DB_PREFIX . "product`";
		$query = $this->db->query($sql);
		foreach ($query->rows as &$row) {
			echo $row['product_id'].$row['model'].$row['price'].$row['quantity']."\n";
		}
		# maintenance off
		$this->db->query("UPDATE " . DB_PREFIX . "setting SET `value` = '0', serialized = '0'  WHERE `code` = 'config' AND `key` = 'config_maintenance' AND store_id = '0'");
	}
}

opencartのライブラリ使用しない場合(mysqli)


		$db = new \mysqli($this->config->get('db_hostname'), $this->config->get('db_username'), $this->config->get('db_password'), $this->config->get('db_database'), $this->config->get('db_port'));
		if ($db->connect_error) {
			throw new \Exception('Error: ' . $db->connect_error . '
Error No: ' . $db->connect_errno); } $db->set_charset("utf8"); $db->query("SET SQL_MODE = ''"); $db->query("SET SESSION sql_mode = 'NO_ZERO_IN_DATE,NO_ZERO_DATE,NO_ENGINE_SUBSTITUTION'"); $sql = "SELECT ".'*'." FROM `" . DB_PREFIX . "product`"; $query = $db->query($sql); if ($result = $db->query($sql)) { while ($row = $result->fetch_assoc()) { echo $row['product_id'].$row['model'].$row['price'].$row['quantity']."\n"; } $result->close(); } $db->close();

さいごに

筆者は、linuxのcron想定で、チェックもコンソール上しか確認していません。web版でのアクセスの場合パーミッションなど、外部からのアクセスも想定する必要があると思います。

まぁ、直接PHP関数使用して、SQL文書いてもよかったのですが、既存のライブラリとか使えたほうが便利かなと思いながら・・・

あと、注意点としては、opencartのDBライブラリは、query関数で、全件メモリに積んでしまうので、バッチに不向きかもしれません。

なので別途、fetch_assocなどで1ループずつ処理したほうがよい感じです。

関連記事

OpenCartのエクステンションインストール&作成5

前回の記事はこちらから
https://www.omakase.net/blog/2021/08/opencart-ext5.html

OpenCartのエクステンションインストール&作成4

記事はこちらから
https://www.omakase.net/blog/2021/08/opencart-ext4.html

OpenCartのエクステンションインストール&作成3

記事はこちらから
https://www.omakase.net/blog/2021/08/opencart-ext3.html

OpenCartのエクステンションインストール&作成2

記事はこちらから
https://www.omakase.net/blog/2021/08/opencart-ext2.html

OpenCartのエクステンションインストール&作成1

記事はこちらから
https://www.omakase.net/blog/2021/08/opencart-ext1.html

OpenCartのインストール

記事はこちらから
https://www.omakase.net/blog/2021/07/opencart.html

関連記事