作りたいものがありすぎる

40歳を過ぎてプログラミングを始めた人の顛末とこれからなど

Laravel フォームで配列を扱う ヘルパ関数old() でチェックボックスを扱う方法

最初の記事がとてもバズり、おかげ様でこの週のはてなブログのランキングに乗ることができました。ありがとうございます。
今回は具体的な技術のTIPSエントリーとなります。こんな感じの記事の時もありますし、おっさんらしく蘊蓄をたれたり心構え的なものや日記みたいな事も記事にしていこうと思ってますので、よかったら今後もお付き合いいただければ幸いです。





フォームのチェックボックスで、DBの boolean 値 を変更させるユーザーフォームを作っていた際、ヘルパ関数の old() やPOSTすべき値で散々悩んだので、うまくった例を記述します。

実装したフォームの参考画像
実装例、『非表示』とあるチェックボックスのバリデート時にリダイレクトされた際に、ユーザーのチェックした内容をどう保持するか、という問題です。

対象はユーザーフォームの 『端末を非表示にする』 というチェックボックスカラム名は hide で 1なら非表示 0なら表示としてます。 しかもこのフォームでは複数端末が表示されるので、配列で扱うというめんどくさい状態。さらに言うなら、DBの値を引っ張りだしてきて、 true なら checkd="checked" を表示させる。 さらに バリデートエラーの際はヘルパ関数 old() でチェックの状態を保持する、という  boolean が何重にも絡んでくるややこしい状態で問題の整理にかなりの時間を要しました。
前提条件としてhtmlのformで配列を扱う際には foreachなどで連続して同じ様なformを出力する必要がある場合があります。
その際に name等は以下の様に配列として扱います。
name="hide[]"

また、連想配列で扱いたい際は
name="hide[key]"
と、書いて扱います。

参考サイト
FormのPOST送信で配列を、できれば連想配列を送信したい。

以上を踏まえた上で先に結論です。

@php
if(
    ($mac_add->hide == 1 && old('mac_address.'.$mac_add->id.'.hide') == null) ||
    old('mac_address.'.$mac_add->id.'.hide') == 1
) {
    $check_hide[$mac_add->id] = "checked='checked'";
} else {
    $check_hide[$mac_add->id] = "";
}
@endphp
<!-- チェックされていない場合は0を送信 -->
<input type="hidden" name="mac_address[{{$mac_add->id}}][hide]" value="0">
<input type="checkbox" name="mac_address[{{$mac_add->id}}][hide]" value="1" id="devise-check-{{$mac_add->id}}" {{$check_hide[$mac_add->id]}}>

viewに @php で直接設定書いてますが、さんざん悩んだので、これ以上いじりたくないという状態です。 あと、三項演算子が苦手で、htmlの中にIF文書きたくないのです。

このphpコードは要は最初のifで チェックボックスに印をつけるか否かの判定をしているのみです。
$check_hide[] という配列に html の"checked='checked'" を書くべきか否かを処理してます。

以下はヘルパ関数 old() で取れる hide の配列内の値です。
'mac_address.'.$mac_add->id.'.hide'

これは、以下の様に解釈します。
array[id][hide]

端末情報 mac_address の配列情報の中に端末の固有IDをキーとして配列を保持させ、さらにその中の hide キーの中身を呼び出してます。
じつは、array[][hide] という風に配列を空にして、キーを自動で入る通し番号にしても良い気がしますが、controller側に渡して処理する際に 配列キーがDBのプライマリキーのIDだと、何かと都合が良いのでこうしてます。

この値はバリデートエラーなどでセッションに初めて保持される値で、普段は null です。
従って以下は フォームの値が 1 の状態か、 old() の値が無いなら、 true となります。
($mac_add->hide == 1 && old('mac_address.'.$mac_add->id.'.hide') == null)

さらにif関数の論理式でor条件を立ててます。
old('mac_address.'.$mac_add->id.'.hide') == 1

