カテゴリー
PHP SQL ただの現状記述 (Daily Activities) インターネット一般 (Internet General) プログラミング (Programming)

昨日よりぶったまげました

いやあ 昨日この現象に気づきました 原因精査にもう一杯一杯となってしまったのです 色々な懸案事項をそっちのけで原因究明に身も心も取られてしまいました

しかし、突然閃きが起こり全て解決しました。それは西暦年号が当然ながら現在は 2020年であり、2019年ではないからだったのです。

現在、鎌倉ライブデモンストレーションの Home Pageにアクセスして例えばコメディカル・セッションを覗いて下さい

そうするとこんなふうにもぬけの殻状態のページが見えるでしょう

もぬけの殻のページ
もぬけの殻のページ

我ながら最初にこの画面見た時、「あーっ、とてつもなく良くないことが起こっている、ページを乗っ取られたのかな」と頭の中が真っ白でした。冷静になり、local serverで動かしても同様なのです。これはおかしい、サーバーを乗っ取られたのであれば、ローカルでも同じ現象が出るのはおかしい、そのように考えました。

そして今朝、シンガポールでコーヒーを飲みながらテストしていて気が付きました。それは kamakuralive.net全体の設定ページに仕込んである次の一文です

$this_year = date('Y');

これにより例えば 次のSQL文が発行され、データベースからデータを読み込むのです

$stmt = $pdo->prepare( "SELECT * FROM `session_tbls2019` WHERE `class` = 'com' AND `year` = '" . $this_year . "' ORDER BY `sessionNo` ASC;" );

要するに、プログラムを時間経過から独立させるために、わざわざ $this_yearという変数を設定し、それを用いているのです。

当然のことながら、現在の date(‘Y’); という文は、’2020’を返します。従って、それに従う SQL文ではデータが無く、空白となるのでした。つまり年号が 2019年から 2020年に変わった途端に見かけ上データが表示されなくなるのでした。でもこれっていいことですね。昔のページが自動的に消失するに等しいのですから・・・

カテゴリー
PHP ただの現状記述 (Daily Activities) インターネット一般 (Internet General) コンピューター (Computer) プログラミング (Programming)

知らなかった

さて、MySQL databaseより UTF-8で文字コード化されているデータを取得し、それを .csv形式で出力するこにより、Excelで読み込みたいと思っているのです。

しかし、先日 uploadしたようにこれはなかなかの難物なのです。普通にやれば必ず激しい文字化けで使い物になりません。ようやく、local database/serverで走らせて文字化けしないようになりましたが、これを Internet Serverに uploadして走らせると、HTTP ERROR: 500という訳の分からないエラーが出て走らないのです。

そこで検索して、かろうじてこのページにヒットしました。これによれば、サーバー処理で時間がかかったりメモリーを消費したりしてエラーが出るようです。ここに書いているように

set_time_limit(600); 
ini_set('memory_limit', '2048M');

この二行を書き加えることにより見事に解決しました。

カテゴリー
PHP ただの現状記述 (Daily Activities) プログラミング (Programming)

これで光がさした

PHPと Excelの関係はなかなか厄介なものがあります それと言うのも、Excelでは昔の 16-bits DOSの名残でずっと日本語文字コードとしてはいわゆる Shift-JISを用いているのです。これは別名 CP932とも呼ばれているものです。

ビジネスの世界では、Excelがデファクト・スタンダードであり、膨大なビジネス文書でこの Shift-JISが用いられているため、今更それを世界標準の UTF-8という文字コードに変更することができないのです

要するに悪しき昔の名残を引きずっているのですね

このことが実際のブログラミングでは問題となります もっとも英語圏の人々には「何言っているの?」てなもんで関係無いのですが、我々のように日本語を用いていると即刻問題となるのです。

