TRY AND ERROR

気になったこと、勉強したこと、その他雑記など色々メモしていきます。。Sometimes these posts will be written in English.,

Cakephp3のShellがcronで動かなかった理由

デイリーの集計絡みのバッチを書いていてちょいはまったのでメモ。


まず、 CakeのShellをcronで叩く際のOfficialの記載はこう

15 0 * * * cd /full/path/to/app && bin/cake myshell myparam

これが動かなかった。


次に試したのは、そもそもcdする必要ないんじゃないかということで
こんな感じでやった。

15 0 * * * /full/path/to/app/bin/cake myshell myparam

しかしこれもだめ。



cron通さずに普通に実行してみると、これは動いた!

 $ /full/path/to/app/bin/cake myshell myparam



ログを出してみると、cronで叩いたときのphpのバージョンが違っていたので、
今回はcakeの問題ではなかった。。

PHP Warning:  PHP Startup: Unable to load dynamic library '/usr/lib64/php/modules/mecab.so' - /usr/lib64/php/modules/mecab.so: cannot open shared object file: No such file or directory in Unknown on line 0
PHP Fatal error:  You must enable the intl extension to use CakePHP. in 


バイナリではなくbin/cake.phpphpのバージョンを指定して叩くことで対応しました。

15 0 * * * /usr/bin/php70 /full/path/to/app/bin/cake.php myshell myparam

phpQueryでタグの破片などのノイズを除きつつテキストっぽいものだけを取得する。

とりあえず行き着いた方法をメモします。
htmlによっては、先頭にxmlステートメントが混ざってくる場合が稀にあるので、最初に除去しておく。
さらに、なぜかscriptやstyleの破片などがノイズとして紛れ込むケースが多々あるので、これらも除去。

newDocumentする前の下ごしらえが結構重要なので、この辺のチューニングが鍵になります。

// Remove xml statement.
$html = preg_replace('/^<\?xml.*\?>/', '', $html);
// Remove noises.
$html = preg_replace(array("/\r/","/\n/","/\r\n/","/<br \/>/","/<br>/","/<script.*?\/script>/","<style.*?\/style>","/ /"),"",$html);

$doc = phpQuery::newDocument($html);
$title = $doc["title"]->text();
$body = $doc['body']->text();

InternetExplorerでjsのメソッドの引数のデフォルト値が使えない

めちゃめちゃあせったー......orzって話です。

function test(a,b=[]) { // IEだとここで落ちる
    console.log(a)
    console.log(b) 
}

こういう書き方をするとIEだとスクリプトが落ちる。(ちなみにIE11)
Chrome,FFは動きます。

とりあえず typeof b == "undefined" で判定しましたが、
ベストプラクティス知りたいです。。

mysqlのレプリケーションでスレーブがreadonlyにならない!!

久々のブログです。。

 

mysql5.7でmaster-slaveのレプリケーション設定でハマったのでメモ。

 

slaveをreadonlyにしたかったので、my.cnfに

read_only=1を追加しサービス再起動、試しにslaveに更新系のクエリを投げてみたところ、更新できちゃう!!

 

意味が分からず格闘すること数時間、以下のようなドキュメントを発見。

 

Finally, in order to make the slave instance read-only, parameter read_only is set to 1. You should be careful with this option since it doesn’t completely prevent changes on the slave. Even when the read_only is set to 1, updates will be permitted only from users who have the SUPER privilege. MySQL has recently introduced the new parameter super_read_only to prevent SUPER users making changes. This option is available with version 5.7.8.

MySQL Master-Slave Replication Tutorial | Toptal

 

 

どうやら、そもそもroot系の権限があるユーザーでは更新できる仕様らしいです。


基本的にアプリ用に CRUD権限を付与しているユーザーでDBAを使っていればread_only=1でOKだと思いますが、v5.7.8からsuper_read_only=1にすると上記ユーザーでも更新不可にできるようです。

 

slaveのmaster昇格などを考えないのなら、read_only=1に加えてsuper_read_only=1を設定しておいてもいいかもしれません。

 

CakePHP3でPC/スマホのviewを切り替える方法

CakePHP3を使ってて一番助かったなあと思う機能が、PC/スマホのview切り替えです。

実装はめちゃくちゃ簡単。

・PC版のviewは通常通りsrc/Templateに作成します。
・plugins直下にスマホ用のディレクトリを作成(今回は「Sp」というディレクトリを作成)
・plugins/Sp/src/Template/を作成し、PC版と同じディレクトリ構造でスマホ用のviewを作る。
・コントローラは共通でOKで、AppControllerのbeforeRenderに切り替え処理を書く
※plugins/Sp/Template内にコントローラのアクションに紐づくスマホ用のveiwがない場合は、通常のsrc/Template内のPC版viewが読み込まれる。

public function beforeRender(Event $event) {
        // ----- 処理 -----

        // PC/スマホのview切り替え
        if ($this->request->isMobile()) {
                // plugins/Sp/Template内のviewが読み込まれる
                $this->viewBuilder()->theme('Sp');
        }
}


めっちゃラクw

Excelでcsvを開いたときに「SYLK:ファイル形式が正しくありません。」という警告が出る件

ちょっとハマった。。。

PHPでDBの取得結果をCSVーDLするスクリプトを書き、実際にDLして開いたところ「SYLK:ファイル形式が正しくありません。」という警告が出ました。
最初は、エンコードやらでなんかおかしなことになったか?と思ったんですが、警告が出るのはExcelで開いた時で、テキストエディタなどで開くと出ない。

ちょっと調べたところ、同様の問題について書いた記事がたくさん出てきました。

原因はExcelの仕様で、先頭セルの値が文字列の「ID」だとSYLK 形式のファイルと認識されてしまうとのこと。

https://support.microsoft.com/ja-jp/kb/215591

マイクロソフトのサポートページでは「開くことができない」とありますが、実際は警告が出るものの開けるようです。


解決方法としては、先頭に空白行を入れるか先頭セルの値を「ID」以外にすればOKとのことですが、DBレコードをCSV出力する機会は結構あると思いますし、さらにレコードの先頭カラムがIDであるケースも多いと思うので、過去にハマった人も多いんじゃないかな。。
今まで引っかからなかったのが不思議なくらいですw

ちなみに、今回は先頭セルを「ID」から「id」に変えたところ警告は出なくなりました。


こんな仕様があるとは想像もできんかったというお話でしたw

Python3 with djangoでエクセルで文字化けしないcsvをダウンロードさせる

よくあるcsvダウンロード機能ですが、エクセルで開くことを想定して作らなければいけないケースが多々あると思います。
今回、エクセルで開いた時に日本語が文字化けしないcsvのダウンロード機能をpythonで書いてみます。
使っているフレームワークDjango

標準のcsvモジュールだとunicodeがサポートされていないとのことなので、unicodecsvを使います。
GitHub - jdunck/python-unicodecsv: Python2's stdlib csv module is nice, but it doesn't support unicode. This module is a drop-in replacement which *does*. If you prefer python 3's semantics but need support in py2, you probably want https://github.com/ryanhiebert/backports.csv

unicodecsvはpipでインストールできます。

pip install unicodecsv


基本的には標準のcsvモジュールと似ていますね。

from django.http import HttpResponse
import unicodecsv as csv

def csvdl(request):
    ret = HttpResponse(content_type="text/csv")
    ret["Content-Disposition"] = "attachment; filename=name.csv"
    w = csv.writer(ret, encoding='cp932')
    w.writerow(["あいう", "えお", ...])    
    return ret

encoding='cp932'を使えるところがミソ!!