階層構造の再帰処理

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

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

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

CLI -> 基本

Posted by muchag | MySQL,コマンドプロンプト |
初回投稿:2015-05-22 (金) 11:41:07 | 最終更新:2015-05-22 (金) 13:43:32

MySQL のコマンドラインからの操作。

【環境】
MySQL:5.5.27
XAMPP:1.8.3
開始

私は MySQL を XAMPP から利用しているので
MySQL も XAMPP 内にある。

コマンドプロンプトを開いたら、下記3種の利用方法がある。

  • そのまま記述(環境変数を登録している場合)
  • MySQL\bin まで cd
  • フルパスで記述
コマンドラインツールの起動
  1. $ mysql -u ユーザ名 -p

これでパスワードの入力を促されるので
パスワードを入力し、認証が通ったら
ツールを利用できるようになる。

  1. mysql>

プロンプトが上記のようになれば、起動成功。

パスワードも含めて起動
  1. $ mysql -u ユーザ名 -pパスワード

-p オプション指定の直後にパスワードを記述する。
スペースを開けずに記述する ところがミソ。

データベースを指定して起動
  1. $ mysql -u ユーザ名 -D データベース名 -p
データベースの選択
  1. mysql> use データベース名
テーブル一覧表示
  1. mysql> show tables
終了
  1. mysql> quit
  2.  
  3. または
  4.  
  5. mysql> \q
書式
文末

SQL 文の最後に ;(セミコロン)を付けること。
なぜって、下記のようにカスケード記述ができるから?

カスケード記述

長い SQL 文を分割して入力できる。

  1. mysql> SELECT a, b, c, d, e FROM table_a, table_b WHERE table_a.id = table_b.table_a_id AND table_a.id = 1;
  2.  
  3. // 途中で Enter キーを押下すると、継続して SQL 文を記述できる
  4. mysql> SELECT a, b, c, d, e(Enter)
  5.     -> FROM table_a, table_b(Enter)
  6.     -> WHERE table_a.id = table_b.table_a_id(Enter)
  7.     -> AND table_a.id = 1;

というわけで、文末にセミコロンを付けないと、永遠に -> が出てくる。 🙄

メモ
コマンドエイリアス
コマンド エイリアス
quit \q
Posted by muchag | MySQL,コマンドプロンプト |
初回投稿:2015-05-22 (金) 11:41:07 | 最終更新:2015-05-22 (金) 13:43:32

SQLSTATE[HY000]: General error: 1005 Can’t create table

Posted by muchag | OpenPNE 3.x,Symfony 1.x |
初回投稿:2015-05-21 (木) 22:49:18 | 最終更新:2015-11-17 (火) 18:04:46

【環境】
Symfony:1.4.13
OpnePNE:3.8.15
状況

OpenPNE3 のプラグインを開発していて、DB の再構築を行ったところ
下記のようなエラーメッセージが出た。

エラーメッセージ
SQLSTATE[HY000]: General error: 1005 Can’t create table ‘database_name.#sql-16e8_55a’
(errno: 150).
Failing Query:
“ALTER TABLE op_my_hoge ADD CONSTRAINT op_my_hoge_parent_id_op_my_parent_id FOREIGN KEY (parent_id) REFERENCES op_my_parent(id)”.
Failing Query:
ALTER TABLE op_my_hoge ADD CONSTRAINT op_my_hoge_parent_id_op_my_parent_id FOREIGN KEY (parent_id) REFERENCES op_my_parent(id)
原因

よく見てみると
op_my_hoge.parent_id と op_my_parent.id のデータ型が異なっていた。

Posted by muchag | OpenPNE 3.x,Symfony 1.x |
初回投稿:2015-05-21 (木) 22:49:18 | 最終更新:2015-11-17 (火) 18:04:46

引数があるメソッドの呼び出しエラー

Posted by muchag | Excel VBA |
初回投稿:2015-05-20 (水) 18:28:51 | 最終更新:2015-05-20 (水) 20:10:02

前から気になっていたことがやっと解決したのでメモ。

【環境】
Excel:2010
現象

以前から何度も出くわしているので、前の例は忘れてしまった。
今回の例。

クラスを作成して、setter を配置したところ
呼び出し元でエラー。
[evba language=”vb” firstline=”” highlight=””] class.setHoge (a)
[/evba]

記述して、改行すると、メソッド名と () の間にスペースが。。。

コーディング中に、「修正候補:=」みたいな感じの
「= がないよ~」という案内が出たと思うけど
確かなことは記憶がない。

お試し

「= がないよ~」と言われた気がするので、試しに無意味な変数をかましてみた。
[evba language=”vb” firstline=”” highlight=””] Dim a
a = class.setHoge(a)
[/evba] 確かに、これだと動くw

解決策

でも気持ちが悪いなぁ、と思っていたら、ひょっこり正解に当たった。

あとは、VBAの場合戻り値のない関数を呼ぶ際には「Call」を
先頭につけたほうが安全です。
( なくても呼べる場合もありますが、基本はつけておく。 )

YAHOO! JAPAN 知恵袋:Excel2003 VBAのクラスメソッドの呼び出しに…

あw そゆこと?
[evba language=”vb” firstline=”” highlight=””] call class.setHoge (a)
[/evba] 確かに~!!! ちゃんと動いた。

昔はちゃんと call をつけていたけど、
call がなくても動くので、いつの間にか忘れてた。。。

Posted by muchag | Excel VBA |
初回投稿:2015-05-20 (水) 18:28:51 | 最終更新:2015-05-20 (水) 20:10:02
« 前ページへ次ページへ »