何故ならばデータベースからデータを取得し、それを加工してから表計算ファイルに出力しても、その出力は UTF-8でされるので、Shift-JISで開く Excelでは途端に文字化けするのです。これを防ぐためには勿論、Excelが UTF-8を正しく読み取れれは良いのですが、それがそうは行かないのです。あるいは UTF-8から Shift-JISに変換してファイルに書き込めばいいはずですが、それまで自分で試したブログラムではなかなかうまく行かないのです。

しかし、今回ようやくめぐり逢いました それはこんなテスト・プログラムで検証しました

// https://qiita.com/ikemonn/items/f2bc4f9f834c989084ff
$rows[ 0 ][ 0 ] = "00";
$rows[ 0 ][ 1 ] = "齋藤 滋";
$rows[ 0 ][ 2 ] = "齋藤 滋です";
$rows[ 1 ][ 0 ] = "10";
$rows[ 1 ][ 1 ] = "SAITO SHIGERU";
$rows[ 1 ][ 2 ] = "さいとう";

$header = "Content-Type: text/plain";
$fp = fopen( 'isample.csv', 'w' );
stream_filter_prepend( $fp, 'convert.iconv.utf-8/cp932' );
fputcsv( $fp, $header );
foreach ( $rows as $row ) {
  fputcsv( $fp, $row );
}
fclose( $fp );

これでバッチリです。

もちろんこのコードのままですと、Excel内部でも csv形式となっているので、これを Excel標準形式で saveすればよいのです。

カテゴリー
Javascript jQuery PHP インターネット一般 (Internet General) コンピューター (Computer) プログラミング (Programming)

jQuery libraryの読み込み判定

jQueryや bootstrapは CDNよりそのソースコードを読み込むのが常道です。これには理由があり、まず CDNはライブラリ読み込みに最適化されているので、自分のサーバーから読み込むよりも早い、そしてCDNより読み込めば プログラムの置かれている階層によらず読み込み先を変更する必要が無い、というものです。

ただ、localhostでインターネット接続せずにプログラムを書いていると CDNから読み込めずにプログラムが作動しなくなることもあります。localhostで開発している時にはこれでは困ります。そんな時に、インターネット接続しているか否かで自動判定すれば助かります。そのコードとしては、

 

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>if (jQuery) document.write('<script src="lib/jquery.js"><\/script>');</script>

としたり、あるいは jQueryが既に読み込まれているか否かの判定として以下のようにするか

<script>window.jQuery||document.write('<script src="lib/jquery.js"><\/script>');</script><

とするか、あるいは phpを走らせて

