2013年1月29日火曜日

似てるけど似てないPHPの配列を結合する

AdventCalendar2012でも書きましたが似てるけど似てないシリーズ。
(シリーズといいながら思いついたときに書き残そうと思っただけですが)
(というかほぼ自分の備忘録)

今回は配列の結合。
最近知ったことなんですが配列を結合に+という配列結合演算子があります。
今まで配列の結合と言えば array_merge と思っていたんですが + もありました。

何か違うことでもあるのかなと思って実際に試してみました。

簡単な例ですが
$tmp1_1 = array("1", "2", "3");
$tmp1_2 = array("a", "b", "c", "d");

var_dump(array_merge($tmp1_1, $tmp1_2));
// 結果
//array
//  0 => string '1' (length=1)
//  1 => string '2' (length=1)
//  2 => string '3' (length=1)
//  3 => string 'a' (length=1)
//  4 => string 'b' (length=1)
//  5 => string 'c' (length=1)
//  6 => string 'd' (length=1)

var_dump($tmp1_1 + $tmp1_2);
// 結果
//array
//  0 => string '1' (length=1)
//  1 => string '2' (length=1)
//  2 => string '3' (length=1)
//  3 => string 'd' (length=1)

全然、違います。
array_merge は指定した配列同士を連結していますが、+ の場合は前に指定した配列に値が追加されるような動きになります。

PHP: array_merge - Manual
http://jp1.php.net/manual/ja/function.array-merge.php
PHP: 配列演算子 - Manual
http://php.net/manual/ja/language.operators.array.php

php.netによると同じキー文字列を有している場合は、後に指定された配列により上書きされる。
とあるので
$tmp2_1 = array(
        "key_1" => "1",
        "key_2" => "2",
        "key_3" => "3",
    );
$tmp2_2 = array(
        "key_1" => "a",
        "key_2" => "b",
        "key_3" => "c",
        "key_4" => "d",
    );

var_dump(array_merge($tmp2_1, $tmp2_2));
// 結果
//array
//  'key_1' => string 'a' (length=1)
//  'key_2' => string 'b' (length=1)
//  'key_3' => string 'c' (length=1)
//  'key_4' => string 'd' (length=1)

var_dump($tmp2_1 + $tmp2_2);
// 結果
//array
//  0 => string '1' (length=1)
//  1 => string '2' (length=1)
//  2 => string '3' (length=1)
//  3 => string 'd' (length=1)

array_merge のほうは同じキー文字列を有しているので上書きされているのがわかります。
+ のほうは先ほどの結果と同じです。

動きを理解しておかないと思わぬ結果が返ってくるかもしれないです。




2013年1月27日日曜日

チートシートアプリ

アプリという方でもないですが。
寝る前に同僚からVimとかSublimeText2のチートシートを作ってと頼まれてたの思い出したので。
適当です。


画面はこんなかんじ。
人それぞれキーバインドしてるから簡単に内容を修正できるようにデータはxmlで。
htmlで作ってるからDropboxとかに置いとけばブラウザで表示できるし、データもxmlだからいつでも修正できる。

とりあえずGithubに置いたからあとはご自由に。
https://github.com/hayashida/cheatsheet






2013年1月20日日曜日

Fieldsetのcheckboxとradioのlabelについて #fuelphp

FuelPHPのFieldsetはFormを自動生成してくれる便利な機能のひとつです。
簡単な登録フォームを作る場合など便利だと思い、私も少し加工したパッケージを作ったことがあります。
Fieldsetの例としては以下がコントローラのソースです。

classes/controller/test.php
<?php

class Controller_Test extends Controller_Template
{
    public function action_index()
    {
        $fieldset = Fieldset::forge();

        $fieldset->add('name', 'Name')
                ->add_rule('required');

        $opt = array(
            '1' => 'Man',
            '2' => 'Woman',
        );
        $fieldset->add('gender', 'Gender',
                array(
                    'options' => $opt,
                    'type' => 'radio', 
                ));

        $opt = array(
            'PHP' => 'PHP',
            'Ruby' => 'Ruby',
            'Python' => 'Python',
        );
        $fieldset->add('lang', 'Lang',
                array(
                    'options' => $opt,
                    'type' => 'checkbox',
                ));

        $this->template->content = View::forge('test/index');
        $this->template->content->set_safe('form', $fieldset->build());
    }
}


これでView側(ここではview/test/index.php)は以下を記述するだけで登録フォームを生成してくれます。
<?php
    echo $form;

便利です。
populateやrepopulateを使うことでバリデーション後やモデルからデータを反映など実装してくれるので良いのですが、checkboxとradioを使った場合、現行バージョン(2013/01/19現在、1.4)ではソースを見ると以下のようになっています。
(langのcheckboxだけを抜粋)
<tr>
    <td class=""><label for="form_">Lang</label></td>
    <td class="">
        <input type="checkbox" id="form_lang_0" name="lang[0]" value="PHP" /> <label for="form_form_lang_0">PHP</label><br />
        <input type="checkbox" id="form_lang_1" name="lang[1]" value="Ruby" /> <label for="form_form_lang_1">Ruby</label><br />
        <input type="checkbox" id="form_lang_2" name="lang[2]" value="Python" /> <label for="form_form_lang_2">Python</label><br />
        <span></span>            
    </td>
<;/tr>

