階層構造の再帰処理

Posted by muchag | PHP |
初回投稿:2015-09-25 (金) 17:27:28 | 最終更新:2015-10-28 (水) 14:18:43

多次元配列の階層構造をリスト表示したくて Google 先生へ質問した結果。

【環境】
php:5.4.7
手法

時間がないので、参考サイトの中から採用したものをコピペ。

  1. $data = [
  2.     [
  3.         'hoge_id' => 2,
  4.         'hoge' => '親2',
  5.         'parent_id' => 0,
  6.     ],
  7.     [
  8.         'hoge_id' => 8,
  9.         'hoge' => '孫',
  10.         'parent_id' => 4,
  11.     ],
  12.     [
  13.         'hoge_id' => 3,
  14.         'hoge' => '子2-1',
  15.         'parent_id' => 2,
  16.     ],
  17.     [
  18.         'hoge_id' => 4,
  19.         'hoge' => '子7-1',
  20.         'parent_id' => 7,
  21.     ],
  22.     [
  23.         'hoge_id' => 7,
  24.         'hoge' => '親7',
  25.         'parent_id' => 0,
  26.     ],
  27.     [
  28.         'hoge_id' => 1,
  29.         'hoge' => '親1',
  30.         'parent_id' => 0,
  31.     ]
  32. ];
  33.  
  34. class HtmlUlBuilder
  35. {
  36.     private $data;
  37.  
  38.     public function __construct($data)
  39.     {
  40.         $this->data = $data;
  41.     }
  42.  
  43.     public function buildFromParent($parent_id)
  44.     {
  45.         $children = array_filter($this->data, function ($element) use ($parent_id) {
  46.             return $element['parent_id'] === $parent_id;
  47.         });
  48.  
  49.         if (count($children) === 0) return '';
  50.  
  51.         return '<ul>' . array_reduce($children, function ($current, $element) {
  52.             return $current . PHP_EOL . '<li>' . $element['hoge'] . $this->buildFromParent($element['hoge_id']) . '</li>';
  53.         }, '') . '</ul>';
  54.     }
  55. }
  56.  
  57. usort($data, function ($a, $b) {
  58.     return $a['hoge_id'] > $b['hoge_id'];
  59. });
  60.  
  61. $builder = new HtmlUlBuilder($data);
  62. $html = $builder->buildFromParent(0);
  63.  
  64. echo $html;
参考サイト

stack overflow:PHP多次元配列から階層リストタグ(略)を出力したい

Posted by muchag | PHP |
初回投稿:2015-09-25 (金) 17:27:28 | 最終更新:2015-10-28 (水) 14:18:43

宣言と初期化

Posted by muchag | Excel VBA |
初回投稿:2015-09-09 (水) 13:17:33 | 最終更新:2015-09-09 (水) 13:18:20

VB は独特なので、しばらく触らないとすぐ忘れる。。。
確かめずに記憶で書いているので怪しい。

【環境】
Excel:2010
基本
変数
[evba language=”vb” firstline=”” highlight=””] ‘ Dim 変数名 As データ型

‘ プリミティブ
Dim hoge As String
hoge = “Yeah”

‘ オブジェクト
Dim hoge As Object
Set hoge = Activesheet
… 処理…
Set hoge = nothing ‘ 解放
[/evba]

1行にまとめる方法

VBAやVBScriptって、変数宣言と初期化がものっそい面倒なイメージがある。

C#やJavaみたいに「int num = 0;」みたいに書ければいいのに…って思っている方は多いのではないでしょうか?

Black Everyday Company:【VB系】変数の宣言と初期化を1行で書く(VB.NET,VBA,VBScript)

ずぅぅぅぅぅぅぅぅぅっと、そう思ってました!
[evba language=”vb” firstline=”” highlight=””] Dim foo As Integer: foo = 0
Dim bar As String: bar = “hogehoge”

Dim obj As Object: Set obj = WScript.CreateObject(“WScript.Shell”)
[/evba] 素晴らしい~♪
ありがとうございます!

