これで光がさした

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すればよいのです。

Ajax synchronousの威力

先週木曜日から土曜日と神戸国際会議場および展示場において、CCT 2019が開催されました。あいにくの雨でしたが、企業協賛がありそれなりに人は集まっていました。

その初日夜に、さくら会 高橋病院において鎌倉ライブ臨時実行委員会を開催しました。ここで、例の Ajax async: false を実際に多量データ入力で用いたのです。まるて field testingでした。

結果は? ばっちりでした。やはり僕の予想したように、これまでのつまづきは、Web Browserが非同期で動作していたからなのです。ここでの「非同期」の意味は、Browserの main threadが、各プログラム単位の関数の戻り値を待たずに、その要求を Queに置くだけで、さっさとプログラムを次のものに変更していく、そんな意味です。これは見かけは turn overが早く、ユーザーは待たされません。

しかしながら、必要なデータを受け取らずに次のプログラムユニットに移行してしまう、ということなので、databaseより適切なデータもらう場合にはまずいことになるのです。そこで、同期が必要なのです。つまりmSec単位で戻り値を待つのです。

これを行ったところ、懸案の web databaseとのやりとりでのデータ欠損問題は全て解決しました。ものすごい威力です。データ入力が本当にスムーズに動作するようになったのです。

Ajaxに悩んだ二年間

現代のWeb PageはAjax通信を用いてページの書き換え無しに表示データを更新する仕組みが広く使われています。Ajax = Asynchronous JavaScript and XMLという訳の分からない言葉の頭文字をつなげた造語です。Ajaxが提唱されたのは、古く Internet Explorer5.0の時代に遡ります。ここいら辺に関しては、やはり Microsoft社とIBM社の功績が大きいようです。このIBMのエンジニアが投稿されたブログに詳しく書かれています。

僕もjQueryを用いてこのAjaxという仕組みを用い、データをデータベースから読み出しそれを用いてホームページのDOMを書き換え、動的にページを画面更新無く刷新するようなページをいくつも作成してきました。実はこれもIBMのエンジニアのブログを読んで出来るようになったのです。

さて、jQuery + PHP + MySQLを用いたAjaxはこれまでに色々なサイトで作成してきました。そのほとんどは期待した通りに動作してきたのですが、一つだけ躓く場面があったのです。現在の鎌倉ライブHpは2017年に原型を作り、それを踏襲してきたのですが、基本的概念は、Web上のMySQL databaseにデータを入力して、ユーザー・ページではその databaseからデータを読み出してHpに反映する、そのようにしたのです。

もちろん DBにデータ入力する時にはPWで保護された部分にアクセスし、一般ではアクセスできないようにしています。この時問題となったのは、下記のプログラム部分です。それが不思議なことにうまく行ったり、行かなかったりするのです。

 function ajax_search() {
$( "#search_results" ).show();
var search_val = $( "#search_term" ).val();

$.post( "tri_chair_mod_add01new_backend.php", {
    search_term: search_val
}, function ( data ) {
    if ( data.length > 0 ) {
        $( "#search_results" ).html( data );
    }
} );

  }

これが時にうまく動作して時に動作しないのです。この原因についてどうしても難しすぎて分からなかったのですが、色々考えている内に、Ajaxとは Asynchronous (=非同期)とうのが本質だと思ったのです。Web pageは非同期で表示していかないとユーザーが待たされることになります。ですから、ある画面を描く時にも、あるいはデータを受け取る時にもどちらかがどちらかの完了を待つ(=同期)することが無く、どんどん進んで行くのです。これが原因ではないかと思いました。そこで以下のように変更したのです。

  function ajax_search() {
$( "#search_results" ).show();
var search_val = $( "#search_term" ).val();
        $.ajax({
            type: 'POST',
            url: "tri_chair_mod_add01new_backend.php",
            dataType: 'html',
            data: {
                search_term: search_val
            },
            async: false,
            success: function(data) {
                if ( data.length > 0 ) {
       $( "#search_results" ).html( data );
                }
            },
            error: function(XMLHttpRequest, textStatus, errorThrown) {
                alert("Ajax error happened!");
            }
        });
  }