checkboxに紐づくはずのlabelのforが「form_form_xxx」となっています。
見た目は特に問題ですが、labelとcheckboxと紐付かないのはなかなか頂けません。
coreのプログラムを追ってたんですが、助言を頂いて1.5-devなら・・・ということで試してみました。

以下は1.5-devで実装した結果
<tr>
 <td class=""><label for="form_">Lang</label></td>
 <td class="">
  <input type="checkbox" id="form_lang_0" name="lang[0]" value="PHP" /> <label for="form_lang_0">PHP</label><br />
  <input type="checkbox" id="form_lang_1" name="lang[1]" value="Ruby" /> <label for="form_lang_1">Ruby</label><br />
  <input type="checkbox" id="form_lang_2" name="lang[2]" value="Python" /> <label for="form_lang_2">Python</label><br />
  <span></span>   
 </td>
</tr>

とりあえずはOK。確かになおってます。
今すぐどうにかしたい方はCoreの部分でdiffするとかやってみるといいかもしれませんね。




2013年1月9日水曜日

Sublime Text2の設定メモ

いろんなサイトを参考にしながら自分なり設定したことをメモ程度に。

ダウンロード
Sublime Text: The text editor you'll fall in love with

参考にしたサイトの紹介

この3つを見てもらえれば大抵の設定はできるので特に書く事もありませんが、自分の設定関係やらキーバインドやらをダラダラと。。。

Preferences - Settings User
{
 // フォントの設定
 "font_face": "Ricty",
 "font_size": 12.0,
 // 現在の行をハイライト
 "highlight_line": true,
 // Vimの有効化
 "ignored_packages":
 [
 ],
 "vintage_ctrl_keys": true,
 "vintage_start_in_command_mode": true,
 // ルーラの表示
 "rulers":
 [
  80,
  120
 ],
 // タブサイズ
 "tab_size": 4,
 // タブをスペースに変換
 "translate_tabs_to_spaces": true
}

Preferences - Key Bindings User
[
    // モードの切替を行わずに改行
    {
        "keys": ["ctrl+o"], "command": "run_macro_file",
        "args": {"file": "Packages/Default/Add Line.sublime-macro"}
    },
    {
        "keys": ["ctrl+O"], "command": "run_macro_file",
        "args": {"file": "Packages/Default/Add Line Before.sublime-macro"}
    },
    // INSERT MODEから抜ける
    {
        "keys": ["j", "j"], "command": "exit_insert_mode",
        "context":
        [
            { "key": "setting.is_widget", "operand": false },
            { "key": "setting.command_mode", "operand": false }
        ]
    },
    // タブ切替
    { "keys": ["ctrl+tab"], "command": "next_view" },
    { "keys": ["ctrl+shift+tab"], "command": "prev_view" },
    {
        "keys": ["g", "t"], "command": "next_view",
        "context":
        [
            { "key": "setting.is_widget", "operand": false },
            { "key": "setting.command_mode" }
        ]
    },
    {
        "keys": [ "G", "T" ], "command": "prev_view",
        "context":
        [
            { "key": "setting.is_widget", "operand": false },
            { "key": "setting.command_mode" }
        ]
    },
    // Command Modeでのカーソル移動
    {
        "keys": ["0"], "command": "move_to", "args": { "to": "bol", "extend": false },
        "context":
        [
            { "key": "setting.is_widget", "operand": false },
            { "key": "setting.command_mode" }
        ]
    },
    {
        "keys": ["9"], "command": "move_to", "args": { "to": "eol", "extend": false },
        "context":
        [
            { "key": "setting.is_widget", "operand": false },
            { "key": "setting.command_mode" }
        ]
    },
    // INSERT MODEでのカーソル移動
    {
        "keys": ["ctrl+h"], "command": "set_motion",
        "args": { "motion": "vi_move_by_characters_in_line", "motion_args": { "forward": false, "extend": true }},
        "context":
        [
            { "key": "setting.command_mode", "operand": false },
            { "key": "setting.is_widget", "operand": false }
        ]
    },
    {
        "keys": ["ctrl+l"], "command": "set_motion",
        "args": { "motion": "vi_move_by_characters_in_line", "motion_args": { "forward": true, "extend": true }},
        "context":
        [
            { "key": "setting.command_mode", "operand": false },
            { "key": "setting.is_widget", "operand": false }
        ]
    },
    {
        "keys": ["ctrl+k"], "command": "set_motion",
        "args": { "motion": "move", "motion_args": { "by": "lines", "forward": false, "extend": true }},
        "context":
        [
            { "key": "setting.command_mode", "operand": false },
            { "key": "setting.is_widget", "operand": false }
        ]
    },
    {
        "keys": ["ctrl+j"], "command": "set_motion",
        "args": { "motion": "move", "motion_args": { "by": "lines", "forward": true, "extend": true }},
        "context":
        [
            { "key": "setting.command_mode", "operand": false },
            { "key": "setting.is_widget", "operand": false }
        ]
    }
]

今のところインストールしているパッケージは

  • SideBarEnhancements ・・・サイドバーの拡張
  • Emmet ・・・Zencodingの次期バージョン?進化版?
  • SublimeLinter ・・・リアルタイムで文法チェック
  • Additional PHP Snippets ・・・PHP用のスニペット
  • SCSS ・・・Sass、Scssのシンタックス
  • ConvertToUTF8 ・・・Shift_JISに対応させるプラグイン


とこんなかんじです。
まだ使いこなせて感、満載ですがとりあえずVimっぽい動きとPHPを書く準備はできました。