tohokuaikiのチラシの裏

技術的ネタとか。

「Laravelリファレンス」 2-1 はじめてのLaravel

この本の2章に沿った勉強。基本的にこの本は手取り足取りの入門書では無くて、WEBの情報を本としてまとめてくれたくらいの感じで取っ付くと良いかも。まぁ、「Laravelリファレンス」だもんね。

Laravel リファレンス[Ver.5.1 LTS 対応] Web職人好みの新世代PHPフレームワーク

Laravel リファレンス[Ver.5.1 LTS 対応] Web職人好みの新世代PHPフレームワーク

Composerや開発環境は一通りそろえた。VagrantでDebian8を作成した。

Laravelのインストール

とりあえず、

$ composer global require "laravel/installer:~1.1"

書籍には、installer=~1.1って書いてあったのだけど、調べても=~っていうシンタックスは無いし、:でも大丈夫だったので=は:のシノニムかな?

特に何もエラーっぽいのでなかったので大丈夫かな?

が、Laravelコマンドが使えない

そもそも環境変数の$COMPOSER_HOMEが無い。無いので、$composer global info とかしても何も情報で無いっぽい。仕方ないので、.bashrcに

export COMPOSER_HOME=~/.composer

を記述。

ていうか、そもそもこのディレクトリなかったし。

改めて先ほどのコマンドを実行

すると最初の一行に

Changed current directory to /home/vagrant/.composer

あれっ?ということは、・・・と思って先ほどの実行結果を見てみると

Changed current directory to /home/vagrant/.config/composer

って出ていた。

なるほど、$COMPOSER_HOMEを指定してないとこのディレクトリが仮のCOMPOSER_HOMEとして使われるのか。多分、HOMESTEAD使ってる前提なのかすっ飛ばしてるけど、この環境変数設定を書いておいてくれると嬉しい。

ということで、laravel installerの再インストール完了。

.bashrcに

export COMPOSER_HOME=~/.composer
export PATH=$PATH:~/bin:$COMPOSER_HOME/vendor/bin

と追加。source .bashrcでlaravelコマンドが使えるようになった。

vagrant@debian:~$ laravel new laravel/20161214

としてLaravelプロジェクトを作成。laravel/20161214/vendorにものすごい勢いでライブラリが蓄積されていく

vagrant@debian:~/laravel/20161214$ composer info laravel/framework
name     : laravel/framework
descrip. : The Laravel Framework.
keywords : framework, laravel
versions : * v5.3.26

最新安定板の5.3.26がインストールされた。

日本語パッケージの追加

vagrant@debian:~/laravel/20161214$ composer require laravel-ja/comja5:~1

問題無くインストール完了。

アプリケーションの設定

本書では「Laravelは規約よりも設定を重視」とあるけど、これは最近のFrameworkなら「設定より規約」なんじゃないか?文章の意味も通らなくなってるし。

設定

メモ * envファイルにデフォルトDBの設定値を記述 * php artisan clear-comliedでコンパイル済みコアClassファイルの削除 php artisan optimizeコマンドだと.envのAPP_DEBUG=trueの場合にコンパイル済みコアClass削除する。

Whoopsの利用

エラー表示にWhoopsを使う場合。

本書では、$composer require しているけど、折角なのでcomposer.jsonに書いてcomposer updateする。

    "require-dev": {
        ...
        "filp/whoops": "~2.1"

まぁ同じことですが。ただ、whoopsは開発環境だけで良いはずなので、

$ composer require filp/whoops:~2.1 --dev

とした方がいいかも。

app/Exceptions/Handler.php のサンプルコードに無かったので写経。TYPOが心配。

<?php
    public function render($request, Exception $exception)
    {
        if (config('app.debug')){
            $whoops = new \Whoops\Run;
            $whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler());
            return new \Illuminate\Http\Response(
                $whoops->handleException($exception),
                $exception->getStatusCode(),
                $exception->getHeaders()
                );
        }
        return parent::render($request, $exception);
    }