<?php
  if ($_SERVER['SERVER_NAME'] === 'locallhost'
?>

として localhostかどうかを判定する、という方法がありますね

カテゴリー
Haskell PHP SQL ただの現状記述 (Daily Activities) コンピューター (Computer) プログラミング (Programming)

Haskellに惑わされ – 6

例えばこうです 僕が良く Web programmingする時に使用する PHP言語ですが、database言語であるSQL (僕が使用しているのは open sourceの MySQL言語です)と連携してSQLサーバーよりデータを取得し、それをサーバー内で PHP言語により加工し、その結果を http通信でクライアント側 つまり、一般ユーザーに送っているのですが、その部分の肝腎の SQL serverからの PHPでのデータ取得部分の一例はこんなものです

$row_session = $stmt_session->fetch( PDO::FETCH_ASSOC );
$stmt_role = $pdo->prepare( "SELECT MAX(`created`) FROM `role_tbls`;" );
$stmt_role->execute();

ここで出てきましたよね この部分です

"SELECT MAX(`created`) FROM `role_tbls`;"

この部分を良く見ると、

`created` や`role_tbls`

のように何だかさっきのもの (`)ではさまれていますね これは実は SQL構文規則では不要なものです しかしながら、この列が SQLの列名であることを分かりやすくするためにわざわざ用いているのです

つまり、 (`)というものはプログラム解析上では何の意味も持たない飾りだということです

従ってこの部分に(‘)というものを使用すると途端に文法エラーとなりプログラムは走りません これと同様のことが Haskellでも起こるのです

カテゴリー
Laravel Mac PHP ただの現状記述 (Daily Activities) インターネット一般 (Internet General) コンピューター (Computer) プログラミング (Programming)

Laravel を MacOSにインストール – つづき

さてようやく MacOS上で composerがインストールできました というか既に何ヶ月か前にインストールしていたのに忘れていたのです

そもそも composerは何か? と言えば、phpを用いて web programを書くときに必要な諸々をサクッとインストールしてくれる便利な小槌と思えばいいのです まず行うことは

$ cd ~/target-folder/

とすることにより、目標とする target-folderに移動します

次いで

$ composer create-project "laravel/laravel=5.5.*" projectName

とすることにより、Laravel version 5.5一式をこのフォルダにインストールします これは大量のファイルをダウンロードしますので数分間かかりますよっ

$ cd projectName

とすることにより今作成したプロジェクト・フォルダに移動します そうすると artisanという phpで書かれたコマンドがこのフォルダには既にインストールされていまので、

$ php artisan --V

とすれば、僕の場合には
Laravel Framework 5.5.44というものが戻ってきました 実はこの artisanというプログラムは local serverを立ち上げるものであり、これで local serverを立ち上げるとその後 Laravelでプログラムを開発する時に面倒なことを考えずにできるのです

$ php artisan serve

これで local serverが  ip address = 127.0.0.1, port = 8000で立ち上がりましたので、ブラウザのアドレス・バーで localhost:8000とするかあるいはhttp://127.0.0.1:8000と打ち込めば見事 Laravelのデモページが立ち上がります

Laravelデモページ
カテゴリー
Laravel Mac PHP ただの現状記述 (Daily Activities) インターネット一般 (Internet General) コンピューター (Computer) プログラミング (Programming)

Laravel再開

一度は挫折した Laravelに再度チャレンジです Macでインストールするのと Windows10でインストールするのでは大分やり方が異なるようです

Windows10では まずは XAMPPをインストールした方が良いようですね それでは まずは Macから ここは Terminalでの作業になりますね

まずは composerのインストールです これは簡単ですよ
$brew install composer

ところがここで以下のような膨大なエラー出現しました

==> Downloading https://getcomposer.org/download/1.8.0/composer.phar
######################################################################## 100.0%
Error: parent directory is world writable but not sticky
Please report this bug:
  https://docs.brew.sh/Troubleshooting
/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/tmpdir.rb:93:in `mktmpdir'
/usr/local/Homebrew/Library/Homebrew/utils/fork.rb:28:in `safe_fork'
/usr/local/Homebrew/Library/Homebrew/formula_installer.rb:743:in `build'
/usr/local/Homebrew/Library/Homebrew/formula_installer.rb:317:in `install'
/usr/local/Homebrew/Library/Homebrew/cmd/install.rb:326:in `install_formula'
/usr/local/Homebrew/Library/Homebrew/cmd/install.rb:256:in `block in install'
/usr/local/Homebrew/Library/Homebrew/cmd/install.rb:254:in `each'
/usr/local/Homebrew/Library/Homebrew/cmd/install.rb:254:in `install'
/usr/local/Homebrew/Library/Homebrew/brew.rb:88:in `'

こんなことで慌ててはいけません 何だか rubyで書かれた Homebrew管理プログラムが色々とシステムに書き込もうとする時に「それは越権行為だ!」というようなエラーですね こういう時は Google叔父さんに聴いてみます 検索したのは

Error: parent directory is world writable but not sticky
Please report this bug:

というものですが、そうすると早速このページにヒットしました これに従い$ sudo chmod +t /private/tmp
$ sudo chmod +t ~/Library/Caches/Homebrew
とすると Treminalからは何の返答もありませんが、再度 $brew install composerと打つと

==> Downloading https://getcomposer.org/download/1.8.0/composer.phar
Already downloaded: /Users/transradial/Library/Caches/Homebrew/downloads/5f21a93cda75f6de1acae0850021a00add848552341d23d14aa9e6afc17de4dd--composer.phar
Error: The `brew link` step did not complete successfully
The formula built, but is not symlinked into /usr/local
Could not symlink bin/composer
Target /usr/local/bin/composer
already exists. You may want to remove it:
  rm '/usr/local/bin/composer'

To force the link and overwrite all conflicting files:
  brew link --overwrite composer

To list all files that would be deleted:
  brew link --overwrite --dry-run composer

Possible conflicting files are:
/usr/local/bin/composer
==> Summary
🍺  /usr/local/Cellar/composer/1.8.0: 3 files, 1.8MB, built in 2 seconds

というように何だか インストールされたみたいです ただ、僕の場合には既に composerがインストールされているのでそれを修正した方が良いよ と出ているようですので、この指示のとおりに$ rm '/usr/local/bin/composer'
$ brew link --overwrite composer
$ brew link --overwrite --dry-run composer
とすると見事にアンイストールできました そして今度は Laravelのインストーラーをインストールするために

$ composer global require "laravel/installer"

とすると 何やらたくさんのファイルが downloadされて インストール準備段階に入りました

実はこの段階でこのインストーラーなどのパスを通さねばなりません それで

export PATH="$PATH:$HOME/.composer/vendor/bin"

という一文を ~/.bashrcの最後に書き加えねばなりません これには vimとか visual studio code (VisutalStudio Code = VS Code)を用いねばシステム領域の書き換えはできませんので、

$ code

とコマンドラインから VS codeを立ち上げようとすると何と以下のエラー出現

/Users/transradial/.pyenv/shims/python: line 21: /usr/local/Cellar/pyenv/1.2.6/libexec/pyenv: No such file or directory
/usr/local/bin/code: line 10: ./MacOS/Electron: No such file or directory

さあ困った そこで、今度は”/usr/local/Cellar/pyenv/1.2.6/libexec/pyenv”で Google検索するとすぐにここにヒットしました この指示のとおりに

$ pyenv rehash

としたところ解決し、VS codeをコマンドラインから立ち上げることが可能となりました 要するに pyenvという python仮想環境が少し破壊されたので、それを自己修正したのですね さて、このようにそと VS codeでパスを無事通し、それを現在のコマンドラインに反映させるために

$ source ~/.bashrc

したところ、無事

$ laravel --version
Laravel Installer 2.0.1

となり さあこれで laravelをインストール可能となりました

さて、今度は Windows10でも行いたいと思いますが、こちらは仮想サーバーを別に立ち上げねばならないのかな? それとも php artisanコマンドで十分なのかな? 未だ検証していません これからの楽しみですが、時間があるかなあ???

カテゴリー
PHP SQL インターネット一般 (Internet General) コンピューター (Computer) プログラミング (Programming)

思いがけないエラー原因

メルアドというのはある個人の IDとしても使用できます 中にはもちろん自分個人のメルアドを作らず、一つのメルアドを共有されている方々もおられますが、この場合どんなプライベートな連絡もその人々で共有されてしまいますので、プライバシーを保つことができません

そんなメルアドの特性からメルアドは IDとして良く使用されます そして、その人が登録されているか否かの判定にはデータベースをメルアドで検索し、見つかった個数が 0であれば登録されていない、という事実を利用します つまりプログラムに書けば以下のようになります

$stmt = $pdo->prepare( "SELECT COUNT(*) FROM `doctor_tbls` WHERE `email` = :email;" );  // (A)
$stmt->bindValue( ":email", $test-email-address, PDO::PARAM_STR );   // $test-email-addressをテストするためにpdoで変数をバインドする
$flag = $stmt->execute();  
// 検索を実行する
if ( !$flag ) {        
// エラーが無いかチェックする
  $infor = $stmt->errorInfo();
  print_r( $infor );
  exit;
}
$already_registered = $stmt->fetchColumn(); 
// COUNT(*)によりそのメルアドがDBに存在するか調べる 既に登録済のメルアドであれば、0ではない
if ( intval($already_registered) === 0 ) { 
// ここからメルアドが登録されているか否かのチェックとなる
}


if ( $already_registered === 0 ) { 
// こうするとこのブロックの中に入らない
}


if ( $already_registered == 0 ) { 
// こうするとこのブロックの中にきちんと入る
}

PHPには同一性判定として ==と ===の2つがあります ===は値のみならずその型もチェックします ですから、===の方が論理的に合っていますので、通常は ===を使用すべきです しかしながらこのように DBより読み込んできたりすると見かけは数字の0であったとしても型が異なるのです ですから、きちんと作動するようにするためには intva()関数により整数型に変換せねばならないのです これに気づくのに相当の時間がかかりました

カテゴリー
PHP インターネット一般 (Internet General) コンピューター (Computer) プログラミング (Programming)

Excelデータを二次元配列に読み込む

今 成田空港に向かう NEXの中でテストを走らせています もちろん Objectとして Excelの行や列を扱うのも良いのですが、MySQL側はあくまでも二次元配列という概念ですので、今後のために2次元配列に変換します その部分を作成しました

require '../vendor/autoload.php';

use PhpOffice\ PhpSpreadsheet\ Spreadsheet;
use PhpOffice\ PhpSpreadsheet\ Writer\ Xlsx as Writer;
use PhpOffice\ PhpSpreadsheet\ Reader\ Xlsx as Reader;
use PhpOffice\ PhpSpreadsheet\ Cell\ Coordinate;

$reader = new Reader();
//$reader->setInputEncoding('SJIS');
$spreadsheet = $reader->load( 'poster2018.xlsx' );
//$reader->setInputEncoding('SJIS');
$sheet = $spreadsheet->getActiveSheet();

$lines = array();
$max_row = 0;	// 今rowの最大数値
$max_column = 0;	// 	columnの最大値
$nlines = array(); // Columnを数字にした二次元配列

$row_counter = 0;
$column_counter = 0;
foreach($sheet->getRowIterator() as $row) {
  foreach($sheet->getColumnIterator() as $column) {
    $lines[$row_counter][$column_counter] = $sheet->getCell( $column->getColumnIndex() . $row->getRowIndex() )->getValue();
    // これで$linesという2次元配列に Excel dataが集積された
    // これからは $lines[n][m]のような二次元配列として扱うことが可能となる
    $column_counter++;
  }
  $row_counter++;
}
$max_row = $row_counter;
$max_column = $column_counter;

ここでキモとなるのが、Excelではそれぞれのセル座長は A1より始まる表記となっていることです 通常の二次元配列では[0][0]より始まる配列ですので、この変換が必要となります

また Excelファイルを扱う時何時も問題となるのが、文字コードです Excelでは DOSからの伝統で日本語文字コードは Shift-JISであり、現在のプログラミングで標準的な UTF-8とは合いませんし、文字化けが起こります

そこで、PhpSpreadSheetにも

$reader->setInputEncoding('SJIS');

というメソッドが定義されているのですが、最近の Excelで改善されたのか、何しろそのようなメソッドを使用せずに自動的に UTF-8に変換されるようです ですからこのメソッドは不要でした

カテゴリー
PHP SQL ただの現状記述 (Daily Activities) インターネット一般 (Internet General) コンピューター (Computer) プログラミング (Programming)

この10日間 悩み抜いたバグがようやく解決

さて、https://www.kamakuralive.net/ のWeb programを作る段階で、コメコメ部門のポスター発表部分がまだ実装できていませんでした その理由は唯一つ、僕がズルというか楽をしたいからだったのです

既にポスター演題が 20集まっており、それをコメコメ委員の方々が Excel形式で集計してくださっていました しかし、それを Web databaseである MySQLデータベースに読み込まねばなりません 実は既に昨年、 Excel (これはShift-J文字コード) の xlsx形式-> Text形式 (.txt)に変換 -> 文字コードを UTF-8に変換 -> .txtを MySQL databaseに読み込み という部分は作成していました

まあ作成といっても、foreachでループを回して読み込むだけなのですが・・・

今回は折角ですので、自分の勉強のためにもPHPSpreadSheetという Excelファイルを PHPで読み込むライブラリを用いることにしたのです

その部分は案外簡単に Excel file読み込みに成功したのですが、肝腎の MySQL databaseに書き込む SQL文がエラーが出るのです その部分のバグとりが全くうまくいかず 10日間以上を無駄に過ごしてしまいました いや 決して人生において無駄というのは無いでしょう そう思わねばやってらんないよっ

結局その部分を簡略化して出しましょう

try {
  // MySQLサーバへ接続
  $pdo = new PDO( "mysql:host=$db_host;dbname=$db_name_sessions;charset=utf8", $db_user, $db_password );
  // 注意: 不要なspaceを挿入すると' $db_host'のようにみなされ、エラーとなる
} catch ( PDOException $e ) {
  die( $e->getMessage() );
}

for ( $rowNo = 1; $rowNo < 24; $rowNo++ ) {
  $stmt = $pdo->prepare( "SELECT COUNT(*) FROM `doctor_tbls` WHERE `email` = :email;" );
  $stmt->bindValue( ":email", $nnlines[ $rowNo ][ 12 ], PDO::PARAM_STR );
  $stmt->execute();
  $count_same_email = $stmt->fetchColumn();

  if ( $count_same_email < 1 ) { // 既にこのメルアドは登録されているのでスキップ
     $stmt_dr = $pdo->prepare( "INSERT INTO `doctor_tbls` (`english_sirname`, `english_firstname`, `is_male`, `email`, `changed`) VALUES (:enlish_sirname, :enlish_firstname, :is_male, :email, :changed);" ); 
    $stmt_dr->bindValue( ":english_sirname", $nnlines[ $rowNo ][ 1 ], PDO::PARAM_STR );
    $stmt_dr->bindValue( ":english_firstname", $nnlines[ $rowNo ][ 2 ], PDO::PARAM_STR );
    
    if ( $nnlines[ $rowNo ][ 3 ] === 'M' ) {
      $sex = 1;
    } else {
      $sex = 0;
    }
    
    $stmt_dr->bindValue( ":is_male", $sex, PDO::PARAM_INT );
    $stmt_dr->bindValue( ":email", $nnlines[ $rowNo ][ 12 ], PDO::PARAM_STR );
    $stmt_dr->bindValue(":changed", date('Y-m-d H:i:s'), PDO::PARAM_STR);
    
    $flag = $stmt_dr->execute();
    
    if ( !$flag ) {
      echo "<h2 style='color:red;'>Error</h2>";
      $infor = $stmt_dr->errorInfo();
      print_r($infor);
      exit( $infor[ 2 ] );
    }
    
  }
}

これがエラーで書き込めません、色々と試みたのがうまく行きませんので、最後に  print_r($infor)の一行を加えて、SQLエラー出力を行いました

そうすると MySQL error code

SQLSTATE[HY093]

というのが出てくるのです これは検索すると パラメータの数が合わないなのですが、目を更にして見てみてもそんな訳はありません しかし、この 10日間の苦難の末ようやく発見しました

 

VALUES (:enlish_sirname, :enlish_firstname, :is_male, :email, :changed)

この部分で english_ とすべきを enlishとしているのですね このためパラメータの数が合わないため SQL errorとなっていたのです なんだかなあ パカみたい 10日間損した気分 でも自分が招いたものだから仕方ありません

本日はこれから 成田空港に向かいます このエラーを解決したのでポスター・セッション部分のプログラム完成できますね