Posted by muchag | Excel VBA |
初回投稿:2015-09-09 (水) 13:17:33 | 最終更新:2015-09-09 (水) 13:18:20

正規表現

Posted by muchag | Excel VBA |
初回投稿:2015-09-09 (水) 13:00:25 | 最終更新:2018-09-17 (月) 10:40:28

Excel VBA で 正規表現 を使う時がきた。

【環境】
Excel:2010
準備
参照設定
[ツール]-[参照設定] Microsoft VBScript Regular Expressions 5.5
にチェック。

これで、下記のように宣言できる。


Dim objRE As New RegExp

参照設定をしない場合は、下記のごとく。


Dim objRE As Object
Set objRE = CreateObject("VBScript.RegExp")
置換
HTML タグ除去

Dim objRE As Object
Set objRE = CreateObject("VBScript.RegExp")
objRE.Pattern = "<[^>]*>"
objRE.Global = True

Dim strHoge as String
strHoge = "

hoge

" strHoge = objRE.Replace(strHoge, vbNullString)
抽出
[123]abc[789]xyz
において、[] で括られたもの以外
つまり、abcxyz を抽出する場合。


Dim objRE As Object
Set objRE = CreateObject("VBScript.RegExp")
objRE.Pattern = "\[.*?\]"
objRE.Global = True

Dim strHoge as String
strHoge = "[123]abc[789]xyz"
strHoge = objRE.Replace(strHoge, vbNullString)

書いてみて思った。
やっていることは、HTML タグ除去と同じだw
考えてみれば当然なんだけど
せっかくなので残しておく。

抽出
[123]abc[789]xyz
ここから、123, 789 を抽出したい場合。


Dim objRE As Object
Set objRE = CreateObject("VBScript.RegExp")
objRE.Pattern = "\[(.*?)\]"
objRE.Global = True

Dim strHoge as String
strHoge = "[123]abc[789]xyz"
strHoge = objRE.execute(strHoge)

If strHoge.Count > 0 Then
	Dim index As Integer
	For index = 0 To strHoge.Count - 1
		MsgBox strHoge(index).SubMatches(0)
	Next index
End If
参考サイト

マイナビニュース > パソコン:正規表現を用いてHTTPタグを除去するVBAを記述する

Posted by muchag | Excel VBA |
初回投稿:2015-09-09 (水) 13:00:25 | 最終更新:2018-09-17 (月) 10:40:28

CSV ファイル出力

Posted by muchag | PHP |
初回投稿:2015-09-07 (月) 12:02:17 | 最終更新:2016-02-28 (日) 16:13:48

ずっと DB に頼ってばかりで、CSV ファイル出力って、ほとんどしてこなかったので
まとめた記事がなかった。

基本
文字コード変換

今では Web サイトは UTF-8 が主流になっているんだろうけど
Excel は、相変わらず Shift-JIS なので
文字コード変換が必要なときもあるでしょう。

  1. mb_convert_variables('SJIS-win', 'UTF-8', $string);
ファイル保存

試していないので、参考サイトのみ。

パス指定
ダウンロード

Qiita:PHPで連想配列を日本語エンコードしてCSV出力する
SCENE LIVE:【PHP】データをCSVでいい感じにエクスポートする方法

連想配列対応
  1. $fields = Array('name', 'content',);
  2.  
  3. $array = Array(
  4.     0 => Array('name' => 'yamada', 'content' => 'pitcher',),
  5.     1 => Array('name' => 'tanaka', 'content' => 'catcher',),
  6. );
  7.  
  8. /* ファイルポインタをオープン */
  9. $file = fopen("C:\Users\UserName\Downloads\test.csv", "w");
  10. fputcsv($file, $fields);
  11.  
  12. foreach( $array as $key => $assoc_row){
  13.   $numeric_row = array();
  14.   foreach ($fields as $header_name) {
  15.     $numeric_row[] = $assoc_row[$header_name];
  16.   }
  17.   fputcsv($file, $numeric_row);
  18. }
  19.  
  20. /* ファイルポインタをクローズ */
  21. fclose($file);