artisanコマンド

php artisanで実行できるコマンド。コマンド無しで実行するとコマンドリストが出る。

artisan serve

Railsのビルトインと同じようにアクセス可能ホストの制限が掛かっているので下記のようにして起動すると良い。

$ php artisan serve --host 0.0.0.0

Laravelのartisanでサーバを立ち上げた時にプライベートIPでアクセスできない問題と、その対処法 - Front-end beginner's luck

今更ですが、Composer.pharがinstallとupdateでcomposer.json/.lockを見て何をしているかを図解

基本的に、下記の事項を覚えておけば挙動は理解しやすい。

  • installは.lockを見てその通りに実行する
  • updateは、.jsonを見て依存性を解決する

composer.phar install を実行した場合にcomposer.lockの有無による挙動の違い

f:id:tohokuaiki:20161213171954p:plain

.lockがあれば待ち時間は少なくて済む。

composer.json を更新した際に、installとupdateでは何が違うのか?

ライブラリを追加したい場合にcomposer.jsonに記載したあと、それぞれのコマンドを打った場合。

install 実行

installは.lockファイルを見るだけなのでライブラリの追加は行われない。

f:id:tohokuaiki:20161213172108p:plain

update 実行

updateは.jsonを見て依存性を解決する。そのため追記したライブラリの依存性を解決しダウンロードが行われる。

f:id:tohokuaiki:20161213172150p:plain

LinuxのディストリビューションとデフォルトパッケージのPHPバージョンの一覧

ディストリビューション バージョン サポート終了 PHPのバージョン
CentOS 5 2017/3/31 5.1
CentOS 6 2020/11/30 5.3
CentOS 7 2024/6/30 5.4
Debian 7 2018/5/31 5.4
Debian 8 2020/4/30 ? 5.6
Ubuntu(LTS) 14 2019/4/30 5.5
Ubuntu(LTS) 16 2021/4/30 7

Laravel が必要とするPHPのバージョンの一覧

Release Notes - Laravel - The PHP Framework For Web Artisansから作成

Laravel PHPのバージョン
4.2 5.4
5.0 5.4
5.1 5.5.9
5.2 5.5.9
5.3 5.5.9

んー、でも現時点で https://laravel.com/docs/5.3#server-requirements を見ると 5.6.4が必要らしい。

開発環境でのConfluenceがクソ重いのでメモリを増やしてみた

Atlassian SDK使っているノートパソコンが古くなってきたのかな?と思ったくらいだったのでとりあえずメモリ増やす。

現状のメモリ使用量

管理画面の「システム情報」を見てみる。空きが14%しかない。

f:id:tohokuaiki:20161209123936p:plain

ということで、変更。

pom.xmlにて

    <build>
        <plugins>
            <plugin>
                <configuration>
                    <jvmArgs>-Xms512m -Xmx1g -XX:MaxPermSize=512m</jvmArgs>

これで、1Gのメモリを使ってくれるはず。

システムが8Gしかないのでちょっと心配なんだけど。。。 f:id:tohokuaiki:20161209124206p:plain

再起動してみる

f:id:tohokuaiki:20161209124359p:plain

これで少しでも快適になるかな・・・。

Windowsの方がやや厳しいかな・・・。f:id:tohokuaiki:20161209124914p:plain

ConfluenceのREST APIを作ってみる - POST編

GETメソッドの場合は引数を@QueryParamで受け取ればなんてことなかったのだけど、POSTの場合はちょっと違った。

なお、通信はXMLじゃなくてすべてJSONを使った場合。

AtlassianのDocumentでいうとこの辺りが参考になる。使わなかったけど。

Developing a REST Service Plugin - Atlassian Developers

あと、そもそもこの技術はJavaのjerseyを使っているので、とりあえずREST with Java (JAX-RS) using Jersey - Tutorialあたりを参考にしたりしました。

そもそもどういうRequestを作るべきなのか?