単純に、 old の値で 1、つまり true が入っているかを判定。 このいずれかに該当すれば、非表示状態の設定とみなし "checked='checked'" がフォーム内に描画され、チェックが入ります。

さらに下のhtmlフォームです。

<!-- チェックされていない場合は0を送信 -->
<input type="hidden" name="mac_address[{{$mac_add->id}}][hide]" value="0">
<input type="checkbox" name="mac_address[{{$mac_add->id}}][hide]" value="1" {{$check_hide[$mac_add->id]}}>

チェックボックスの前の行にhiddenでcheckboxに同じ name="" を付けてますが、これがちょっとややこしい事になります。 知っている人には当たり前かもしれませんが、実はチェックボックスのフォームって、チェックを入れないと、POSTされないそうです。 つまり、このままですと、ユーザーが空のフォームにチェックした情報は取れますが、ユーザーが意図的にチェックを外した。という情報が取れない訳です。 そこで、 hiddenを chekboxの前に書いて、もしユーザーがチェックを入れてない場合は、 name="hide" に 0 の値をPOSTしてやる、という事をしています。 htmlフォームで name が同じものが2つ以上あった場合は、後に書いた方の値が飛ぶ、という仕様をハックして、普段は下のフォームの値が飛び、いざチェックが外された際はhidden の値が飛ぶ、という訳です。

詳しくは以下を参照
[HTML]formでcheckboxにチェックしていない時にもパラメータを送る方法 isket.jp

これで各フォームの name="hide" に 0と1の状態がPOSTされる状態が表現できました。あとはバリデートエラー等で、再度フォームを描画する際に old 関数の値を引っ張り出すことで、フォーム直前の状態が 0か1がわかり、それを元に "checked='checked'" を入れるか入れないかを判定すれば良い。ということですね。

参考サイト

Laravelで多次元配列のバリデーション
qiita.com

checked="checked"はどうやって表示させるの? qiita.com

Laravelで、チェックボックスをPOSTした後の old() 問題 qiita.com

次回は軽めの記事にしようと思います。

40歳を過ぎてからプログラミングを始めて滞在者確認サービスをリリースするまでの話

こんにちは世界。このたびシェアオフィスやコワーキングスペース等で、滞在者が確認できるサービスを制作しリリースしました。既に複数のコミュニティで使用をしてもらっており、今後も広く皆さんに使ってもらおうと思ってます。

このブログでは40歳を過ぎてプログラミングを始めた顛末や、技術的な方法論の共有、備忘録、またサービスの発展や、今後行って行きたい事柄についてなるべく気軽に書いて行こうと思います。

 

コンセプト

 誤字脱字気にしません。

 事実誤認のご指摘あれば直します。

 文章で議論とかはしません。

 気軽に、軽めに、自分の負担にならない形で記事を書きます。

 

今回はサービスの概要とプログラミングを初めてからサービスをリリースするまでの経緯を書きます。

 

どんなアプリなのか?

任意の人がある程度自由に集まる場所で『今、誰がいるか?』が、スマホに通知され確認できるサービスです。シェアオフィスやコワーキングスペース、またはボードゲームのプレイスペース等、様々なコミュニティで使ってもらえるものを目指しています。

f:id:sakamata:20181116072626p:plain

 

どんな仕組と方法なのか?

シェアスペースにあるwi-fi に来訪者がスマホやパソコンでネットに接続している際に、端末に付いている固有番号『MACアドレス』というものを、他のパソコンで定期的に確認し『このMACアドレスは○○さんのスマホ』というように、端末と人を結び付けて、今その場所に誰が居るかがわかる仕組になっています。

他の人の端末の固有番号、MACアドレスは、wi-fiに接続していると、実は誰でも見る事が出来ます。コマンドプロンプトという黒い画面を出して arp -a と打つだけですが、wi-fiや端末の設定などで見れない場合もあります。