参考サイト

Qiita:PHPで連想配列を日本語エンコードしてCSV出力する

Posted by muchag | PHP |
初回投稿:2015-09-07 (月) 12:02:17 | 最終更新:2016-02-28 (日) 16:13:48

ファイル削除 -> 復旧

Posted by muchag | Eclipse |
初回投稿:2015-09-07 (月) 11:38:36 | 最終更新:2015-09-07 (月) 11:46:29

うっかり、必要なファイルまで削除してしまった~!!!

状況

ソース流用にて新システムを構築時に
新規コードをある程度組み、動作確認をした後で
コピーしてきたファイル群から不要ファイルを削除した。

ら!
せっかく書き上げた必要なファイルまで削除してしまった。涙

どうしよう・・・。

削除方法

Eclipse の プロジェクトエクスプローラツリーから
ファイルを選択し、Delete キーにて削除。

確認画面が出たにも拘らず、OK。。。
ちなみに PHP ファイル。

存在確認

プロジェクトディレクトリを確認したが
やっぱり、ファイルは全て削除されていた。

復旧方法

仕方がないので、コピー元プロジェクトより元ファイルを再度コピーしてきてリネームし、
再度同一コードを書こうと当該ファイルを Eclipse 上で開いたところ
内容が、削除前のファイル通り!!!

Eclipse のキャッシュ機能かしら~♪

動作確認

とりあえず、ブラウザにて動作確認。

エラー

残念ながら

Fatal error: Class ‘HogeService’ not found
解決

むむむ。

ひとまず、変更を Eclipse へ伝えるために
当該ファイルの中で任意の一文字を消去して保存。
消去した文字を復旧して保存。

これで無事に動作した♪

考察

ファイルを削除しちゃったときは
すぐに気がついたので、
ブラウザでの動作確認はしていないから
ファイルが削除されたことをブラウザは認識していないはず。

とすると、考えられるのは、Eclipse のキャッシュなのかしらね~。

Posted by muchag | Eclipse |
初回投稿:2015-09-07 (月) 11:38:36 | 最終更新:2015-09-07 (月) 11:46:29

SoftDelete

Posted by muchag | OpenPNE 3.x,Symfony 1.x |
初回投稿:2015-09-06 (日) 17:41:37 | 最終更新:2015-12-28 (月) 9:45:02


SoftDelete:日本語版

レコードを削除する際に、本当に削除(物理削除)するのではなく
削除フラグを立てることによって、削除モードにする(論理削除)機能。

【環境】
OpenPNE:3.8.15
Symfony:1.4.13
doctrine:1.2.4
設定
ProjectConfiguration

ここまで実装方法などについて書いてきましたが、実はこれだけだと動きません。
Doctrineのデフォルトの設定では、Doctrine_Queryを実行前後で修正することが出来なくなっており、そこを設定してあげる必要があります。この設定の方法がsymfony 1.0とsymfony 1.1で変わってきます。

symfony 1.1ではProjectConfigurationクラスに設定を記述します。

アシアルブログ:Doctrineで論理削除を意識せずに扱う

ProjectConfiguration.class.php
  1. class ProjectConfiguration extends sfProjectConfiguration
  2. {
  3.   protected $plugins = array('sfDoctrinePlugin');
  4.  
  5.   public function configureDoctrine($manager)
  6.   {
  7.     $manager->setAttribute(Doctrine::ATTR_USE_DQL_CALLBACKS, true);
  8.   }
  9. }
OpnePNE3

OpenPNE3 では、こういう設定を追加する場所が用意されているっぽい。
まだ、成功体験をしていないので、本当にこれでよいかは不明。