Labelを付けるREST APIを見ながら考察した。するつRequest Headerはこんな感じ。

Accept:application/json, text/javascript, */*; q=0.01
Accept-Encoding:gzip, deflate
Accept-Language:ja,en-US;q=0.8,en;q=0.6
Connection:keep-alive
Content-Length:70
Content-Type:application/json
Cookie:JSESSIONID=xxxxxxxxxxxxxxxxxxxx

普通にjQueryで$.ajaxするとContent-Typeが「application/x-www-form-urlencoded」になるので、そこを変更しなければならない。

また、POSTデータを見てみると、Request Payloadになっていて、

[{"name":"ccc","id":1481094538830},{"name":"dddd","id":1481094538831}]

まんま、JSONの形。

ということで、これをjQueryで使うには

var data = {
    foo: 123,
    bar: 456
};
$.ajax({
    url: "{ConfluenceのBASE URL}/rest/restpath/1.0/restclasspath/{pageId}/restmethod.json",
    type: "post",
    contentType:'application/json',
    data: JSON.stringify(data)
}).success(function (data, status, xhr) {

という感じでContentTypeを指定し、送信データをJSON.stringifyしてやる。

受けるConfluence側

atlassian-plugin.xml

にてRESTの指定をする。決める重要な情報は、restのpathのみ。
先ほどのAjaxで受ける場合はrestpathの部分を以下のように指定する。

<rest key="foo-bar-rest" path="/restpath" version="1.0">
    <description>RESTの説明</description>
</rest>

JavaクラスとRESTのクラスパス

クラスの場所はどこでもいいので、@Pathアノテーションに持つクラスを作る。
これは結構不思議というか、じゃあ先ほどatlassian-plugin.xmlのpathで指定したものとの関連性は無いのか?という感じである。

とりあえず、先ほどのAjaxの場合は

@Path("/restclasspath")
public class Foobar {

という感じでClassを作る。

JavaメソッドとRESTのメソッド

先ほどのAjaxのパスの場合だと

    @POST
    @Path("{pageId}/restmethod")
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    public Response api(@PathParam("pageId") FoobarModel foobarModel) {

というメソッドを作る。メソッド名はapiとしているけどこれは特に意味は無い。わかりやすいのを付ければ何でもいいのではないかと思う。

メソッドの引数としては、メソッドの@Pathアノテーション内で定義したものを、@PathParamでアノテーションされた引数と、POSTされたJSONデータを受け取るModelクラスを指定する。

POST値を受け取るModelクラス
var data = {
    foo: 123,
    bar: 456
};

を受け取りたい場合はこんな感じ。

@XmlRootElement(name = "foobar")
@XmlAccessorType(XmlAccessType.FIELD)
public class foobarModel {

    @JsonIgnore
    @XmlElement(name = "foo")
    private String foo;

    @XmlElement(name = "bar")
    private String barString;

    public foobarModel() {
    }
}

@JsonIgnoreが付いていると、その要素は無くても大丈夫になる。各プロパティに逐一全部つけるのが面倒な場合はクラスにまとめて

@JsonIgnoreProperties(ignoreUnknown=true)
public class foobarModel {
@JsonIgnoreProperties({"foo","bar"})
public class foobarModel {

としてやる。

もし、JSONが下記のようであったら

var data = {
    foo: 123,
    bar: 456
};

プロパティにJsonアノテーションを付ける。

    @JsonProperty("barStr")
    @XmlElement(name = "bar")
    private String barString;

@JsonPropertyがなくても、@XmlElementのnameで指定していればそれを援用してくれる。

このようなオプションを通してもマッピングできない場合は、common.error.jersey.ThrowableExceptionMapper が投げられる。

レスポンスの設定

レスポンスには、OK/NGのステータスとOKの場合はJSONを付けられるので

return Response.ok(new foobarModel).build();

とすると、foobarModelオブジェクトをJSONにしたものを返却できる。