しかし、これは、いつ、どこに誰が居たかを特定できる個人情報になりますので、確認の為に収集したMACアドレスは、不可逆暗号化されています。なので誰にもMACアドレスが判らない形でありながら、個別の端末判定ができる様になっています。

f:id:sakamata:20181116181515p:plain

自宅のwi-fi環境でコマンドを打った例です、私は別にバレてもいいのですが…。

 

余談ですが、この問題解決の為にteratailで質問したら、なんと徳丸本の中の人(体系的に学ぶ 安全なWebアプリケーションの作り方 等の著者)からアドバイスをもらえて嬉しかった。teratail.com

 

MACアドレスの確認には数千円の小型パソコン RaspberryPi を使用しています。タバコの箱より小さくて、消費電力はおよそ2.5Wと電球以下、オフィス等にモニターもマウスも無しでコンセントに繋げるだけで動きます。これをwi-fiネットワークに繋ぎ、今現在接続されている端末を24時間調べ続けて、インターネット上のサービスに情報を送信しています。

f:id:sakamata:20181116181801p:plain

 (エンジニアの方向けの概要説明)具体的には arp-scan というコマンドでwi-fiネットワークをポーリングしてます。cronで1分おきにコマンドを叩き、接続端末に変化があればshellスクリプトで取得した値をJSONにして、hashキーを付与してWebサーバーに側にhttps curlでPOSTしてます。

 slack sampleç»å

Webサーバー側は、いわゆる普通のWebアプリになっており、PHPフレームワークLaravelとMySQLで構成しています。管理者が端末番号と人を結び付けたり、ユーザーが自分のプロフィールや端末の管理ができる様になっています。

また、人が来たり帰ったりすると、皆さんが良く使うLINEやメール、Slack等のおなじみのコミュニケーションアプリに通知してくれるので、ほぼリアルタイムにお知らせが来ます。具体的にはIFTTTのwebhooksを使ってます。

f:id:sakamata:20181117044618p:plain

f:id:sakamata:20181116072823p:plain

また、一覧で誰が居るかを知りたい場合は、コミュニティのメンバーだけに共有されている秘密のページで現状を確認できます。さらに来訪や帰宅を知られたくない人は、匿名や非表示にして存在を隠すこともできます。

f:id:sakamata:20181116181917p:plain

実際に稼働中のサービス画面です

今後はこのサービスを他のIoTデバイスや様々なサービスと連携させ、シェアリングエコノミーを運営する方や、そのコミュニティの参加者の方にとって便利で嬉しいサービスを総合的に提供して行きたいと考えています。人が集うための触媒になるようなサービスをたくさん作りたいですね。現在はそのプラットフォームとしてのアプリという位置づけでやってますので、よかったら使ってやってください。

販売受付のサイトはこちらです。

https://www.livelynk.jp/

 

なお、現状ソースコードGithubOSSの状態で上げていますので、よかったらツッコミや協力をしてもらえるととても助かります。

github.com

github.com

 

作ることになったきっかけと感謝したいこと

長くギークオフィス恵比寿という招待制の会員オフィスのメンバーで、そこで『オフィスに今誰が居るかを知りたい』というニーズがありました。しかし、カメラとかだとプライバシー的にも心理的にも監視されているようで嫌なわけです。そこで、IoTデバイスとかでなんとかなんない?という相談がきっかけになり、試行錯誤の末にこのような仕組みに落ち着きました。

実はここのメンバーには大変お世話になっており、サービスのwebデザインをやってもらったり、企画やプロデュース、少額個人投資もしていただきました。また、最近では営業等を行ってくださる方も現れて、自然発生的に様々な方にゆるく手伝って頂いてます。このつながりが無ければこのサービスも、私のプログラミング技術もここまで来れませんでした。日々感謝してます。そして私のもっとも身近な人に最大限の感謝を。今まで大変な迷惑をかけてきたので今後はちゃんと恩を返して行きたいです。

 