(openpne3)\config\ProjectConfiguration.class.php
  1. public function setupProjectOpenPNEDoctrine($manager)
  2. {
  3.     // You can write your own configurations.
  4.  
  5.     // In default, OpenPNE uses foreign key.
  6.     // If you want not to use foreign key, comment out the following configuration:
  7.     // $manager->setAttribute(Doctrine::ATTR_EXPORT, Doctrine::EXPORT_ALL ^ Doctrine::EXPORT_CONSTRAINTS);
  8.  
  9.     $manager->setAttribute(Doctrine::ATTR_USE_DQL_CALLBACKS, true);
  10. }
schema
schema.yml
  1. Category:
  2.   actAs:
  3.    - SoftDelete
設定変更

カラム名やデータ型を変更したい場合は、下記のように記述すればよいみたい。
Symfony world:Doctrine SoftDelete behavior usage
→この記事のコメント投稿内情報。未検証。

  1. Category:
  2.   actAs:
  3.     SoftDelete:
  4.       name: is_deleted
  5.       type: datetime

力技でやっている人もいるみたい。
@chisei のはてなブログ:Doctrineの論理削除

マニュアルとの差異

このように設定することで、当該テーブルへ deleted_at カラムが追加される
んだけど・・・

公式マニュアル では、delete カラムが追加される、とされている。
データ型も、公式マニュアルでは、TYNYINT とあるけど、実際は DATETIME になる。
バージョンの問題かしらね~。

データ挿入

んで、実際に試してみた。
CSV で、データを突っ込む際に、deleted_at カラムには null を指定しておいたところ
当該カラムの値は 0000-00-00 00:00:00 となった。

CSV から Null を放り込む方法

文系プログラマによるTIPSブログ:MySQLのload dataで日付型にnullをセットする
こちらの記事がビンゴ!

  1. LOAD DATA
  2.     LOCAL INFILE 'data.csv'
  3.     INTO TABLE [table_name]
  4.     FIELDS TERMINATED BY ','
  5.     ENCLOSED BY '"'
  6.     SET
  7.         deleted_at = nullif(deleted_at, '0000-00-00 00:00:00')
  8. ;

上記記事では、指定項目がもっといっぱいあったけど
ひとまず、私の今回の環境およびデータでは、上記 SQL にて、
無事に daleted_at カラムへ Null 値を放り込めた。

nullif

どうやら第2引数に、データ型に合わせたデフォルト値を設定するみたい。
なので、その他のデータ型は下記の通り。

  1. SET
  2.         datetime = nullif(datetime, '0000-00-00 00:00:00')
  3.         date = nullif(date, '0000-00-00')
  4.         time = nullif(time, '00:00:00')
データ取得
  1. $result = $this->createQuery('c')
  2.     ->execute();

データ取得を試みたところ
取得データ数は 0 。

SQL 確認

SQL の確認 のごとく、発行された SQL 文を確認すると、
ちゃんと WHERE 句が付記されている。

  1. WHERE (o.deleted_at IS NULL)

※エイリアスに p を指定しているのに、テーブル名の先頭文字 o をエイリアスにされているが気になるけど。。。

エイリアス o

これは、こちらの指定した DQL から Doctrine が SQL を生成する際に、
指定されたテーブルを順番に o1, o2, o3, … と再指定しているためだった。

その o も、恐らく、テーブル名の頭文字を取っていると思われる。
OpenPNE3 の場合、テーブル接頭辞を付けているため
全テーブルが op_ で始まるのよね。

原因

Doctrine が NULL を探しているのに対して、
データ側は ‘0000-00-00 00:00:00’ という値であるため
スルーされていた。

解決

上記 データ挿入→CSV から Null を放り込む方法 を用いて
値を Null にしてやることで、ちゃんとデータを取得できるようになった。

過去の対応策
  1. $result = $this->createQuery('p')
  2.     ->andWhere('p.deleted_at = ?', '0000-00-00 00:00:00')
  3.     ->execute();

これで一応拾ってくることはできた。

とりあえずはこれでいくしかないけど。。。意味なーい!
いつか解明しなければ。。。
(やっと解明できた)

エイリアス

