cafemilk @ ウィキ

データベース ログデータベース

ログデータベース

  • CAFEMILK SHOPIING CART V5 ではカンマ区切りCSV形式のデータベースを用います。
    • 文字コードは UTF-8N となります。
    • エクセルの書式に対応しています。
  • データベース運用の方法は用途に合わせて基本データベースとログデータベースの二種類があります。
  • データベース関連の処理はフレームワークとなっていますので、カスタマイズ時の実装作業が楽です。
    • レコードの各項目は SQL のようにカラム名をつけて操作することができ、効率的です。
  • 独自仕様であるため、SQL に常態化しているようなデータベースインジェクション脆弱性の危険がありません。

ログデータベースの概要

  • ログデータベースは、レコードを収めた10のファイルとそのカラム名を収めたファイルの11ファイルからなるデータベースを運用する形態となります。
    • レコードは古くなると消えます。(ログローテンションします。)
    • Flock を用いてロックすることはしません。
    • ログデータベースでは書き込みは追記しかできません。
  • ログデータベースを扱うモジュールのファイル名は以下の通りです。
cafemilk_database_log.pl
  • cafemilk_database_log.pl のあるディレクトリは以下の通りです。
[Apache_server]
 └ [cgi-bin]
    └ [pl]
  • ログデータベースの扱うデータベースのファイルは例えば以下の通りです。
item_news.0.log.csv.cgi : 新着商品のレコード0
item_news.1.log.csv.cgi : 新着商品のレコード1
item_news.2.log.csv.cgi : 新着商品のレコード2
item_news.3.log.csv.cgi : 新着商品のレコード3
item_news.4.log.csv.cgi : 新着商品のレコード4
item_news.5.log.csv.cgi : 新着商品のレコード5
item_news.6.log.csv.cgi : 新着商品のレコード6
item_news.7.log.csv.cgi : 新着商品のレコード7
item_news.8.log.csv.cgi : 新着商品のレコード8
item_news.9.log.csv.cgi : 新着商品のレコード9
item_column_list.csv... : 新着商品のカラム名
  • データベースは標準にてセーフモードで運用されます。
    • パーミッションファイルのないディレクトにあるデータベースの読み書きはできません。
  • 標準のセーフモードは以下のように指定されています。
$config->{database}{safety} = '1';
  • $config->{database}{safety} を設定しているファイルは以下の通りです。
[Apache_server]
 └ [cgi-bin]
    └ [config]
       └ [admin]
          └ config_basic.pl
  • セーフモードにて要求されるパーミッションファイルは以下の通りです。
    • ファイルの内容は何でもかまいせん。
[permit_database_connect.txt]

ログデータベースの操作のサンプル

  • 以下は、ログを追記する場合のサンプルとなります。
まずはデータベース接続
my $log_database = Cafemilk_database_log->connect
 ({
 config => $config,
 userdata => $userdata,
 log_error => $log_error,
 log_alert => $log_alert,
 status => $status,
 column_filename => 'log/access_log_column_list.csv',
 column_separator => ',',
 database_filename => 'log/access_log',
 database_separator => ',',
 record_stack => $config->{database}{log_stack}{common},
 });
ログとして書き込む内容の作成
my $error = "@{$log_error}";
my $alert = "@{$log_alert}";
$error =~ s/\x0D\x0A|\x0D|\x0A//g;
$alert =~ s/\x0D\x0A|\x0D|\x0A//g;
my %records =
 (
 id => $userdata->{'time'},
 time => $userdata->{'time'},
 admin_name => $userdata->{admin_registry_values}{admin_name},
 user_name => $userdata->{user_registry_values}{user_name},
 execute => $userdata->{request_values}{execute}[0],
 ip_address => $ENV{'REMOTE_ADDR'},
 referer => $ENV{'HTTP_REFERER'},
 # post => $ENV{'CONTENT_LENGTH'},
 # get => $ENV{'QUERY_STRING'},
 # cookie => $ENV{'HTTP_COOKIE'},
 # error => $error,
 # alert => $alert,
 );
追記
$log_database->postscript(\%records);
終了処理
undef $log_database;
  • 以下は、最後のレコードを取得する場合のサンプルとなります。