つまり、Ajaxのdefaultである async: trueというのを敢えて async: falseにしたのです。つまり同期をとるようにしたのです。これで長年の懸案が解決しました。とっても難しい概念です。

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かどうかを判定する、という方法がありますね

.bash_profileが反映されない!!

先日来 terminalの挙動がおかしくなっていました それは根本的には .bash_profileが反映されない、というものでした
したがって、たとえば composerにより laravel/installerをインストールしても、それが反映されないのです。正確に言えば、もっと訳の分からない挙動を示していいたのです
つまり、

$composer global require "laravel/installer"

として MacOSに Laravel installerをインストールします。そうすると bashの設定ファイル ~/.bash_profileの最後にきちんと以下の一文が書き込まれます

export PATH="/Users/******/.composer/vendor/bin:$PATH"

これにより terminalを再起動すれば、その部分も読み込まれ

$echo $PATH

とすれば、きちんと環境変数 PATHに追加されている筈です!

ところが、これが反映されないのです 何でだ??? もちろん

source ~/.bash_profile

として明示的に.bash_profileを読み込ませれば反映されますが、そうせねば反映されないのです。これは bashが壊れたか? とまじに思いました。

しかし、発見しました ネットでは見つけられなかったので誰か困っている方もおられると思いますのでここに記録しておきます。

ターミナルのメニュー
ターミナルのメニューから環境設定を選択する
環境設定メニュータブからシェルを選択
環境設定メニュータブからシェルを選択
シェルタブ選択すねると、「シェル無いで実行」というチェックボックスがある
シェルタブ選択すねると、「シェル無いで実行」というチェックボックスがある

このチェックボックスをチェックするとシェル内で新たなまっ更なシェルが立ち上がる感じで、~/.bash_profileが読み込まれません!!!

なんとなんとこんなオプションがあったなんて!!!

 

ようやく前に進めました

入門Haskellプログラミングを読みながら Haskellの勉強を未だに続けています 何回も何回も挫折の連続ですが、ようやくサンプル・プログラムが作動しました

 

— $stack ghci addressLetter.hs で読み込む
— そして以下のようにこの関数を呼び出すと出力が適切に変化する
— *Main> addressLetter (“Bob”, “Jones”) “sf”
— “Bob Jones – PO Box 1234 – San Francisco, CA, 94111”
— *Main> addressLetter (“Bob”, “Jones”) “ny”
— “Bob Jones : PO Box 789 – New York, NY, 10013”

  

addressLetter name location = locationFunction name
  where locationFunction = getLocationFunction location

  

sfOffice name = if lastName < “L”
                then nameText
                  ++ ” – PO Box 1234 – San Francisco, CA, 94111″
                else nameText
                  ++ ” – PO Box 1010 – San Francisco, CA, 94109″
  where lastName = snd name
        nameText = (fst name) ++ ” ” ++ lastName

  

nyOffice name = nameText ++ ” : PO Box 789 – New York, NY, 10013″
  where nameText = (fst name) ++ ” ” ++ (snd name)
renoOffice name = nameText ++ ” – PO Box 456 – Reno, NV 89523″
  where nameText = snd name

  

getLocationFunction location = case location of
                               “ny” -> nyOffice
                               “sf” -> sfOffice
                               “reno” -> renoOffice
                               _ -> (\name -> (fst name) ++ ” ” ++ (snd name))
  

このようなプログラムです 本からコピーしましたが、HaskellではPythonのようにインデントにも論理的に重要な意味があり、それを間違えると作動しませんし、compileもできません 何回はねられましたが最後に動作しました 出力例もコメントに記載しています

だいぶん頭脳が Haskell脳になってきました

最近感じるのですが、これまでの半年間以上に渡る苦闘の末に、いやまだまだ末ではないのですが、自分の思考がなんだか変わりつつあるのを自覚するようになってきました。要するに Haskell脳になってきているのです。もっともその道のプロの方から見れば「赤ちゃん」のように幼稚な脳でしょうが、それでも変わりつつあります。

そのように自覚するのは、別に Haskellの勉強をしたり、プログラムを書いたりしている時ではないのです。日常生活で、フト今までとは違った思考をしているのに気づくのです。ようやくここまで来ました