ちなみにテーブルエイリアスを付けないと、上記記述でも拾ってこない。

  1. // NG
  2. $result = $this->createQuery()
  3.     ->andWhere('deleted_at = ?', '0000-00-00 00:00:00')
  4.     ->execute();

必ずエイリアスをつける必要があります。
ただしこれはSELECT限定で、DELETEのときはエイリアスがなくても動くようです。

アシアルブログ:Doctrineで論理削除を意識せずに扱う

Posted by muchag | OpenPNE 3.x,Symfony 1.x |
初回投稿:2015-09-06 (日) 17:41:37 | 最終更新:2015-12-28 (月) 9:45:02

plugin -> iG:Syntax Hiliter カスタマイズ 2015-09-01

Posted by muchag | Library & PlugIn & AddIn,WordPress |
初回投稿:2015-09-01 (火) 16:52:52 | 最終更新:2015-09-04 (金) 17:01:01

iG:Syntax Hiliter をカスタマイズ その3。
数日前、WordPress 本体のヴァージョンアップのお知らせがきており、それに合わせて更新したら
iG:Syntax Hiliter も更新のお知らせがきたので、更新してみた。
そうしたら、表示が大分変わってしまった・・・ので、再挑戦~。

前回記事

【環境】
WordPress:4.3
iG:Syntax Hiliter:5.0
GeSHi:1.0.8.11
独自タグの追加
ハイライト設定ファイルへの紐付け

独自に設定したショートタグをプラグインに認識させる方法。

plugins/igsyntax-hiliter/classes/frontend.php
  1. /**
  2.  * @var Array Contains file names for GeSHi language files associated with expected tag names
  3.  */
  4. protected $__geshi_language = array(
  5.     'as' => 'actionscript',
  6.     'html' => 'html4strict',
  7.     'js' => 'javascript',
  8.     'evba' => 'vbnet',        ← 追加した独自タグ
  9. );

このように記述してやることで、独自に設定したショートタグから

plugins/igsyntax-hiliter/geshi

にある、各言語ハイライト設定ファイルへと紐付けることができる。

言語表示文字列への紐付け

独自に設定したショートタグを任意の文字列にて表示させる方法。

plugins/igsyntax-hiliter/classes/frontend.php
  1. /**
  2.  * @var Array Contains display names for some languages, like C# for csharp, VB.NET for vbnet
  3.  */
  4. protected $__geshi_language_display = array(
  5.     'cpp'         => 'C++',
  6.     'cfm'         => 'Cold Fusion',
  7.     'csharp'      => 'C#',
  8.     'vbnet'       => 'VB.NET',
  9.     'as'          => 'ActionScript',
  10.     'c_mac'       => 'CMac',
  11.     'html'        => 'HTML',
  12.     'html4strict' => 'HTML4',
  13.     'evba'        => 'Excel VBA',
  14. );
外観

今回の CSS ファイルは圧縮してあるので
行番号はなし。

全体
幅とマージン
plugins\igsyntax-hiliter\assets\css\front-end.css
  1. .syntax_hilite {
  2. background:#FFFFFF;
  3. width:98%;
  4. margin:10px 0px 20px 0px;
  5. border:1px solid #CCCCCC;
  6. border-left:none;
  7. border-right:none
  8. }
コード部
文字サイズ
plugins\igsyntax-hiliter\assets\css\front-end.css
  1. .syntax_hilite ol,.syntax_hilite .pre {
  2. width:90%;
  3. line-height:1.5em;
  4. margin-bottom:0px;
  5. padding-top:5px;
  6. font-size:1.25em
  7. }

全体幅を調節したせいか、こちらの幅を狭めておかないと
ハイライト行がはみ出す。

plugins\igsyntax-hiliter\assets\css\front-end.css
  1. .syntax_hilite ol,.syntax_hilite .pre {
  2. width:90%;
  3. line-height:1.5em;
  4. margin-bottom:0px;
  5. padding-top:5px;
  6. font-size:1.25em
  7. }