my $database = Cafemilk_database_log->connect
 ({
 config => $config,
 userdata => $userdata,
 log_error => $log_error,
 log_alert => $log_alert,
 status => $status,
 column_filename => 'database/forum_thread_column_list.csv',
 column_separator => ',',
 database_filename => 'database/admin_forum_thread',
 database_separator => ',',
 record_stack => $config->{database}{session_stack}{admin_forum}{thread},
 });
条件に合う最後のレコードを取得
my $extract_database = $database->extract_last_record
 ({
 extract_column_name => 'thread_id',
 extract_column_value => $message_values{thread_id},
 });
%thread_values にレコードのカラム名と値を格納
%thread_values = $database->get_values_argument
 ({
 database_values => $extract_database,
 });
undef $database;
  • 以下は、最後のレコードを取得して内容を修正し、追記する場合のサンプルとなります。
my $database = Cafemilk_database_log->connect
 ({
 config => $config,
 userdata => $userdata,
 log_error => $log_error,
 log_alert => $log_alert,
 status => $status,
 column_filename => 'log/sale_count_column_list.csv',
 column_separator => ',',
 database_filename => 'log/sale_count',
 database_separator => ',',
 record_stack => 10,
 });
my $extract_database = $database->extract_last_record
 ({
 extract_column_name => 'dummy',
 extract_column_value => 'count',
 });
%count_values にレコードのカラム名と値を格納
my %count_values = $database->get_values_argument
 ({
 database_values => $extract_database,
 });
%count_values の変更
$count_values{count} ++;
$status->{sale_count} = $count_values{count};
$count_values{id} = $userdata->{'time'};
$count_values{time} = $userdata->{'time'};
$count_values{dummy} = 'count';
追記
$database->postscript(\%count_values);
undef $database;
  • 以下は、データベスーから特定の条件に合うレコード(複数)を抽出して、抽出された各レコードを順次処理していく場合のサンプルとなります。
まずはデータベース接続
my $database = Cafemilk_database_log->connect
 ({
 config => $config,
 userdata => $userdata,
 log_error => $log_error,
 log_alert => $log_alert,
 status => $status,
 column_filename => 'database/item_column_list.csv',
 column_separator => ',',
 database_filename => 'database/item_news',
 database_separator => ',',
 record_stack => $config->{database}{session_stack}{item}{news},
 });
全レコードの読み込み
$database->get_record_all();
追記により重複しているレコードを最新のものを除いて削除
$database->merge_database
 ({
 column_name => 'item_id',
 });
完全一致カラム抽出処理
my $target = 'multiprice';
$database->match_database
 ({
 column_name => 'item_type',
 match_word => $target,
 });
検索文字列の用意
文字列はスペース区切りで AND 検索となる
my $words = $input_values{'search'};
$words = Cafemilk_basic::decode_escape
 ({
 config => $config,
 userdata => $userdata,
 log_error => $log_error,
 log_alert => $log_alert,
 status => $status,
 text => $words,
 });
検索の対象となるカラムの指定
my @columns =
 (
 "item_id",
 "name_$userdata->{language_type}",
 "text_1_$userdata->{language_type}",
 "text_2_$userdata->{language_type}",
 "manufacturer_$userdata->{language_type}",
 "table_value_1_$userdata->{language_type}",
 "table_value_2_$userdata->{language_type}",
 "table_value_3_$userdata->{language_type}",
 "table_value_4_$userdata->{language_type}",
 "option_name_1_$userdata->{language_type}",
 "option_name_2_$userdata->{language_type}",
 "option_name_3_$userdata->{language_type}",
 );
検索実行
$database->search_database
 ({
 search_column => \@columns,
 search_words => $words,
英字の大文字と小文字の区別
1 でしない
 character_mode => '1',
 });
並び替え処理
$database->sort_database
 ({
 column_name => "price_main_$userdata->{currency_type}",
逆順処理
1 で逆順
 reverse_mode => '0',
並び替えモード
number_quick で数値モード
character_quick で文字モード
 sort_mode => 'number_quick',
 });
抽出・検索・並び替えされたレコードを取得
my @lines = $database->get_extract_database();
レコード処理
foreach (@lines)
 {
 my $line = $_;
レコードの分割とカラム名との関連づけ
 my %target_values = $database->get_values_argument
  ({
  database_values => $line,
  });
ここで例えばレコードの内容の表示処理を行う
 print $target_values{item_id};
 }
終了処理
undef $database;

更新履歴