私のこと

50歳近いおっさんで、40歳もなかばに近づいた頃にプログラミングを本格的に始めました。普段は大学の非常勤講師で、パソコンの基礎(Word,Excel)をスマホ世代の大学生に教えたり、主に介護福祉系の中小企業やNPOさんのIT全般のサポート業務をしてますがまあ貧乏です。

プログラミングは主にPHP, JavaScript, 少しだけ Ruby on Rails を使います。VPSの構築やDBの最低限の設定はできる様になりました。現在はPHPフレームワークのLaravelを主に使ってますが、今後は linuxコマンドの詳細把握や、IoTデバイスとの連携、APIの活用や作成、node.jsでサーバーサイドJavaScriptや、可能なら以前挫折したPython等にも手を出していきたいと思っていますが、具体的に作りたいものがたくさんあるので、都度最低限の学習で最大限の効果を出せるものを模索したいタイプです。最近度数1.5の老眼鏡を買いました。

 

プログラミングを学んできた経緯など

プログラミング紀元前

十年以上前から思いついた仕組があって、それを実現したいと色々やってましたが、やっぱり自分で作れるようにならなきゃ駄目だな。という事が身に沁み始めたのが6年位前でしょうか?それまでプログラミングは経験全く無しでした。IT企業の営業から何故かSEやディレクションみたいな事をしつつも、いざプログラミング学習に挑戦しようとして何度も挫折してました。「英語の出る黒い画面怖い!」みたいな感じです。ただ、自分なりにWebサイトを作った事はあったのでhtmlやcssの基本位は把握していました。

 

初めてのPython 第3版

初めてのPython 第3版

 

 いきなりオライリーは無謀だと思った。

JavaScriptの絵本 ホームページ作りが楽しくなる9つの扉

JavaScriptの絵本 ホームページ作りが楽しくなる9つの扉

 

これでも難しかった。

 

プログラミング元年

それまでもちょいちょい初心者向けのJavaScriptの本を読んでifやfor位は試してはみていたのですが、それが一体なんでアプリになるのか?という所には結び付かず、ちゃんとしたものが作れるようになるには、果てしなく学習しなくてはいけないのか…。と愕然としていましたが、ある時 ITの講師としてMicrosoftAccessを教える事になったのがきっかけで、データベース(DB)に興味を持ち『基礎からのMySQL』という本を買った事で開眼しました。

基礎からのMySQL 改訂版 (基礎からシリーズ)

基礎からのMySQL 改訂版 (基礎からシリーズ)

 

私の起源でありバイブル

DB操作の基礎とPHPでごく簡単な掲示板を作る本でしたが、これがきっかけで『DBは要は表。プログラムで作るアプリケーションはその表に値を入れたり出したり、上手い事表示させるための仕組。』というDBを使ったアプリの基本概念が腑に落ちてからは、様々な事柄の理解がいっきに進みました。

 

プログラミング幼年期

いくつかの本を読み進めつつ、PHPのスクラッチでどうしても作りたいシステムをコツコツ作ってました。この辺の詳しい話はいずれ書きます。 ただ、理想の完成形は多分自分ひとりのスキルで作るのは難しいかも。とかも考えますが、どこまでいけるか一生かけてやってみたいです。

基礎からのPHP (基礎からシリーズ)

基礎からのPHP (基礎からシリーズ)

 
10日でおぼえるLinuxサーバー入門教室 CentOS対応

10日でおぼえるLinuxサーバー入門教室 CentOS対応

 
10日でおぼえるJavaScript入門教室 第3版 (10日でおぼえるシリーズ)

10日でおぼえるJavaScript入門教室 第3版 (10日でおぼえるシリーズ)

 

 これらで基礎的な事を徐々に身に付けてました。

プログラミング近代