ツールバー
文字サイズ
plugins\igsyntax-hiliter\assets\css\front-end.css
  1. .syntax_hilite .toolbar {
  2. width:97.5%;
  3. margin:0px 0px 10px 0px;
  4. padding:5px 10px 5px 4px;
  5. background:#EEEEEE;
  6. font-family:"Trebuchet MS", Arial, Helvetica, sans-serif;
  7. font-size:1em;
  8. color:#555555
  9. }
Posted by muchag | Library & PlugIn & AddIn,WordPress |
初回投稿:2015-09-01 (火) 16:52:52 | 最終更新:2015-09-04 (金) 17:01:01

php.ini

Posted by muchag | PHP |
初回投稿:2015-05-29 (金) 12:53:43 | 最終更新:2015-05-29 (金) 12:53:43

初期設定項目。

extention
extension=php_openssl.dll

外部 API からレスポンスがない

Posted by muchag | PHP |
初回投稿:2015-05-29 (金) 12:53:43 | 最終更新:2015-05-29 (金) 12:53:43

外部 API からレスポンスがない

Posted by muchag | PHP |
初回投稿:2015-05-29 (金) 12:50:56 | 最終更新:2015-05-29 (金) 12:50:56

まさかこんなところが原因だとは思わず、24時刊無駄にしちゃった。 😥

【環境】
php:5.4.7
現象

Google Places API を利用しようと思ってコーディングしたところ
file_get_contents の戻り値が false になった。

原因

API 問い合わせ先が https であるのに対して
php の openssl が ON になっていなかった。

解決
(xampp)\php\php.ini
  1. - ;extension=php_openssl.dll
  2. + extension=php_openssl.dll
試行錯誤
cURL

file_get_contents がだめだったので、cURL も試してみたけどだめだった。

ブラウザでチェック

試しに要求 URL をブラウザに直接入力してみると
ちゃんとレスポンスが返ってきて、json 文字列が表示された。

API キー

Google Developer Console を見ると、API キーには4種類
サーバー キー、ブラウザ キー、Android キー、iOS キー
があるようで、サーバーサイドの場合は、サーバー キーが必要なんかと思い
これを取得、設定を変更したけど、ダメ。

解決後調査結果

サーバーサイドスクリプト内であろうが、ブラウザ直接入力であろうが
サーバー キーでも、ブラウザ キーでも、どちらでもレスポンスが返ってきた。

素の php

はた、と思いついて、マッサラのテストページを作り
当該箇所のみを記述して読み込んでみた。

  1. $url  = sprintf( 'https://maps.googleapis.com/maps/api/place/textsearch/json?query=%s&sensor=false&key=%s', $word, $key );
  2. $json = file_get_contents( $url );
  3. echo $json;
Warning

すると、下記のような Warning が。

file_get_contents(): Unable to find the wrapper…

「file_get_contents(): Unable to find the wrapper」

Symfony でも、エラーを表示するように設定しないと時間の無駄だね。。。

Google 先生

で、Google 先生に質問したら、下記記事が一番上に表示された。
YAHOO! JAPAN 知恵袋:PHPでhttps://から始まるURLのオープンに…

こちらの回答に従って、extention を ON にしたところ、無事に解決した。

Posted by muchag | PHP |
初回投稿:2015-05-29 (金) 12:50:56 | 最終更新:2015-05-29 (金) 12:50:56

データベース設計

Posted by muchag | SE |
初回投稿:2015-05-27 (水) 11:07:28 | 最終更新:2015-09-02 (水) 8:43:06

参考サイト

DeNA Engineers’ Blog
ソーシャルゲームのためのMySQL入門
ソーシャルゲームのためのMySQL入門その2

slideshare:ソーシャルゲームのためのデータベース設計
→残念ながら見ることができない。メモリオーバーかも。。。

リレーショナル・データベースの世界

Posted by muchag | SE |
初回投稿:2015-05-27 (水) 11:07:28 | 最終更新:2015-09-02 (水) 8:43:06
« 前ページへ次ページへ »