-- Haskellで書いた
--リストより先頭文字が一致した項目
--を削除するプログラム
-- remove0.hs

remove' hanbetsu [] = []
remove' hanbetsu (x:xs) = if hanbetsu x
                          then remove' hanbetsu xs
                          else x:remove' hanbetsu xs

test_array = ["apple", "banana", "avogado"]

このソースコードは remove0.hsとしてセーブされています。
これでターミナルから以下のように打ち込みます

$stack ghci

これによりHaskell Interpreterが立ち上がりますので以下のようにプログラムのソースコードである remove0.hs

Prelude>:l remove0.hs

とすることによりコンパイルされますそして

Main>remove' (\(x:xs) -> x == 'b') test_array

とすることにより”banana”のみ無くしたリストが得られます。

まだまだ分からないことだらけ

今朝実は北京経由で西安に入ります それで早朝ですが、突然 node.jsをインストールしようと思いました こんなものとうの昔にインストールしてあった筈ですが、さっきひょんなことで homebrewをアンインストーるして、再びインストールしたのです。そんな訳で homebrewでインストールしてあった node.jsも消えてしまったのです。

「うん? どうやれば node.jsインストールできるんだっけ?」

そこで google博士に聞いて見ました ここにヒットし、とても最近の uploadなのでこれが最高!と思いましたね、そして指示に従いインストールしたのです キモは最後の最新の node.jsをインストールするというこのコマンドです

$nodebrew install-binary latest

ところが、これがエラーが出てどうしてもインストールできないのです。sudoにより権限昇格しても駄目なのです!! 結構こんな時の僕の気分は深海の如く deep blueとなりますね。

それでもやはり朝でした 未だ元気な僕でした ふと思ったのです 何でこんなコマンド入れるのかな? もっと素直に

$brew install node

で良いのでは?

そこでやったところ一発で node.jsがインストールされ、今現在僕のターミナルでは

$node -v
v12.0.0

という具合に最新 node.jsが戻ってきます やったね!!!

僕のbashに一体全体何が起こったのか?

昨日TAVI三例とMitraClip一例の合間に突然のごとく気がついたのです また Visual Studio Code (VS Code)上でかんたんなHaskell programをテストがてらに書いていて、それを VS Codeのターミナルで走らせようと思ったところ、なんとなんと VS Codeターミナル画面から command promptが消失しているのです

これって、要するにコマンド打ち込めません $stack ghc ****.hsとして Haskellプログラムをコンパイルしようとても、なにせその $ が無いのです!!!

まさか、と思い Macのターミナルを立ち上げるとここにも $が無いのです これは大変な事態になりました 何も悪いことはしていません それなのに突然そんなことになったのです 前日はそんなことありませんでした

ひょっとして bashでなく zshでは大丈夫では? と zshを $より立ち上げようとするのですが何しろその $が無いっ!!

きっと、~/.bashあるいは ~/.bash_profileという bashの設定ファイルが壊れたためか? と思いそれを何とか VS Codeの「開く」という graphical interfaceで開こうとしても、今度は 隠しファイル(先頭に .がついたファイルで通常の Macからは見ることも存在も知ることができないファイル)を調べようとしても、何しろそれが見れないのです。そこで、今度は「コマンド」+「シフト」+「.」を押したところ、隠しファイルを見ることができましたので、それで両方の設定ファイルを調べても何も変わっていないのです

今度はとりあえず、「ターミナル」の「環境設定」から立ち上がりシェルを zshに変更し、とりあえずターミナルで zshを立ち上げそれにより操作をしました。まずは、この環境設定から、zsh上で $/bin/bash –version により現在のシステムbashの versionを調べると version 3.2.57(1)となっていました

これは MacOS Mojaveをインストールすると立ち上がる bashですが、何しろ現在の bashは version 5.0.11なので相当に古いものです

そこで次にzshより立ち上がるコマンドをbashにしたのです そして、homebrewで最新の bashをインストールしました

これにより $which bashとすると /usr/local/bin/bashとなり、bash –versionも version 5.0.11となりました

今は訳のわからないままこの状態で動かしています 一体全体何が突然起こったのでしょうか? どなたか Unixに詳しい方教えて下さい