そろそろ Simple HTML DOM Parser を使うのはやめたほうがいい
Simple HTML DOM Parser といえば定番のスクレイピングライブラリで、僕も随分お世話になったわけだけど遅いし重いので Goutte 使ったほうがいいという話です。某サイトをスクレイピングするのに比較したら特にメモリ消費に大きな差がでました。
比較したスクリプトは Github においてありますので自由に使ってください。なおプロファイラは @koriym さんが Qiita にポストしたものを使用させていただきました。
プログラム
スクレイピング対象のサイトはこのブログにしました。あざといですね。タイトルのリストを出力するプログラムです。
Simple HTML DOM Parser
<?php require_once './vendor/autoload.php'; require_once './profiler.php'; $html = \SimpleHtmlDom\str_get_html(file_get_contents('http://localdisk.hatenablog.com/')); $nodes = $html->find('h1.entry-title'); foreach ($nodes as $node) { echo trim($node->text()) . "\n"; } $html->clear();
Goutte
<?php require_once './vendor/autoload.php'; require_once './profiler.php'; $client = new \Goutte\Client; $crawler = $client->request('GET', 'http://localdisk.hatenablog.com/'); $crawler->filter('h1.entry-title')->each(function($node) { echo trim($node->text()) . "\n"; });
結果
処理時間は大差ありませんが*1、メモリ消費にかなりの差が出ているのがわかると思います。プログラムを見てもわかるように使い方に大差ありません。むしろ Goutte のほうが Closure 使えて嬉しいですね。
Simple HTML DOM Parser
便利な日時操作ライブラリ Carbon Response::xml macro を作ったよ NHK番組表API for PHP を書いたよ 足りないインフラ力をAnsibleでまかなう すべてのPOSTリクエストに対してCSRFフィルターを適用する 今年もよろしくお願いします Laravel でトランザクション 完結済の俺が好きな漫画+ Laravel でWebアプリのインストーラーを作ってみる Laravel 最速マスター Memory: 9,014,440 / 10,773,432 bytes Time: 1756.099939 ms Declared: 141 classes Ibcluded: 10
Goutte
便利な日時操作ライブラリ Carbon Response::xml macro を作ったよ NHK番組表API for PHP を書いたよ 足りないインフラ力をAnsibleでまかなう すべてのPOSTリクエストに対してCSRFフィルターを適用する 今年もよろしくお願いします Laravel でトランザクション 完結済の俺が好きな漫画+ Laravel でWebアプリのインストーラーを作ってみる Laravel 最速マスター Memory: 2,417,136 / 2,437,208 bytes Time: 1246.071815 ms Declared: 205 classes Ibcluded: 95
便利な日時操作ライブラリ Carbon
Response::xml macro を作ったよ
Laravel って json を返すメソッド Response::json
は用意されてるんだけど、XML を返すメソッドは用意されていない。API を作成しなければならない場合、いささか困る部分ではあります。なので作ってみた。
まず、 app
の下に macros.php
というファイルを作って下のコードをコピーしてください。
<?php // macros.php Response::macro('xml', function(array $vars, $status = 200, array $header = [], $xml = null) { if (is_null($xml)) { $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><response/>'); } foreach ($vars as $key => $value) { if (is_array($value)) { Response::xml($value, $status, $header, $xml->addChild($key)); } else { $xml->addChild($key, $value); } } if (empty($header)) { $header['Content-Type'] = 'application/xml'; } return Response::make($xml->asXML(), $status, $header); });
gist も貼っておきますね。
Response::xml macro
Laravel 4.1 から Response
クラスにも macro
が定義できるようになりましたので、このように楽に作ることができます。
で、その次に作成した macros.php
を使えるようにします。app/start/global.php
を開いて一行追加します。
<?php // global.php require app_path() . '/macros.php';
準備は完了しました。使い方としてはこのようになります。
<?php // routes.php Route::get('api.{ext}', function() { $data = ['status' => 'OK']; $ext = File::extension(Request::url()); return Response::$ext($data); })->where('ext', 'xml|json');
拡張子で判定して xml/json
のどちらかを出力するコードです。where
メソッドで拡張子は xml/json
のどちらかしか許可されません。これ以外の文字を入力すると HttpNotFoundException
が発生します。
Laravel を楽しんでください。
NHK番組表API for PHP を書いたよ
非常によい試みだと思います。民放各局もぜひ追随していただきたいところです。
ものは試しということでさくっと書いてみました。
実装はかなり適当なので*1、まぁテスト程度に使っていただければと思います。
リクエストを投げるのに Guzzle を使ってます。よく使われるライブラリなので慣れてる人は多いのではないでしょうか。
使い方はテストをみていただければと思います。
追記
Packagist に登録したよ。
こんな感じで composer.json を書いてくれればインストールできます。
{ "require": { "localdisk/nhk": "dev-master" } }
*1:例外処理とか書いてないし、パラメータの受け渡しにもう一工夫できる
足りないインフラ力をAnsibleでまかなう
2014/01/22 追記あり
このエントリを書いたあと、いくつかアドバイスを頂いた。ありがとうございます。それを受けていくつか playbook を修正しています。
@localdisk pipe('|') を使う場合は command じゃなくて shell ですね。SSH のは .ssh/config が Host にマッチしたものに適用する設定だからですね
— yteraoka (@yteraoka) 2014, 1月 19
@localdisk sourceslist への追加はapt_repository を使うと冪等性が出ていいと思います。 http://t.co/iwNDw40JUC
— shirou - しろう (@r_rudi) 2014, 1月 20
僕の感想。
自分の知らないことでも頑張ってブログに書くとできる人が色々アドバイスをくれるのでみんなもっとブログ書けばいいと思った。インターネットは優しさであふれてる。
— MATSUO Masaru (@localdisk) 2014, 1月 20
みんなブログ書くといい。
Vagrant の使用には慣れたものの、年末 Chef に挫折。インフラ力の高まりは感じただけで終わってしまったのだった。いや、ここで諦めてはいけない。他の選択肢を検討に入れてみよう。Puppet …も難しそうだ。 Chef に挫折したことを考えると勝算は低い。
なので Ansible に挑戦してみた。
読むのが面倒な人のためのまとめ
Ansible は Chef/Puppet とくらべて
という利点があり、Chef に挫折した自分でも丸一日の学習でなんとかなるので学習コストはかなり低いと言える。
しかし、この手のツール全てに言えることだけど Chef/Puppet/Ansible を使ったからと言って低いインフラ力が高くなるわけではないし*1、実際は状況に合わせたこまめなメンテナンスが必要になる。こまめなメンテナンスや調整は高いインフラ力を必要とするわけで、結局のところVagrant 使って開発用のサーバを作って一人で開発するという使い方であればあんまり必要ないと思う。
結論:得意なやつに任せろ。
目標
Ansible を使用して速やかにサーバ環境を作成する。デプロイに関しては考えない。
実益を兼ねて以下のアプリケーションをインストールできるまで頑張りたい。
前提
以後の作業は以下のバージョンで進めていきます
- Max OS 10.9.1
- VirtualBox 4.3.6
- Vagrant 1.4.3
- Python 2.7.6
- pip 1.4.1
- Ansible 1.4.4
インストール
インストールのページを見るにPythonは2.6以上が良いみたいだ。あと Windows は諦めろって書いてある。*2 もうほんと Windows では開発作業に支障がでるレベルになってて不憫である。主に仕事で使わざるを得ない自分が。
今回は Mac なので pip という Python のパッケージマネージャを使用してインストールする。
$ easy_install pip
自分のPCでは 1.4.1 がインストールされてた。
$ sudo pip install ansible
で、Enter。最初うっかり sudo
抜きでやってしまい
error: could not create '/usr/share/ansible': Permission denied
と怒られることになってしまったので注意が必要だ。うまくいくとコンソールにいろいろ出力されて最終的に
Successfully installed ansible paramiko jinja2 PyYAML httplib2 pycrypto ecdsa markupsafe
と出れば OK だと思う。
バージョンは 1.4.4 のようだ。
$ ansible --version ansible 1.4.4
接続
まずは Vagrant での接続を試してみよう。というわけで Vagrantfile を用意する。
そして起動。
$ vagrant up
ssh に登録。
$ vagrant ssh-config >> ~/.ssh/config
すると ~/.ssh/config
に Vagrant の情報が追記される。
Host node HostName 127.0.0.1 User vagrant Port 2222 UserKnownHostsFile /dev/null StrictHostKeyChecking no PasswordAuthentication no IdentityFile ~/.vagrant.d/insecure_private_key IdentitiesOnly yes LogLevel FATAL
その後に Ansible のインベントリファイルというやつを作ってやる。Ansible を適用する接続情報だと思っておけばOKだと思う。多分。ここでは hosts
というファイル名にする。
$ cat hosts
してこのような内容にしておこう
[vagrant] 192.168.33.10
そして Ansible から ping をうってみよう。
$ ansible -i hosts all -m ping
すると
192.168.33.10 | FAILED => SSH encountered an unknown error during the connection. We recommend you re-run the command using -vvvv, which will enable SSH debugging output to help diagnose the issue
繋がっ…てない。アルェー? とりあえず debug 情報を出すために -vvv オプションをつけてみる。
$ ansible -i hosts all -m ping -vvv
デバッグ情報が出てきたが…わからん。多分 ~/.ssh/config に追記された内容がおかしいような気がするので修正してみる。
Host 192.168.33.10 HostName 192.168.33.10 User vagrant Port 2222 UserKnownHostsFile /dev/null StrictHostKeyChecking no PasswordAuthentication no IdentityFile ~/.vagrant.d/insecure_private_key IdentitiesOnly yes LogLevel FATAL
Host と HostName を書き換えてみると…。
$ ansible -i hosts all -m ping 192.168.33.10 | success >> { "changed": false, "ping": "pong" }
うまくいった。理由はわからない。
playbook
Ansible では接続を定義するインベントリファイルとサーバの構成を管理する playbook というファイルが最低限必要になる。Best Practices という推奨された構成があるが、慣れてから手を付けたほうが良いように思う。
Chef をちょっと触っただけでわかった気になった自分の knife の切れ味に絶望して何もかもを放り出してしまったあの痛ましい事件を忘れてはならない。
簡単な playbook を作って実行する
playbook は yaml で記述する。ここが Ansible の良いところだと僕は思っている。Ruby 力が足りないプログラマでも優しいのだ。デザイナさんにもおすすめできるのもよい。
$ touch playbook.yml
で作って
- hosts: 192.168.33.10 user: vagrant sudo: yes tasks: - debug: msg="Hello! Ansible!"
と書いてみよう。早速実行?いや、まずはチェックだ。
$ ansible-playbook -i hosts --syntax-check playbook.yml
を実行しよう。typo があった場合は怒られるぞ。では、エラーがなかったので実行しよう。
$ ansible-playbook -i hosts --syntax-check playbook.yml PLAY [192.168.33.10] ********************************************************** GATHERING FACTS *************************************************************** ok: [192.168.33.10] TASK: [debug msg="Hello! Ansible!"] ******************************************* ok: [192.168.33.10] => { "msg": "Hello! Ansible!" } PLAY RECAP ******************************************************************** 192.168.33.10 : ok=2 changed=0 unreachable=0 failed=0
よし、では色々とインストールしていこう。
Nginx のインストール
まずは Nginx のインストールだ playbook.yml に追記してと…
tasks: - name: install nginx apt: pkg=nginx state=latest notify: restart nginx
うん?失敗する。apt-get update
しろと言ってくる。そりゃそうか。では別に pre.yml
を用意して…
- hosts: 192.168.33.10 user: vagrant sudo: yes tasks: - name: updates a server apt: update_cache=yes - name: upgrade a server apt: upgrade=full
そして実行。時間がかかるので少し待つべし。
$ ansible-playbook -i hosts pre.yml
終わったら再び
$ ansible-playbook -i hosts playbook.yml
OKだ。vagrant ssh
してバージョンを調べてみると…
vagrant@precise64:~$ nginx -v nginx version: nginx/1.1.19
古い…。仕方がないので Ubuntu 12.04 LTS に最新の Nginx をインストールする - xykの日記 を参考にして操作を playbook に落としていく。
- hosts: 192.168.33.10 user: vagrant sudo: yes tasks: - name: update sources list1 apt_repository: repo="deb http://nginx.org/packages/ubuntu/ precise nginx" - name: update sources list2 apt_repository: repo="deb-src http://nginx.org/packages/ubuntu/ precise nginx" - name: PGP Key Add apt_key: url=http://nginx.org/keys/nginx_signing.key - name: install nginx apt: pkg=nginx update_cache=yes - name: restart nginx service: name=nginx state=restarted enabled=yes
これで nginx の version が 1.4.4 になった。
sourceslist の追加が苦肉の策すぎてブログに載せるをためらうレベルだけど、誰かが教えてくれることを祈ってそのままにしておく。
(2014/01/22追記)
lineinfile モジュールの部分を apt_repository モジュールを使用するよう変更した。
MySQL のインストール
これはわりとすんなりと。今思ったけど、ファイル分けるより tag をつけたほうがいいね。
- hosts: 192.168.33.10 user: vagrant sudo: yes tasks: - name: install mysql apt: pkg=mysql-server - name: start mysql service: name=mysql state=started enabled=yes
PHP のインストール
ppa を足すときに、python-pycurl
のインストールを求められるくらいで特に引っかかるところはなかった。
- hosts: 192.168.33.10 user: vagrant sudo: yes tasks: - name: install python-pycurl apt: pkg=python-pycurl - name: add php repository apt_repository: repo='ppa:ondrej/php5' - name: install php apt: pkg={{ item }} update_cache=yes with_items: - php5 - php5-cli - php5-fpm - php-pear - php5-dev - php-apc - php5-mcrypt - php5-gd - php5-curl - php5-xdebug - php5-sqlite
Composer のインストール
command: curl -sS https://getcomposer.org/installer | php
と書くと "|" を誤認識(?)するらしく以下の様なエラーになる。
failed: [192.168.33.10] => {"changed": true, "cmd": ["curl", "-sS", "https://getcomposer.org/installer", "|", "php"], "delta": "0:00:41.804834", "end": "2014-01-19 11:42:57.120323", "rc": 6, "start": "2014-01-19 11:42:15.315489"} stderr: curl: (6) Couldn't resolve host '|'
仕方がないので vagrant-ansible-symfony2/devops/webserver.yml at master · tvieira/vagrant-ansible-symfony2 · GitHub から引用。
- hosts: 192.168.33.10 user: vagrant sudo: yes tasks: - name: install composer shell: curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin - name: move composer.phar to composer command: mv /usr/bin/composer.phar /usr/bin/composer
(2014/01/22追記)
command モジュールの部分を shell モジュールを使用するよう変更した。
Redis をインストールする
apt だと 2.2.2 とバージョンが古い。自分は詳しくないのだが、これでよいのだろうか?*3。ビルドするにはjprichardson/ansible-redis · GitHubが詳しい。
もう疲れてきた…。
HHVM のインストール
これで最後。この Playbook だけはぐぐっても見つからなかったので、このエントリでは唯一価値あるものだと思う。
- hosts: 192.168.33.10 user: vagrant sudo: yes tasks: - name: Add HHVM Key apt_key: url=http://dl.hhvm.com/conf/hhvm.gpg.key - name: Add Sources List apt_repository: repo="deb http://dl.hhvm.com/ubuntu precise main" - name: Install HHVM apt: pkg=hhvm-fastcgi update_cache=yes
(2014/01/22追記)
lineinfile モジュールの部分を apt_repository モジュールを使用するよう変更した。
なんのことはない。簡単である。
参考
すべてのPOSTリクエストに対してCSRFフィルターを適用する
Laravel のフィルターって本来はこう書くわけですが
<?php Route::post('user/register', ['before' => 'csrf', function() { return 'You are over 200 years old!'; }]);
POST するたびにいちいち before…
とか書きたくない。漏れがあったらやだし。なのでちょっとぐぐってみたところ stackoverflow の記事がひっかかりました。
php - Laravel 4 CSRF on all POST requests - Stack Overflow
…なんか苦肉の策感がすごい。いやいや、もうちょっとどうにかなるだろ、と思って調べてみたらどうにかなったよ。
こんな感じ。自力でフィルターを呼んでやるわけです。コメントにも書いてますが $request->getRealMethod()
とすれば POST / PUT / DELETE / PATCH
のリクエストの際にも CSRF のフィルターが呼ばれます。
追記
コントローラーでやりたい人はこうすればOK.
CSRF on all POST requests (Controller-based) | Laravel-Tricks.com
今年もよろしくお願いします
去年のふりかえり
脱ニートしてIT土方へとジョブチェンジしました。「ジョブチェンジ先ミスってんだろ!」というツッコミはまぁそのとおり*1。仕事ではほとんどJavaを書いてました。*2それも Struts2というこの先どこに活かせばいいのかよくわからないフレームワーク*3 にどっぷり浸かるというわけのわからないことに。
さらに通勤時間が現在往復4時間強と拷問というか苦行みたいな感じ*4になっており、大分県の片田舎からの引っ越しを現在真剣に考えています。
今年の目標
という闇から距離を置きたいというのが目標です。
あと、PHP 書きたい。レガシー状態からモダンに書きなおす案件とかやってみたい。
というわけで、今年は転職活動頑張ります。よろしくお願いします。
完結済の俺が好きな漫画+
完結済の俺が好きな漫画ベスト50を発表する!:わんこーる速報!
年末に良い記事だなぁと思ったのでご紹介。ついでに僕のおすすめも足してみようかと。一人の作者につき一作品でいきます。一応コメントを入れてますが、参考にならないです。でも、どれも面白いので機会があったら読んでみてください。
あずまんが大王 全3巻 完結セット (少年サンデーコミックススペシャル)
- 作者: あずまきよひこ
- 出版社/メーカー: 小学館
- 発売日: 2010/01
- メディア: コミック
- 購入: 4人 クリック: 14回
- この商品を含むブログ (4件) を見る
- 作者: 遠藤浩輝
- 出版社/メーカー: 講談社
- 発売日: 2013/05/02
- メディア: Kindle版
- この商品を含むブログを見る
- 作者: 吉田秋生
- 出版社/メーカー: 小学館
- 発売日: 1994/11
- メディア: 文庫
- 購入: 3人 クリック: 14回
- この商品を含むブログ (66件) を見る
- 作者: 澤井健
- 出版社/メーカー: 小学館クリエイティブ
- 発売日: 2010/02/01
- メディア: コミック
- 購入: 4人 クリック: 24回
- この商品を含むブログ (5件) を見る
- 作者: 吉本蜂矢
- 出版社/メーカー: 少年画報社
- 発売日: 1998/07
- メディア: コミック
- 購入: 2人 クリック: 71回
- この商品を含むブログ (22件) を見る
この作品とサーフサイドハイスクールは稲中卓球部の「中学のバカ」じゃなくて「高校のバカ」。シモネタがより生々しくてよい。
- 作者: 沙村広明
- 出版社/メーカー: 講談社
- 発売日: 2010/03/05
- メディア: コミック
- 購入: 38人 クリック: 842回
- この商品を含むブログ (160件) を見る
- 作者: よしながふみ
- 出版社/メーカー: 新書館
- 発売日: 2004/04/01
- メディア: コミック
- 購入: 6人 クリック: 70回
- この商品を含むブログ (312件) を見る
ハチミツとクローバー 1 (クイーンズコミックスDIGITAL)
- 作者: 羽海野チカ
- 出版社/メーカー: 集英社
- 発売日: 2013/06/28
- メディア: Kindle版
- この商品を含むブログを見る
- 作者: 芦奈野ひとし
- 出版社/メーカー: 講談社
- 発売日: 2012/11/19
- メディア: Kindle版
- クリック: 1回
- この商品を含むブログを見る
- 作者: 士郎正宗
- 出版社/メーカー: 講談社
- 発売日: 1991/10/02
- メディア: コミック
- 購入: 32人 クリック: 579回
- この商品を含むブログ (288件) を見る
- 作者: 高橋しん
- 出版社/メーカー: 小学館
- 発売日: 2013/07/15
- メディア: Kindle版
- この商品を含むブログを見る
- 作者: 相田裕
- 出版社/メーカー: メディアワークス
- 発売日: 2002/11
- メディア: コミック
- 購入: 6人 クリック: 145回
- この商品を含むブログ (243件) を見る
- 作者: 森薫
- 出版社/メーカー: エンターブレイン
- 発売日: 2002/08/26
- メディア: コミック
- 購入: 5人 クリック: 155回
- この商品を含むブログ (417件) を見る
- 作者: 西原理恵子
- 出版社/メーカー: KADOKAWA / 角川書店
- 発売日: 2013/11/08
- メディア: Kindle版
- この商品を含むブログを見る
- 作者: 乃木坂太郎,永井明
- 出版社/メーカー: 小学館
- 発売日: 2013/12/14
- メディア: 文庫
- この商品を含むブログを見る
- 作者: 冬目景
- 出版社/メーカー: 幻冬舎コミックス
- 発売日: 2002/01
- メディア: コミック
- 購入: 3人 クリック: 174回
- この商品を含むブログ (96件) を見る
- 作者: 伊藤悠,佐藤大輔
- 出版社/メーカー: 集英社
- 発売日: 2005/03/18
- メディア: コミック
- 購入: 7人 クリック: 556回
- この商品を含むブログ (404件) を見る
眠いのでここで終わり。
余談
アカギの最新刊で鷲巣が鬼と鬼ごっこしてるんだけど、どういうことなの…。
Laravel でWebアプリのインストーラーを作ってみる
このエントリはLaravel Advent Calendar 2013の23日目の記事です。
実はパッケージを作った話をしようと思ったのですが、死ぬほど地味で Laravel ほとんど関係なくなった*1ので別のネタで。
20日目でこんな記事がありました。
laravel4を使ったアプリケーション配布時の工夫 - Qiita [キータ]
これをもうちょっとカジュアルにLaravelっぽくやってみようという試みです。WordPress のインストーラーを思い浮かべると処理としては大体以下のような感じ。
- インストールされているかチェック
- DB につながっているかつ、テーブルが作成されていればインストール済みとみなす
- インストール画面から接続情報を取得して DB に接続できるように設定ファイルを書き換える
- DB に繋がったらマイグレーションファイルからテーブルを作成
- シーダーから初期データをインポート
みたいな感じになると思います。
では、まずインストールされているかどうかのチェックを行いましょう。これは routes.php
よりは filters.php
に書くほうがいいでしょう。
<?php App::before(function($request) { // パスチェック. インストール時はチェックしない if (strpos($request->path(), 'install') !== false) { return; } $installed = false; try { // データベースにつながるならOK // あるいはインストール後に設定ファイルに書き込んで // それをチェックするのもありかも $connection = DB::connection(); $connection->table('posts'); $installed = true; } catch (Exception $exc) { return Redirect::to('install'); } });
Laravel の場合、コネクションが取得できなかった場合、例外が発生しますので catch 節に達した場合は install にリダイレクトします。ここにインストール画面を表示させます。
<?php Route::get('install', function() { return View::make('install'); });
インストール画面はこんなかんじで
<!DOCTYPE HTML> <html lang="ja-JP"> <head> <title>install</title> <meta charset="UTF-8"> <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css"> <style type="text/css" media="screen"> .container { max-width: 400px; } </style> </head> <body> <div class="container"> <div class="page-header"> <h1>install</h1> <?= Form::open(['url' => 'install/execute']) ?> <div class="form-group"> <label for="db">DB</label> <select id="db" name="db" class="form-control"> <option value="mysql">MySQL</option> <option value="pgsql">PostgreSQL</option> <option value="sqlite">SQLite</option> <option value="sqlsrv">SQLServer</option> </select> </div> <div class="form-group"> <label for="host">HOST</label> <input type="text" id="host" name="host" class="form-control" value="<?= Input::old('host') ?>" /> </div> <div class="form-group"> <label for="database">DB</label> <input type="text" id="database" name="database" class="form-control" value="<?= Input::old('database') ?>" /> </div> <div class="form-group"> <label for="username">UserName</label> <input type="text" id="username" name="username" class="form-control" value="<?= Input::old('username') ?>" /> </div> <div class="form-group"> <label for="password">Password</label> <input type="password" id="password" name="password" class="form-control" value="" /> </div> <div class="form-group"> <input type="submit" class="btn btn-primary" value="Submit" /> </div> <?= Form::close() ?> </div> </div> </body> </html>
で、ここからが本処理。やることは
です。設定ファイルの書き換えはvar_export 関数を使って設定ファイルを書き換えてみる - localdiskを参考にしてください。今回の肝は Artisan::call
を使用して SQL ファイルを用意することなくちゃちゃっとデータを整えちゃおうというところです。ここまで長かった…。
<?php Route::post('install/execute', function() { $rules = [ 'db' => 'required', 'host' => 'required', 'database' => 'required', 'username' => 'required', 'password' => 'required' ]; $val = Validator::make(Input::all(), $rules); if ($val->fails()) { return Redirect::back()->withInput()->withErrors($val); } // 設定ファイルを書き換える $config = Config::get('database'); $config['default'] = Input::get('db'); $config['connections'][Input::get('db')]['host'] = Input::get('host'); $config['connections'][Input::get('db')]['database'] = Input::get('database'); $config['connections'][Input::get('db')]['username'] = Input::get('username'); $config['connections'][Input::get('db')]['password'] = Input::get('password'); $file = '<?php' . "\n" . var_export($config, true) . ';'; File::put(app_path('config') . '/database.php', $file); try { // マイグレーション Artisan::call('migrate:install'); // マイグレーション導入 Artisan::call('migrate'); // マイグレーション実行 // 初期データ投入 Artisan::call('db:seed'); } catch (Exception $e) { return Response::make($e->getMessage(), 500); } return View::make('install/complete'); });
まとめ
作りがすごい甘かったり、ちゃんと動かしてないコードですがおおよその流れは掴めたかと思います。年内にはちゃんと書いて github にあげておきます。
*1:ServiceProvider と Facade 作るだけ