『パーフェクトPHP』という本を買い、本にあったスクラッチのサンプルフレームワークを写経した後、それを拡張してどうしても作りたいアプリケーションのバージョン2を作ってました。MVCオブジェクト指向、クラスの使い方をなんとなく把握した感じです。

 

パーフェクトPHP (PERFECT SERIES 3)

パーフェクトPHP (PERFECT SERIES 3)

 

いまだに辞書替わりにしてます、フルスクラッチフレームワーク制作は手ごたえたっぷりでした。

 

この頃にポツポツと個人からのアプリ制作の依頼があり、個人事業主としてスポットで制作を請け負ったりしました。GoogleMAP Distance Matrix API から値を取得するプログラムを制作したり、リモートでとあるサイトの機能追加等のお手伝いをしたりしました。

改訂3版基礎 Ruby on Rails (KS IMPRESS KISO SERIES)

改訂3版基礎 Ruby on Rails (KS IMPRESS KISO SERIES)

 

フレームワークとして優れた設計思想というものを目にしたのと2つ目のサーバーサイド言語として知識が並列して役立つ事を学びました。

 

去年あたり

個人からの依頼がポツポツ来るようになり、様々な企画や提案をされた方のWebサービスのプロトタイプをスクラッチで何度か作る事になりました。この頃からちゃんとしたフレームワークを使おうと思い、Railsよりも慣れたPHPで「これから来るかも」と目を付けたLaravelの学習をしつつプロトタイプアプリを作ったりしてました。

PHPフレームワーク Laravel入門

PHPフレームワーク Laravel入門

 

 この辺までくるとノリでなんとなくサクサクできる様になりました。カスタマイズもリファレンスやブログ記事をググりながらやってました。

今年

どうしても作りたいアプリとかなり似たものを作ろうという話が一部で盛り上がり、少しだけ作ったりしてました。これは今も周囲に期待してもらっているので、今のサービスと並行して進めて行こうと思ってます。そして今年、8月初旬に『シェアオフィスの滞在者がわかるアプリが欲しい』という依頼を受け現在に至ります。制作期間は一か月で1つのコミュニティで使用する基本のモックアップが完成し、運用しつつアップデートしていました。3か月経った現在では複数のコミュニティで使って貰えるよう、DB設計を1から見直したものが動いてます。(DB周りを全て書き直しました)

PHPフレームワーク Laravel Webアプリケーション開発 バージョン5.5 LTS対応

PHPフレームワーク Laravel Webアプリケーション開発 バージョン5.5 LTS対応

  • 作者: 竹澤有貴,栗生和明,新原雅司,大村創太郎,丸山弘詩
  • 出版社/メーカー: ソシム
  • 発売日: 2018/09/26
  • メディア: 単行本
  • この商品を含むブログを見る
 

この本の輪読会で毎週秋葉原コワーキングスペースWeeybleさんに通わせてもらってます。サービスを作りつつ今はこれと格闘中です。内容はかなり難しく、2章で「Laravel何もわからない」状態ですが、読むほどにリファクタリングしまくりたくなる…。

 

これから

既に書いてますが、もっとたくさんのものを形にして行きたいです。あと、いい歳をした未経験の野生のプログラマーを雇ってくれる様な会社も無いと思いますが、プログラミングでほどほどにご飯が食べられるようになりたいです。また、今まで長く自分にはアイデアはあるけどできない事が山の様にあったので、それをどんどん作っていきたいですね。それらを作り、使ってもらう事で、私も、私に近しい人も、そして利用する方も、人生が少しでもラクで楽しくなれば良いなと思ってます。

 

はてなブックマークは10年以上使っているユーザーですが、はてなダイアリーをちょうど10年間放置してました。記念に10年前の記事?をインポートしています。が、良い機会なので今後は出来る範囲で気軽な情報のアプトプットをして行こうと思います。よかったら今後も更新する記事を読んでもらえると嬉しいです。