2017年1月29日日曜日

Gradle / 事始め2

書き足りなかった部分をプラス
途中からSpringも混ざりますが、ご容赦願います。


メモ

$ gradlew xxx -Pargs="hoge"
-Pargs:引数の設定

jarだけ消す
$ gradle cleanJar
[root]/build/libsディレクトリ配下にあるjarを消去できます。
生成済みのclassファイルは残ったままです。

サーバポートを変更してwebアプリjarを実行する
$ java -jar demo-0.0.1-SNAPSHOT.jar --server.port=8888
でいけるはずですが、、、
no main manifest attribute, in demo-0.0.1-SNAPSHOT.jar
となりました。デフォルトポートで実行するぶんにはマニフェストファイル不要なんですがね。。。
mavenで作った際は指定できましたが、gradleだと何か足りていないみたいでした。

spring boot devtoolsを使用する
compile('org.springframework.boot:spring-boot-starter-web',
'org.springframework.boot:spring-boot-devtools')

結果、立ち上げ時のmainプロセスが、restartedMainプロセスに変わります。
これでホットデプロイできるらしいですが、これは完全サポートが保証されているわけではないみたいです。

build.gradle
sourceCompatibility:受け付けるソースコードのバージョン
targetCompatibility:クラスファイルのバージョン

SpringBootTest
package com.example;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.Assert.*;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.boot.test.web.client.TestRestTemplate;
import static org.hamcrest.CoreMatchers.is;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class DemoApplicationTests {

 @Autowired
 TestRestTemplate template;


 @Test
 public void contextLoads() {
  ResponseEntity res = template.getForEntity("/", String.class);
  assertThat(res.getStatusCode(), is(HttpStatus.OK));
  assertThat(res.getBody(), is("Hello world"));
 }

}

Assertはstaticでないといけないっていうのが気をつけどこ

Java / try with resources句
tryに()カッコをつけて、その中で閉じる必要があるインスタンスを生成する
finally句がなくてOK

IntelliJでlombokを入れる
Preferencies → Install JetBrains plugin...
→ lombokで検索 → Install
libraryに追加した後にビルドパスに追加するのをお忘れなく。。。
Eclipseでもそうですが、libraryにjarをコピーしただけでは使えません。

また、Annotation Processorsを有効にしないと@AllArgsConstructorなどが認識されない
参考:Lombokプラグインをインストールする
Preferencies → Build, Execution, Deployment
→ Compiler → Annotation Processors
Defaultを選んで、右のペインで「Enable annotation processing」にチェックを入れる

IntelliJにCoverageというプラグインが入っている
Run with Coverageで実行するとどれだけテストがカバーできているかが表示される

Spring / @SpringBootApplication
下記3つのアノテーションを1つにまとめた効果
  • @EnableAutoCOnfiguration
  • @Configulation
  • @ComponentScan

Spring / CommandLineRunnerインターフェース
DIが可能になる(プロパティに@Autowiredをつけて、インスタンスを自動生成できる)
また、mainメソッドに
SpringApplication.run(xxx.class, args);
とすることでアプリを立ち上げられる。
もちろん、自クラスにrunメソッドを記載すること。

Java可変長引数([type]... hoges)
そんなに使わないから、ググりました。
ひしだま's 技術メモページ
  • 配列としてメソッド内で使える
  • 引数のうち一つだけ
  • 最後の引数の時だけ使用可能
  • 可変長引数と同じ型でオーバーロードして、どちらにも適用されるような呼び出しは、可変長で「ない」メソッドに引数を渡す

Spring / @ComponentScanの対象になるアノテーション
  • @Component
  • @Controller
  • @Service
  • @Repository

lombok/ @AllArgsConstructor
プロパティ全てを引数に取るコンストラクタを自動生成するCC

Java / ConcurrentMapインターフェース
スレッドセーフなマップ
実装はConcurrentHashMapクラスか、ConcurrentSkipListMapクラス。

Postgre SQL / ユーザの一覧
$ select rolname from pg_roles;
or
=> \du
Describe Userかな。。。

psql / \c (database name)
pslqでのDB接続は\c (database name)

Spring / JDBCでの接続
必要なもの
  • DBコネクタライブラリ
  • spring-boot-starter-jdbc
実行の流れ
  • NamedParameterJdbcTemplateインスタンス
  • SQL文字列
  • MapSqlParameterSourceインスタンス(SqlParameterSourceインターフェース)
  • NamedParameterJdbcTemplateのqueryForObjectメソッド実行

H2DBでインメモリな設定
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.sql-script-encoding=UTF-8

H2DBで永続化する
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:file:./target/db/testdb
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.sql-script-encoding=UTF-8

SQL / テーブルがなかったら、、、
CREATE table if not EXISTS salse_table ( id int, date timestamp );

2017年1月28日土曜日

Gradle / 事始め

今更感がありますが、Gradleを初めてちゃんと触れたので、メモメモ


メモ

Mac OSXでのJAVA_HOME設定
$ export JAVA_HOME=`/usr/libexec/java_home`
バッククォートです。
注意点は、JDK変えた時に改めてexportしないといけないことですか。
$ /usr/libexec/java_home --help
Usage: java_home [options...]
Returns the path to a Java home directory from the current user's settings.
ログインユーザの環境でのjava_homeを返します。

gvmもといSDKMAN
Groovy/Grails関連のパッケージ管理ソフト
$ curl -s "https://get.sdkman.io" | bash
でインスト

$ gvm install gradle
gradleのインストール
Installing: gradle 3.3
Done installing!


Setting gradle 3.3 as default.
で終わり。

バージョンを指定したインスト
$ gvm list gradle
DL可能なバージョンを表示
$ gvm install gradle 3.2.1
など。

デフォルトバージョンの設定
$ gvm default gradle [version]

$ gradle --version
とりあえず、パス通っているかを確認

Groovy / 文字列
'シングルクォート:文字列(charじゃない)
"ダブルクォート:GString($で変数を入れることができる...「なんだと」)

Groovy / メソッド呼び出し時のカッコ
引数がないとき、メソッドの引数としてメソッドを使うとき、式の右辺でメソッドを使うときは、()が必須 その他のケースで、引数があるときはなくてもOK
1つのメソッド呼び出しする行の時だけですね。

Groovy / defによる変数の宣言
def age = 99
型を省略して変数を宣言できます。
Javaにおける、Object型の変数と同じ扱いになるそうです。

ダックタイピング
実際の値が、処理に適したものかどうかでメソッドやプロパティを捉える。

クロージャ
{}で定義する
def closure = { param -> println "$param" }
引数に対して->処理を行う
$itをつかって、引数を省略することも可能
呼び出しは、
closure.call()または、closure()
カッコの省略はメソッドと同様。

<<によってタスクに定義することも可能
task printParam << { println "$it" }

分けて書く場合、
def closure = { param-> println "$param" }
task printParam {}
printParam.leftShift(closure)

built-in task
あらかじめ利用できるgradleのタスク
$ gradle tasksで一覧表示が可能
$ gradle tasks
The Task.leftShift(Closure) method has been deprecated and is 
 ..scheduled to be removed in Gradle 5.0. Please use Task.doLast(Action) instead.
        at build_441sas0jfgrsmxsyzaz0sazay.run
        (/Users/Shogo/gitdir/gradle_git/build.gradle:1)
:tasks

------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------

Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]

Help tasks
----------
buildEnvironment
 - Displays all buildscript dependencies declared in root project 'gradle_git'.
components
 - Displays the components produced by root project 'gradle_git'. [incubating]
dependencies
 - Displays all dependencies declared in root project 'gradle_git'.
dependencyInsight
 - Displays the insight into a specific dependency in root project 'gradle_git'.
dependentComponents
 - Displays the dependent components of components in root project 'gradle_git'. [incubating]
help
 - Displays a help message.
model
 - Displays the configuration model of root project 'gradle_git'. [incubating]
projects
 - Displays the sub-projects of root project 'gradle_git'.
properties
 - Displays the properties of root project 'gradle_git'.
tasks
 - Displays the tasks runnable from root project 'gradle_git'.

To see all tasks and more detail, run gradle tasks --all

To see more detail about a task, run gradle help --task 

BUILD SUCCESSFUL

Total time: 0.957 secs


Build Setup tasks / Help tasksのグループが確認できる

とりあえずのテスト
$ vim build.gradle
task hello << {
  println 'Hello Gradle world!'
$ gradle hello
Starting a Gradle Daemon (subsequent builds will be faster)
The Task.leftShift(Closure) method has been deprecated and is scheduled to 
 ..be removed in Gradle 5.0. Please use Task.doLast(Action) instead.
        at build_441sas0jfgrsmxsyzaz0sazay.run
 ..(/Users/Shogo/gitdir/gradle_git/build.gradle:1)
:hello <-----タスク名
Hello Gradle world! <-----タスクの出力

BUILD SUCCESSFUL

Total time: 4.332 secs

$ gradle properties
ビルドスクリプトで定義されているプロパティの一覧を表示

gradleのデバッグ

-q:エラーログのみ出力する
-i:INFOレベル
-s:例外のスタックトレースを表示
-S:例外のフルスタックトレースを表示
-d:通常のスタックトレースを含むデバッグログを表示

$ gradle help --task
タスクを指定してヘルプを確認できる

ビルドスクリプトファイル名をデフォルト(build.gradle)以外のファイル名にする場合
$ gradle -b build_new.gradle hello
-bオプションでビルドファイルを指定する

initタスク
手順
  1. プロジェクトルートとなるディレクトリを作成する
  2. そのディレクトリに移動する
  3. $ gradle init --type java-library

タスクのライフサイクル
  • Internal:内部的にしか参照できない機能。ユーザが直接使うことはできない。
  • Incubating:実験的な公開
  • Public(default):公開中  どのライフサイクルステータスもつけられていないときはパブリック
  • Deprecated:廃止予定のタスク

JCenter
Mavenレポジトリ

dependency
gradle init --type java-libraryで作ったbuild.gradle
dependencies {
    // The production code uses Guava
    compile 'com.google.guava:guava:20.0'

    // Use JUnit test framework
    testCompile 'junit:junit:4.12'
}
compile:プロダクションコードのコンパイルと実行に必要なライブラリを記載 test:テストコードのコンパイルと実行に必要なライブラリを記載

Google Guava
Javaのコアライブラリ

タスクの一覧をGUIで確認する
$ gradle --gui

ビルドする
$ gradle build
Starting a Gradle Daemon (subsequent builds will be faster)
:compileJava
Download https://jcenter.bintray.com/com/google/guava/guava/20.0/guava-20.0.pom
Download https://jcenter.bintray.com/com/google/guava/guava-parent/20.0/guava-parent-20.0.pom
Download https://jcenter.bintray.com/com/google/guava/guava/20.0/guava-20.0.jar
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava
:processTestResources UP-TO-DATE
:testClasses
:test <-- テストの実行
:check
:build

BUILD SUCCESSFUL

Total time: 17.849 secs
実行すると、プロジェクトルート配下にbuildディレクトリができます。
再度、$ gradle build 実行しても、変更がないタスクはスキップされます。

$ gradle clean
buildディレクトリが削除されます

テストの実行結果
build/reports/tests/test/index.html
にテスト結果が記載されます。

テストコードの実行
$ gradle test

$ gradle tomcatRunWar

Gradleでは型の宣言が必要
最低でもdefが必要(Object型)

システムプロパティの使用
System.properties['xxx']
$ gradle -Dxxx=hoge [task]

もしくは、gradle.propertiesに記述する
systemProp.message=hoge
この場合、自動でプロパティファイルを参照するので、
引数は不要
$ gradle [task]

taskの定義
タスクの設定
<<あり:実行処理
<<なし:設定処理

2017年1月24日火曜日

Java/ org.w3c.dom

Java SE 1.4からある古いパッケージですが、今日初めて知ったので、少しメモ


メモ

Documentインターフェース
スーパーインスタンス:Node
HTML/XMLファイル全体をさすインターフェース。
ドキュメントツリーのルートを格納する。

Elementインターフェース
HTML/XMLファイルの要素のインターフェース

2017年1月22日日曜日

Groovy / Differences with Java

Groovyの公式ドキュメントを読んでみます。
参考:Differences with Java

実行環境:Groovy Version: 2.4.8 JVM: 1.8.0_111 IDE:IntelliJ IDEA 2016.3.3


Default imports

次のパッケージはデフォルトでインポートされていますので、
下記のパッケージのクラスは明示的にimportしなくても使えます。

  • java.io.*
  • java.lang.*
  • java.math.BigDecimal
  • java.math.BigInteger
  • java.net.*
  • java.util.*
  • groovy.lang.*
  • groovy.util.*
printlnで標準出力できます〜。(System.outがいらない)


Intellij IDE CEでJunitしてみる

プロジェクトを右クリックする
Open Module Settings
Libraries
+ button
Junitで検索
とりあえず現在の最新のjunit:junit:4.12を検索
OK

あとは実行クラスでassertするだけ

import org.junit.Assert;
Assert.assert();


Intellij IDE CEでgroovyしてみる

Groovyプロジェクトは最初から選べましたが、
実行してみるとSDKがないと怒られました。

実行環境がMax OSXなので、brew install groovysdkです。
先にgroovyだけでインストールしていると競合します。
(エラーメッセージにある通り、brew unlink groovy競合を回避できます)

...

が、しかし、
brewでのインストール先が、「/usr/local/Cellar/groovysdk/2.4.7」で
Intellijで選べないとこにあるわけです。
しょうがないので、公式からzipをダウンロードし、解凍したディレクトリを選択します。
これでコンパイルできます。


Multi-method(Runtime Dispatch)

オーバーロードされたメソッドについての話。
Javaだとコンパイル時にどのメソッドを呼ぶかが決まります。
一方、実行時の引数の型により、呼び出すメソッドが決まります。

公式のサンプルをIntelliJで実行できる形式にしたものが下記です。
※JUnitをライブラリに登録してあるものとします。

import org.junit.Assert;

int test(String arg) {
    return 1;
}
int test(Object arg) {
    return 2;
}
Object o = "Object";
int returnInt = test(o);

//println result;
Assert.assertEquals((long)1, (long)returnInt);


IntelliJの実行ショートカット

Ctl + Shift + r
MacでIntelliJを使うのに慣れていないものでして。。。

Array initializers

配列の初期化は[]でよろしくどうぞ。
{}はクロージャ(無名メソッド)で予約されているので、配列の初期化には使えないそうです。

unexpected token: 1 @ line 4, column 17.
   int[] array = { 1, 2, 3};
                   ^
こんな感じで怒られます。

クラスのフィールドのアクセス修飾子を省力するとprivateとなりgetter/setterが作られます

class Student {
    String name
}

Student person = new Student()
person.setName("hoge")

println(person.getName())
Javaだとデフォルトのアクセスレベルはパッケージプライベートです。

また、groovyで@PackageScopeアノテーションをつけることで、
パブリックではなく、パッケージプライベートにすることができるようです。
自分の環境だと下記のエラーでアノテーションとして認識してくれなかったのですが。。。

6: unable to resolve class PackageScope ,  unable to find class for annotation
 @ line 6, column 1.
   @PackageScope class Student {
コマンドラインで実行してもダメ、コンパイルの設定も問題なさそうでしたが。。。
stackoverflowでも同じ事例はなさそうで、
「Eclipseでクリーン実行したらエラーが消えた」という事例はありましたがIntelliJでクリーン実行なさげ。


EclipseでGroovyしてみる

上記のunable to resolve class PackageScope問題で、原因切り分けとして、
Eclipseで同じコードを実行してみます。
参考:Qiita Gradle + Spock + Eclipse環境
まずプラグインが入っていなかったので、入れます。
使用バージョンは、STS 3.8.3.RELEASE(Eclipse Neon.2(4.6.2))です。
Help → Install New Software... →
http://dist.springsource.org/snapshot/GRECLIPSE/e4.6/ に対して、groovyで検索してプラグインを入れます。
これで新規作成ウィザードでGroovy関連を使用できます。
結果、変わらず「PackageScope is not an annotation」でエラーでした。とりあえず次。


GroovyはTry with Resourceをサポートしていません

公式でARM(Automatic Resource Management)という言葉が出てきましたが、StackOverflowを見た限り、
Try with ResourceのことをARMとも呼ぶみたいです。
GroovyはTry with Resourceはサポートしていませんが、クロージャで代用することが可能みたいです。
該当するeachLineメソッドがドキュメントに載っていないので、定かではないのですが。。。
IOGroovyMethodsのpublic static <T> T eachLine(InputStream stream, Closure<T> closure)
が一番近しいですが、、、どうだか。


Static inner classes

若干Javaと異なるらしい

Static inner classes

これは全然変わらない。

Anonymous Inner Classes

インナークラスのインスタンス生成は、
outer.new.Inner()はサポートされず、new Outer(inner)で書く


Lambdas

Java8のラムダそのままの書き方ができないが、クロージャで代用できる。


GStrings

ダブルクォートで囲った文字列は、GStringとして解釈される。
ダラーマークを含む文字列が,JavaとGroovyで若干異なる出力になる可能性がある。
ただ、Java APIに沿ってGStringとStringをオートキャストしてくれる。
しかし、Objectクラスの場合は、実際の値がチェックされる。


String and Character literals

Groovyだとシングルクォートは文字列として扱われる。
char型の変数にシングルクォートの値が割り振られた時は、自動でcharにキャストする。
値を直接参照する時は、キャストされないので、明示的にキャストする必要がある。

キャスト方法

  1. (char)'a'
  2. 'a' as char
(char)'a'
String str = 'x'
char x = (char) str
println((Object)x.getClass().getCanonicalName())
println(x)
-----------
java.lang.Character
x
'a' as char
String str = 'x'
char x = str as char
println((Object)x.getClass().getCanonicalName())
println(x)
-----------
java.lang.Character
x


Primitives and wrappers

Groovyは変数を全てオブジェクトとして扱う、とさらっと書かれています。
そのため、プリミティブ型変数をラッパークラスに自動変換します。
Javaはボクシング(ラッパークラスからプリミティブ型変数への変換)より変数拡張を優先します。
Groovyでは、プリミティブ型変数の引数をラッパークラスとしてまずは扱うので、
JavaとGroovyとでオーバーライドしたメソッドの呼び出し先が異なる場合があります。


Behaviour of ==

==:値のチェック
a.is(b):参照のチェック
nullは==でいいみたいです。


Extra keywords

Javaのキーワードに加えて、Groovyはas, def, in, traitもキーワードです。


Conversions

時間があるときに、確認します。


参照サイト

公式以外はこれかな、、、
http://www.tutorialspoint.com/groovy/

Servlet / JSP 再入門とAWSやLinuxの雑記3

続き


メモ

Spring Tool SuitsにDB Viewerを入れる
パースペティクブ開こうとしたら入っていなかったです。
Eclipse MarketplaceからDLできました。
参考:Small Java World Eclipseの「DBViewer」プラグインを利用して「Java DB」の環境を作成し、SQLを発行してみる

Mac OSXでPostgreSQL立ち上げるのにハマりググる。
クライアントはすぐ見つかるが、サーバ側がなかなか起動できなかった。
失敗した方法:
PostgreSQL 9.0.4文書 17.3. データベースサーバの起動
$ postgres -D /usr/local/pgsql/data >logfile 2>&1 &
Mac OSXでbrewでpostgresqlをインストすると/usr/local/pgsql/dataにconfファイルがないみたいでした。

解決した方法:
Qiita Homebrewを使ったPostgreSQLのインストール(Mac OS Lion)
postgres -D /usr/local/var/postgres

JDBCのダウンロード
まぁ公式から。
Java SDKのバージョンにより、使用するJDBC Driverのバージョンが異なります。
  • 1.6 → JDBC4
  • 1.7 → JDBC4.1
  • 1.6 → JDBC4.2

JDBC API
(Class)java.sql.Drivermanager
: static Connection : getConnection(String url)

(interface)java.sql.Connetion
: static PreparedStatement prepareStatement(String sql)
: void close()

(interface)java.sql.PreparedStatement
: void close()
: ResultSet executeQuery()
: int executeUpdate()
: boolean execute()
: void setString(int parameterIndex, String x)
: void setInt(int parameterIndex, int x)
: void setDouble(int parameterIndex, double x)
: void setDate(int parameterIndex, Date x)

executeQuery(), execute(), executeUpdate()
  • executeQuery() = SQLを実行してResultset型の戻り値を返す
  • execute() = SQLを実行し、完了したかどうかのboolean値を返す
  • executeUpdate() = SQLを実行し、影響があった行数を返す

INパラメータ
PreparedStatmentに埋め込む"?"のこと。
インデックスは1始まり。まぁSQL絡みだから間違えないかな。

ResultSet
(interface)java.sql.ResultSet
: void close()
: boolean next()
: String getString(String columnName)
: int getInt(String columnName)
: double getDouble(String columnName)
: java.sql.Date getDate(string columnName)

JDBCの書き方
Class.forName("org.postgresql.Driver");
Connection con = DriverManager.getConnection
("jdbc:postgresql://localhost:5432/test?user=test&password=test");

PostgreSQLのserialがずれる
独自idカラムをserialかつPrimary Keyにしていたら、Webアプリでレコード追加した際に
idカラムが重複してエラーを起こしていた。シーケンスが、すでにテーブルにある値とずれることがあるらしい。
参考:ぺけみさお PostgreSQLでINSERT時に自動採番の主キーが重複してエラーが出る場合の対処法

JSP / Javaコードに変換されたソースのありか
Eclipseで確認しているのは、
[project root] / work / org.apache.jsp / [jsp file name]_jsp.java

jspファイルへのリクエストへの度に_jspServiceメソッドを実行
javax.servlet.jsp.JspWriter型のout変数にjspファイルの内容を書き込む
結果として、整形されたHTMLコードがレスポンスで渡される。

JSP / ディレクティブ
  • page:ページ設定
  • taglib:タグライブラリ
  • include:外部ファイルの読み込み

JSP / pageディレクティブ
<%@ attribute1="value1" attribute2="value2" ... %>
import属性は複数使用可能で、その他は一度しか使用できない。
pageディレクティブの設定は、そのページのみで有効
  • language:javaを指定
  • contentType:MIMEタイプと文字エンコード("text/html; charset=UTF-8")
  • pageEncoding:JSPファイルをサーブレットクラスに変換するときの文字コード("UTF-8")
  • import:一度の指定でカンマ区切りで複数のクラスをインポート可能
    e.g. import="java.util.*, java.sql.*"
  • extends:JSPから変換する際のサーブレットクラスのスーパークラス
  • info:JSPページの情報。javax.servlet.ServletインターフェースのgetServletInfo()で取得することができる
  • session:セッション有効化フラグで、デフォルトはtrue(有効)です

スクリプティング要素
  • スクリプトレット:Javaプログラムブロック <% xxx; %>
  • 式:値を出力する式 <%= xxx %>
  • 宣言:変数宣言とメソッド定義のブロック <%! xxx %>
  • JSPコメント:HTMLコメントと違い、レスポンスで返されるHTMLには含まれない <%-- xxx --%>
式は文末に;がいらないけど、スクリプトレットと宣言は;が必要
式は変数やメソッドを1回呼び出すだけだからだろうか。

暗黙オブジェクト
オブジェクトを明示的に生成しなくても使用できるオブジェクト
  • out
  • request
  • response
  • session
  • application
  • config
  • pageContext
  • page
  • exception

JSP / 他のファイルの入れ込み
  • includeディレクティブ:<%@ include file="xxxx" %>
    include元と先どちらも合わせてコンパイルするので、元で先のJSPタグを使用できる
  • includeアクション:<jsp include page="xxxx" />
    include元を先にコンパイルし、その後にinclude先のファイルの呼び出す(実行する)

JSP / forwardアクションタグ
<jsp:forward page="xxx" />
前項includeディレクティブとアクションは、あくまで呼び出し元がHTTPレスポンスを返す。
一方、forwardアクションは、呼び出し先がHTTPレスポンスを返す。

2017年1月21日土曜日

Servlet / JSP 再入門とAWSやLinuxの雑記2

続き


メモ

Eclipseでブロックコメント追加のショートカットキー(Mac OSX)
Ctl + Cmd + /
解除ができないみたいですが。。。

Eclipseで現在の行のコピーのショートカットキー(Mac OSX)
Cmd + Alt + ↑ : 現在の行を1行下にコピーする(カーソルは移動しない)
Cmd + Alt + ↓ : 現在の行を1行下にコピーする(カーソルを移動する)

Servletのエンコーディング
javax.servlet.http.HttpServletRequest
: void setCharacterEncoding(String env)

javax.servlet.http.HttpServletResponse
: void setContentType(String type)

Javaのパッケージ名は小文字で、ドメインの逆、ハイフンは使えないのでアンスコ使う
広く → 狭く
参考:めちゃログ 「Java」パッケージ名の付け方! そして作成する方法
一方、プロジェクト名はどうすべきなのか。。。

http request headerのformdataのx, y
クリック位置だそうです。知らなかった。
参考:それマグで! <input type=image>で送信すると、X,Y座標が送信されるので、調べたら闇だった

Servlet / HTTPリクエストヘッダとレスポンスヘッダ
(interface)javax.servlet.http.HttpServletRequest
: String getHeader(string name)
: Enumeration getHeaderNames()

(interface)javax.servlet.http.HttpServletResponse
: void setHeader(string name, String value)
: void setStatus(int status_code)

Servletでリダイレクト
String referer = req.getHeader("Referer");  // リファラーの取得
if ( referer == null || referer.equals( URL_STRING) ) {
  resp.setStatus(303); // ステータスの設定
  resp.setHeader("Location",  url); // リダイレクト先
} 

Javaの正規表現
(class)java.util.regex.Pattern
: static Pattern compile(String regex)
: static Pattern compile(String regex, int flags)
: Matcher matcher(CharSequence input)
参考:JavaDrive 修飾子の種類と指定方法
DOTALLフラグを初めて知りました。デフォルトでは、.(ドット)は改行コードを含まないんですね。
(class)java.util.regex.Matcher
: boolean matches()
: boolean find()
: String group()

servletでファイルアップロード
Apache commonライブラリを使います
(Class)org.apache.commons.fileupload.disk.DiskFilteItemFactory
: void setSizeThreshold(int sizeThreshold) : void setRepository(File repository)

Servelet クッキーの利用
  1. クッキーオブジェクト作成
  2. クッキー発行
  3. クッキー取得
1.クッキーオブジェクト作成
(Class) javax.servlet.http.Cookie : Cookie(String name, String value)
: String getName()
: int getMaxAge()
: void setMaxAge(int expiry)
: String getValue()
: void setValue(string newValue)

2.クッキー発行
(interface)javax.servlet.http.HttpServletResponse
: void addCookie(Cookie cookie)

3.クッキー取得
(interface)javax.servlet.http.HttpServletRequest
: Cookie[] getCookie()

Servlet セッションオブジェクトによるセッショントラッキング
javax.servlet.http.HttpSession
: Object getAttribute(string name)
: void setAttribute(String name, Object value)
: invalidate()
: setMaxInactiveInterval(int interval) # デフォルトは30分

  1. セッションオブジェクト取得
  2. セッションオブジェクトから情報を取り出し記録
  3. セッションの破棄
1.セッションオブジェクト取得
(interface) javax.servlet.http.HttpServletRequest
: HttpSession getSession(boolean create)
: HttpSession getSession()

2.セッションオブジェクトから情報を取り出し記録
(interface) javax.servlet.http.HttpSession
: Object getAttribute(String name)
: void setAttribute(String name, Object value)

3.セッションの破棄
(interface) javax.servlet.http.HttpSession
: void invalidate()
: void setMaxInactiveInterval(int interval)

Servlet / JSP 再入門とAWSやLinuxの雑記

枯れた技術ですが必要があり復習。全然入門レベルから抜け出せてないですが。

前提:
デプロイ予定:amzn-ami-hvm-2016.09.1.20161221-x86_64-gp2(CentOS6ベース)
開発環境:
Mac OSX
Spring Tool Suite 3.8.3(Eclipse Neon.2(4.6.2)ベース)


メモ

AWSの初期設定
  • locale変更(/etc/sysconfig/i18n)
  • NICの設定(/etc/sysconfig/network)
  • 固定IPの場合(/etc/sysconfig/network)
  • 一般ユーザでsudoしたい場合
  • sshのパスワード認証を禁止する
参考:お便利サーバー.com サーバーを前提としたネットワーク設定

locale変更
$ vim /etc/sysconfig/i18n
LANG="ja_JP.utf8"
LC_CTYPE="ja_JP.utf8"
参考:
Qiita sshでログインした時、localeまわりでエラーが出た場合の対処法
CentOS(6.0)でロケール関係の設定

固定IPの場合
/etc/sysconfig/networkにホストのIPアドレスとサブネットマスクを記載する
IPADDR=xx.xx.xx.xx NETMASK=xx.xx.xx.xx

一般ユーザでsudoしたい場合
$ usermod -aG wheel <USER> ←G=補助グループの設定。a=追加(ないと置き換え)
# groups <USER> ← 確認
# visudo
# %wheel  ALL=(ALL)       ALL  ←コメント(#)を外す
参考:
Qiita Linuxでユーザーをグループに追加する Qiita Linuxコマンドでユーザーのグループ確認・変更。

sshのパスワード認証を禁止する
# vi /etc/ssh/sshd_config
PasswordAuthentication no
参考:sshでパスワード認証を禁止するには

/etc/sysconfig/network
centosのネットワーク設定ファイル
HOSTNAMEの変更時に設定を忘れないこと
参考:
CentOS6.0でホスト名を書き換える

ZeroConf
ITプロ Linuxキーワード Zeroconf
DNSやhostsファイルを使用せずに、ホスト名だけでホストを特定する仕組み。
ということで、通常サーバには不要
$ cat /etc/sysconfig/network
NOZEROCONF=yes

Java8の"JDK"を入れる
java-1.8.0-openjdk.x86_64はJREなんですね。ややこしい。
どこかのwebサイトに載っていたおかげで知りました。
まぁyum searchのパッケージの説明にも書いてはあるんですが。。。
java-1.8.0-openjdk.x86_64 : OpenJDK Runtime Environment
いち開発者としてはjavac入りのJDKを入れます。
$ yum update -y
$ yum install -y java-1.8.0-openjdk-devel.x86_64


システムJava(1.7)のままだったので、1.8にふりかえます。
$ alternatives --config java
2 プログラムがあり 'java' を提供します。

  選択       コマンド
-----------------------------------------------
*+ 1           /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/java
   2           /usr/lib/jvm/jre-1.8.0-openjdk.x86_64/bin/java

Enter を押して現在の選択 [+] を保持するか、選択番号を入力します:2


# java -version
openjdk version "1.8.0_111"
OpenJDK Runtime Environment (build 1.8.0_111-b15)
OpenJDK 64-Bit Server VM (build 25.111-b15, mixed mode)
# javac -version
javac 1.8.0_111
参考:Task Notes CentOSのalternativesでJavaのバージョン管理

tomcatの対応Javaバージョン表
公式Apache Tomcat Versions
まだalpha版だけどtomcat9も出ている。これはJava8が必要。
tomcat7/8.0/8.5はJava7で対応(tomcat7はWebSocket以外はJava6で問題なし)

service登録周り
/etc/rc.d/init.dに起動・停止スクリプトを置かないとサービス登録できません。
置いたら、
$ sudo chkconfig --add <service name>
$ sudo chkconfig <service name> on

SELinuxの確認
$ getenforce Disabled

IntelliJ CE(Community Editin)は Java EE非対応
大人の事情で、Eclipseを使うことにします。

Spring Tool SuiteにTomcatプラグインを入れる
今回はMarketplaceから入れました。Tomcat Manager Plugin 9.1.2

Mac OSXでEclipseを使うときは、¥ではなく\
¥だとEclipseがエスケープだと認識してくれない。。。

<html lang="ja">
「ダブルクォートいるっけ?」ググった。
改めて思うと、文字列をダブルクォートくくらないのは、Linuxのシェルくらいかな。

HTMLのテンプレート(Eclipse on Max OSX)
Preference → Web → HTML files → Templates → new HTML File(5) → Edit

cyberduckでAWS接続
FTPでなくSFTPでした。「pemどこに設定すんだろ」と思わず調べる
こちらのQiita記事(【AWS】cyberduckからファイルのアップロード、ダウンロードができない)に感謝です。

jarのデプロイ
参考:
迷走男子!! [Tomcat] Tomcatへのwebアプリのデプロイ方法(jarファイル編)
(tomcat_base)/webapps # tree hoge
hoge
`-- WEB-INF
    |-- lib
    |   `--(deploy jar file)
    `-- web.xml
というふうに、webappsにディレクトリ分けた上で、下記を配備
  • libディレクトリ
  • deploy jar file
  • web.xml

2017年1月16日月曜日

Python / 最初の一歩1

Webスクレイピングしたい、ということでPythonやります


メモ

Mac
システムPythonを使うのもどうかなと思い、
pyenvでPython3系を使うことにした。

参考:Mac に Python 3.x 系と 2.x を共存するベストな方法
この記事3年前じゃん、、、どんだけ遅れてるんだ俺。
pyenv install 3.6.0 でこける
$ pyenv install 3.6.0
Downloading Python-3.6.0.tar.xz...
-> https://www.python.org/ftp/python/3.6.0/Python-3.6.0.tar.xz
Installing Python-3.6.0...

BUILD FAILED (OS X 10.12.2 using python-build 20160602)

Inspect or clean up the working tree at /var/folders/hw/cjswx79j0zg_q040bz66_d8m0000gn/T/python-build.20170116211951.2465
Results logged to /var/folders/hw/cjswx79j0zg_q040bz66_d8m0000gn/T/python-build.20170116211951.2465.log

Last 10 log lines:
  File "/private/var/folders/hw/cjswx79j0zg_q040bz66_d8m0000gn/T/python-build.20170116211951.2465/Python-3.6.0/Lib/ensurepip/__main__.py", line 4, in 
    ensurepip._main()
  File "/private/var/folders/hw/cjswx79j0zg_q040bz66_d8m0000gn/T/python-build.20170116211951.2465/Python-3.6.0/Lib/ensurepip/__init__.py", line 189, in _main
    default_pip=args.default_pip,
  File "/private/var/folders/hw/cjswx79j0zg_q040bz66_d8m0000gn/T/python-build.20170116211951.2465/Python-3.6.0/Lib/ensurepip/__init__.py", line 102, in bootstrap
    _run_pip(args + [p[0] for p in _PROJECTS], additional_paths)
  File "/private/var/folders/hw/cjswx79j0zg_q040bz66_d8m0000gn/T/python-build.20170116211951.2465/Python-3.6.0/Lib/ensurepip/__init__.py", line 27, in _run_pip
    import pip
zipimport.ZipImportError: can't decompress data; zlib not available
make: *** [install] Error 1
「すぐにググるのは最低な奴がすることだ」と誰かに言われた気がする。
とはいえ、立ち向かえなさそうなエラーのため即ググる。
参考:Qiita MacでPython 3.5.0インストールに失敗したら
xcode-select --install
xcodeのCLIツールが必要らしい
その後は無事成功

pyenv install --list
pyenvでダウンロード可能なバージョン一覧

pyenv versions
インストール済みのバージョン一覧

GithubのSSH公開鍵が違っていたりとかね
cat ~/.ssh/id_xxx.pub
を貼り付け

$ pyenv local 3.6.0
実行ディレクトリでpythonバージョンの変更

$ pyenv global 3.6.0
システム全体で使用するpythonバージョンを変更する

pyenv local xxxしてもバージョンが変更されない
  • eval "$(pyenv init -)"が実行されていない
  • $ which pythonが「/usr/local/bin/pyenv」のようにpyenvを示していない
の2つの場合があるそうです。参考:Qiita pyenvでPythonがSystemバージョンから切り替わらない時の対処
vim /etc/pathsが探索パスだと初めて知った。謝謝。

今日は環境構築でおしまい

2017年1月15日日曜日

PHP / DateTime

PHPでの日付・時間の取り扱い方を振り返ります。


メモ

$time = new DateTime('now');
現在時刻でDateTimeクラスインスタンスを生成する

$time->format('Y-m-d H:i:s')
指定したフォーマットで日付を返します。
Y=4桁の西暦
y=2桁の西暦
m=2桁の月
M=英単語の略称 e.g. Jan,Feb
d=2桁の日
H=24時間表記の時間
h=12時間表記の時間
i=2桁の分
s=2桁の秒

2017年1月14日土曜日

Schoo / Webサーバー運用のためのLinux実践 3rd

Schooのメモ


メモ

RTO
Recovery Time Objective
障害から復旧までの目標時間
参照:RPOとRTOの考え方
ちなみに、RPOはRecovery Point Objectiveで、復旧させる時点のことらしいです。

Ansible
構成管理ツール

KNOPPIX
Optimal Diskからの起動を前提としたLinux distribution

OS不調時の対処
  • OSの再インストール
  • 代理boot
  • Snapshotからの復元
  • Orchestrationシステムからの復元

>grub でOS起動が止まった場合
/boot/grub2/grub.cfgが読み込めていない可能性がある

Virtual BoxでISOファイルから立ち上げる
マシンを停止させる
設定
ストレージ
IDE Controllerで光学式ディスクを追加
(今回はLive DVDにチェックを入れてみました)
システム
Boot OrderでOpticalを一番上にする
マシンを起動する
Troubleshooting
Rescue a CentOS system
1) Continue
$ chroot /mnt/sysimage
$ cd /boot/grub2
$ grub2-mkconfig -o /boot/grub2/grub.cfg $ exit $ exit

自動再起動
起動中のkernelパニックに有効な対処は再起動
自動再起動を設定することで、素早く対処することができる
$ cat /proc/sys/kernel/panic
0
kernel.panicオプションの値で、1以上だとシステムが停止したら自動で再起動する

- 設定 -
$ vi /usr/lib/sysctl.d/00-system.conf
~
kernel.panic = 10
$ sysctl -p 00-system.conf # 設定の反映
$ sysctl kernel.panic
kernel.panic=10 # 設定の確認

カーネルパニックを起こしてみる
echo c > /procy/sysrq-trigger
実際に10秒ぐらいで再起動かかった
ただ、ログイン必要ですね。。。。
現地には行かなくても済むけど、サービス断の短期化の効果は小さい

Schoo / Webサーバー運用のためのLinux実践 2nd

Schooのメモ


メモ

UEFI
Unified Extensible Firmware Interface
UEFIはBIOSに変わるブートローダ

grub2-mkconfigがない場合
yum install -y grub2でインストールしたgrub2-toolの中に入っているみたいでした。

起動ログの標準出力
$ cat /etc/default/grub
~
GRUB_CMDLINE_LINUX="rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhbg quiet crashkernel=auto biosdevname=0 net.ifnames=0"
~
$ grub2-mkconfig -o /boot/grub2/grub.cfg # 修正を実体に反映させる

rootパスワード紛失時の変更
CentOS6まで:シングルユーザーモードでrootパスワードリセット
CentOS7:シングルユーザーモードへの移行にrootパスワードが必要に!
-> 初期ramディスク=initramfsマウント時点で処理を止める
(=rootfsロード前)

rd.breakオプションで処理を止める
起動ブートローダ選択時にeを押す
linux16で始まる行の最後に、「rd.break」と入力
ctrl xを押す
swithc_root:/# というプロンプトになります。
# mount -o remount,rw /sysroot #/sysrootを読み書き可能で再マウント
(読み取り専用になっているらしい)
# chroot /sysroot # rootディレクトリの変更
# LANG=C # asciiコードを文字コードとして使用 # passwd root # rootユーザのパスワード変更
# passwd root
Changing password for user root.
New password:
BAD PASSWORD: The password is shorter than 8 characters
Retype new password:
passwd: all authentication tokens update successfully.
exit -> exitで改めてブートする

SELinuxの停止
$ getenforce
enabled
$ vi /etc/selinux/config
SELINUX=disabled
$ getenforce
Disabled

Schoo / Webサーバー運用のためのLinux実践 1st

Schooのメモ


メモ

OS起動の流れ
  1. BIOS起動@Mother Board
    1. ハードウェア初期化
    2. ブーとデバイス検索
  2. ブートローダ読み込み@Storage
    1. kernel展開
    2. rootfs mount
    3. Systemdの起動

FHS
Filesystem Hierarchy Standard
/(ルート)を頂点とした、階層構造のファイルシステム基準のこと

BIOS
マザボのROMに格納されている
POST(Power On Self Test)を最初に実行し、HW不良の有無を確認する

ブートローダ
kernelを起動するプログラム
LILO/ GRUB / GRUB2などがある
CentOS6=GRUB
CentOS7=GRUB2

rootfs
/(ルート)ディレクトリを管理するファイルシステム
まぁ名前の通りですね

rootfsをmountする前に、
初期ramディスク(initramfs)からデバイスドライバをロードする

grub.cfgの編集
GRUB2のコンフィグファイルである/boot/grub2/grub.cfgは直接編集できない
編集用の/etc/default/grubを編集したのちに、grub2-mkconfigコマンドで反映させる

CentOS7のランレベル
数字ではなく、UNITの値で操作する

起動レベル対応表
  • CentOS6 : CentOS7
  • 0 : poweroff.target
  • 1 : rescue.target
  • 2-4 : multi-user.target
  • 5 : graphical.target
  • 6 : reboot.target
まぁ慣れれば、7の方が分かりやすそうですね。

起動レベルの変更(システム起動時)
起動中にe
linux16で始まる行で systemd.unit=rescue.xxx ctrl + x で起動

起動レベルの変更(システム起動中)
systemctl isolate xxx.target

DAS
Direct Attached Storage
1つのサーバがあるストレージを占有する方式
クライアントからDASへアクセスする場合は、
クライアント -> サーバ -> ストレージという流れになり、
アクセス速度は高速ではない。

Schoo / Webサーバー運用のためのLinux実践 - 5th/6th

Schooさんの授業のメモ


メモ

fdisk -l
接続されているディスクの一覧表示

IDEとSCSIでデバイスファイルが違うんですね
/dev/hda IDEタイプHDD
/dev/sda SCSIタイプHDD
参考:/dev/hdaとか/dev/sdaとはなんぞや?

パーティションの種類
  1. 基本パーティション
  2. 拡張パーティション
  3. 論理パーティション

基本パーティション
4個までしか作れない上、4個作ってしまうとそれ以上パーティショニングが実行できない。

拡張パーティション
論理パーティションを格納するためのパーティション
拡張パーティション自体はデータを保存できない

論理パーティション
拡張パーティション内に作成される、データ格納用のパーティション


fdisk /dev/sd?
追加したディスクに対してディスクのパーティションを作成する
n -> p -> Enter -> Enter -> +nG (サイズに該当) -> w(終了)

mkfs -t xfs /dev/sdn
centosは上
ubuntuはmkfs.xfsをインストする

blkid /dev/
デバイスのファイルシステムを確認できる

マウント
一時的なマウントと永続的なマウントがある

mount -t xfs -o defaults /dev/ /
一時的なマウント

/etc/fstab
$ cat fstab
LABEL=cloudimg-rootfs / ext4 defaults 0 0
/dev/sdb1 /mnt ext2 defaults 0 0

mount -a
fstabの内容に沿ってマウントしてくれる。
シャットダウンで永続的マウントを確認する前に、
こちらで確認する

そもそもVirtual Boxへの仮想HDDの追加方法
Virtual Box -> マシンを選択しSetting※停止中であること
-> Storage -> box-diskを含むControllerの右横のディスクの追加ボタン
-> 今回はvmdkを追加しました。
これで、/dev/sdbからsdc,sddへと追加されます。

fdisk /dev/sdn
コマンド (m でヘルプ):t
※ パーティションのシステム ID を変更する
8e Linux LVM

partprobe
inform the OS of partition table changes(man)
パーティションの内容を変更したら、念のためOSに変更を通知する

Physical Extent
物理ディスク(デバイス)を仮想的に分割する最小単位

Physical Volume
物理ディスク(デバイス)を PE単位で分割した仮想ボリューム
Physical Volume=物理ボリュームという割には仮想的なボリュームです。

pvcreate /dev/device_file1 /dev/device_file2
Physical Volumeの作成

pvdisplay /dev/device_file1 /dev/device_file2
Physical Volumeの詳細表示

vgcreate volutemGropu /dev/device_file1 /dev/device_file2
Volume Groupの作成

vgdisplay -v volutemGroup
Volume Groupの確認

lvcreate -L nM -n logicalVolume volumeGroup
Logical Volumeの作成

lvdisplay volumeGroup/logicalVolume
Logical Volumeの確認

LVのサイズを変更するには、
パーティションのサイズの変更
ファイルシステムのサイズを変更

lvextend -L 50M /dev/volumeGroup/logicalVolume
パーティションのサイズの変更

xfs_growfs /dev/volumeGroup/logicalVolume
ファイルシステムのサイズを変更

Schoo / Webサーバー運用のためのLinux実践 4th

Linuxはまだまだ入門者の域を抜けられないので、少しSchooで勉強


メモ

ファイルシステム
ディスクベースとメモリベースに分けられる
ディスクベース:xfs, ext n, btrfs メモリベース:tmpfs

ttyコマンド
接続している仮想端末のデバイスファイル名を出力する

dd if=/dev/zero of=/boot/grub2/sample bs=4000 count=10
/dev/zero=Linuxのスペシャルファイルの一つ。全てNULL文字

du
オプションなどがうろ覚え
du -h dir/file

df -i
inodeの使用状況の表示

ls
デフォルト=ファイル名の昇順
-U=ディレクトリ内の順番で出力
-S=サイズで降順
r, h, t, l, 1あたりは使うのでわかるんですけどね、ここら辺はU,Sはなかなか使わないですね。

echo
Schoo関係ないけど、仕事中に調べた事項
-eをつけないと¥nを改行コードとして扱わない!
-nをつけると、echoの最後の改行はなくなる

VFS
Virtual File System
Linuxのファイル管理システム
@ITさんの記事を後で読もう。

dd(1) で空ファイルを作るときは /dev/zero より seek
こちらの記事が勉強になりました。(dd(1) で空ファイルを作るときは /dev/zero より seek )

/dev/null
これもLinuxのスペシャルファイルの一つ。
明示的に消去する際に使いますね。

PHP / なかなか身につかないPHP

Code IQでHTMLのスクレイピングの問題が出ていたので、PHPで書いてみた。
課題はクリアできなく、振り返りです。

<?php
$input =  trim(fgets(STDIN) )  ;
$th = array();
$td = array();
while ( $input ) {
    // echo $input . "\n";
    preg_match('/^<th>(.*)<\/th>$/', $input, $match_th);
    preg_match('/^<td>(.*)<\/td>$/', $input, $match_td);
    // var_dump($match);
    if ($match_th ) $th[] =  preg_replace('/<\w*>/', '' , $match_th[1] );
    if ($match_td ) $td[] =  preg_replace('/<\/?\w*>/', '' , $match_td[1] );
    $input =  trim(fgets(STDIN) ) ;
}

printCsv($th);
printCsv($td);


function printCsv($array) {
    foreach ($array as $key => $var ) {
        echo "\"" . $var . "\"";
        if ( $key < count($array) -1 ) {
            echo ",";
        } else {
            echo "\n";
        }
    }
}



function e($target){
    return htmlspecialchars($target, ENT_QUOTES);
}
?>


メモ

trim(fgets(STDIN) )
標準入力の読み込みと両端スペースの消去

preg_match(regex_str or regex_array, str or array, $store);
パターンマッチした行とグループ化した部分を$storeに格納する

preg_replace(regex_str, inserted_str , target_str );
target_str内でregex_strに対応する部分をinserted_strに置き換える。
preg_matchと同様にregex_strとinserted_strは配列でも構わない

count($array)

PHPの配列の要素数のカウントを思い出せずググった次第です




foreach ($array as $key => $var ) {

同じく

htmlspecialchars($target, ENT_QUOTES);

同じく

fputcsv(output , array [, delimitter[, enclosure[, escape_char] ] ] )

配列をcsvで出力する
enclosureがつくルールがわからず、今回は使えず

2017年1月12日木曜日

[読後メモ]無線LANでスマホ・PC全部繋がる!Wi-Fi完全マニュアル

Wi-Fiの設定などについて理解を深める
さすがにWi-Fiに繋げることは理解していますが、
親機の設定などは把握仕切れていないので。。。

参考書籍:
無線LANでスマホ・PC全部繋がる!Wi-Fi完全マニュアル
井村克也 著


メモ

Wi-Fi ≠ 無線LAN
Wi-Fi = Wi-Fi Allianceがテストし正常性を確認したことを示すブランド名 無線LAN = 無線方式で構築するLAN

アドホックモード
無線LAN機能を持つ機器同士で直接通信すること
iPhoneのAirDropやBlue Toothでの通信もこれにあたりますね

アクセスポイントモード
ルーティング機能は持たず、スイッチとして中継する役割をする状態

AOSS
バッファローが提供している無線LANの簡易接続機能

WPS
Wi-Fi Protected Setup
無線LANの簡易接続機能
子機で待ち受け状態にした後、
親機でWPS用ボタンを押せば、パスワード不要でネットワークを認証することができる。
注意点は子機と親機は1m以内と、かなり近くで操作する必要がある。

また、ボタン方式だけでなく、PINコード方式もあり、
子機側で表示させたPINコードを管理画面に入力することで、子機をネットワークに認証させることも可能。

IEEE802.11ac
記事を書いている時点では、新しい部類の無線LAN規格
5GHz / OFDM(LTE) / Multi-User MIMO

WEP
Wired Equivalent Privacy
解読方法が知れ渡っているので、使わないこと。

WPA
Wi-Fi Protected Access
接続時にユーザー認証が必要なWPA-EAP(Enterprise Mode)
事前共有鍵で認証するWPA-PSK(Public Shared Key)

TKIP / AES
WPA-PSK, WPA-PSK2にはTKIP / AESの2通りの暗号化方式がサポートされている

コマンドプロンプト wlanコマンド
wlanコマンドを駆使する

2017年1月9日月曜日

Azure / ひと目でわかるAzure 基本から学ぶサーバー&ネットワーク構築<続き>

前回の続き

参考書籍:
ひと目でわかるAzure 基本から学ぶサーバー&ネットワーク構築
横山 哲也


メモ

ディスクストライピングの使用
手順
  1. ディスク追加
  2. 記憶域プールの作成
  3. ストライピングされた仮想ディスクの追加

記憶域ブール
こちらの記事を参考を拝見しました。
最低でもディスク容量が4GB必要
これではまってて、容量が少ないと、そもそも記憶域プールに使用可能なディスクグループがない。
Windows Server 2012で追加された機能
サーバマネージャ → ファイルサービスと記憶域サービス
→ ボリューム・記憶域プール
→ 右上の「タスク」プルダウンメニュー

仮想ディスクの作成
レイアウトの種類
  • Simple
  • Mirror
  • Parity

1アカウントで複数サブスクリプション
可能でした

請求額アラート(Preview)
機能の有効化
旧ポータル → 右上のプロフィール画像 → View My Bill
→ 上段のナビゲーションタブからpreview features → Billing Alert Service → Enable的な何か

Accountページ → Subscription → ALERTS
→ add alert
ちゃんとロケールに沿った通貨で設定できました。
参考:公式Doc

NTFS
Winで使われるファイルシステム
FAT系と違ってアカウントごとの権限制御がある、とのこと
参考:IT用語辞典

SMB(Server Message Block)
ファイル共有プロトコル

Azure旧ポータルの好きではない点
インスタンスのKPIグラフの縦軸が相対的であること

仮想ネットワーク
仮想マシン作成時にしか指定できない。
よって、インスタンス作成前に仮想ネットワークを作成しておくこと
仮想ネットワーク間のインスタンスの通信は、エンドポイントに設定していないポートも使用できる

RPIP
Reserved Private IP
  1. ローカルPCでPowerShellのAdd-AzureAccountをじっこする方法
  2. 新ポータルを使う方法

Windowsの仮想マシンバックアップ
ゲストベースバックアップ / ホストベースバックアップ

GPT
Guid Partition Table形式
ディスクのパーティション方式

MBR
Master Boot Record
ディスクの先頭セクターのこと、またはパーティション方式

ゲストベースバックアップ
手順の最後に再起動がかかります。
  1. ディスクをオンライン
  2. ディスクの初期化
  3. パーティションの作成
  4. フォーマット
ディスクの初期化によりPartitionがGPT形式になることを確認する
Dashboard → Add roles and features
Wizardに沿って、Roleのパートで、Windows Server Backupを選択する
閉じる

ローカルバックアップ
Windows Server Backupでスケジューリングするか、
即時バックアップするかをします。
スケジューリングでディスクを占有した場合、そのあとの即時バックアップでそのディスクは使用できない。
また、インスタンスを立ち上げた直後であってもSystem stateのバックアップは時間がかかる。
11GBで約1時間かかりました。

Azureバックアップ(オンラインバックアップ)

Recovery Serviceによる仮想マシンのバックアップ
本来はオンプレミス環境のバックアップをAzureに残す目的だそうですが、 公式ドキュメント参照

Express Route
Azureのデータセンターとオンプレミス環境を繋ぐためのVPN

AD DS
Active Directory Domain Service
ADを使ったドメイン管理
詳細は後でフォローします。

Azure / ひと目でわかるAzure 基本から学ぶサーバー&ネットワーク構築

Azureを触ってみようということで、書籍をなぞってみる。

参考書籍:
ひと目でわかるAzure 基本から学ぶサーバー&ネットワーク構築
横山 哲也


メモ

クラウドコンピューティング
煎じ詰めれば、サーバーの利用形態
一般的に認知されている定義はNIST(米国国立標準技術研究所)が公開した文書によるもの。
上記文章引用:
2. NIST によるクラウドコンピューティングの定義

クラウドコンピューティングは、共用の構成可能なコンピューティングリソース(ネットワーク、サー バー、ストレージ、アプリケーション、サービス)の集積に、どこからでも、簡便に、必要に応じて、ネ ットワーク経由でアクセスすることを可能とするモデルであり、最小限の利用手続きまたはサービス プロバイダとのやりとりで速やかに割当てられ提供されるものである。

サブスクリプション
Azureの課金の単位
コア数や共同管理者数、ストレージアカウント数などに制限がある
詳細は公式参照。
対応策としては、複数のサブスクリプションを運用するか、上限の引き上げを申請する。

管理ポータル
管理画面。AWSで言うところの、コンソール。

Region / Data Center
基本的なことですが、地域とデータセンターです。
GeoもRegionと同義

クラウドサービス
インターネットからのアクセスの単位
仮想マシンの「箱」に当たる
パプリックIPアドレスを1つ持ち、インターネットからアクセスできる。
クラウドサービス間のインスタンスのアクセスには、仮想ネットワークかインターネットを経由する必要がある。

仮想ネットワーク
仮想マシンを作る前に作成する必要がある。
注意点:
クラシックポータルで、仮想ネットワークがない状態で仮想マシンを作成した場合は、 クラウドサービス内のみで利用可能なネットワークが構成されます。

virtualの意味
面白いコラムだったのですが、virtualはどちらかと言うと「仮想」よりも「事実上の」と言う意味に近いそうです。
英語の「virtual」の第一義は「事実上の」で、例文として「virtual promise」が出ていました。これは「法的な形式は満たしていないけれども効力のある契約」の意味だそうです。
引用:横山 P20
へー、知らなかった。

クラウドサービスのURL命名規則
ドキュメントでは見つからなかったですが、わざとエラーメッセージを表示させてみた。
This field can contain only letters, numbers, and hyphens. The first and last character in the field must be a letter or number. Trademarks, reserved words, and offensive words are not allowed.
  • 文字
  • 数字
  • ハイフン※最初と最後には使えない
商標、予約語、不適切な表現は許可されない、とのこと。

Storageのレプリケーション
  • Locally Redundant(LRS):同地域の同施設に3つの複製を作成
  • Geo-Redundant(GRS):組み合わせが固定された別の地域に複製を作成:地域ごとに3つの複製を持ち、合計6つ
  • Read-access Geo-Redundant(RA-GRS):Geo-Redundantの複製先は直接利用できないが、こちらは読み取りが可能となる
  • Zone Redundant(ZRS):複数の地域・施設に複製を作成
Zone RedundantはブロックBLOBのみサポート
参照:公式

ストレージアカウントの主なサービス
  • BLOB(Binary Large OBject
  • Que
  • Table
  • File
また、BLOBは2種類ある。
  1. ブロックBLOB:連続再生に向いている
  2. ページBLOB:ランダムアクセスに最適化している
公式を読んでて面白いなと思ったのは、「LRSについては、データの書き込み時は3回レプリケートし、3つとも書き込まれた場合に、書き込みが正常に終了する」と言うこと。3つのレプリケーションのどれかが主であるわけではないんですね。
また、LRSはデータセンターレベルの障害でデータ損失の可能性がある(10年単位であるかないかだと思いますが)ので、MSとしてはGRSを推奨している。しかし、LRSが望ましいケースもあるとのこと。

GRSのリージョンペア
GRSのセカンドリージョンは固定
東日本と西日本がペアです。今のところ、もう少し離れててもいいじゃないかと。。。

仮想マシンが持つ動的IPアドレス(DIP)
DHCPサーバから割り当てられ、再起動するまでは同じ

Virtual Machineの種別
TierとSizeで分別される。 Tier = Basic / Standard
Basicの方は、機能が一部省かれます。
Azure ロード バランサーと自動スケーリング機能が提供されず、料金は最大で 27% 低く設定されています。
引用:Basic (基本) レベルの仮想マシン
Size = CPU, Memory, Disk, GPUの組み合わせ
Azureの仮想マシンのサイズを確認してみた
  • A-series
  • A-series - compute-intensive instances
  • Av2-series
  • D-series
  • Dv2-series
  • DS-series*
  • DSv2-series*
  • F-series
  • Fs-series*
  • G-series
  • GS-series*
  • H-series
  • N-series
A = 汎用、 D = SSD使用の入出力性能重視、 G = 大容量Memory使用の演算性能重視
F = Dv2シリーズと同じプロセッサを搭載しているものも、Dv2シリーズと比べ、コア当たりのメモリやローカルのSSD容量は小さい
Tier BASICで選べるのはA seiesのみ。

RDMA
Remote Direct Memory Access
ダイレクトメモリアクセス(Direct Memory Access (DMA))は、CPUが介在することなく、ホストメモリへ直接アクセスを行うデバイスの機能である。 RDMA (Remote DMA)は、CPUが関与することなくネットワーク越しにリモート計算機上のメモリへアクセスする(すなわち、リモート計算機上のメモリからリードおよびリモート計算機上のメモリへライトする)機能である。

参考:SSD情報

クラウドサービスのRDP時のポート
ランダムなポートが割り当てられる
通常はTCPの3389番

RTM
Release To Manufacutre
完成品

FCS
First Customer Shipment
最初の発送

SysPrep
サーバ固有の情報を抜いて仮想マシンイメージを作ることができるツール
GUIもあるが、/move:vmオプションが使えない(HW検査を省略できない)
VMIからSysPrep済みかは分からないので、分かりやすいVMI名をつけないとハマる

windowsサーバで英語キーボードと認識される
結局解決策は分からず。。。
やっていること
  • 言語に日本語追加
  • Dateを日本に変更
  • Localeを日本に変更
  • 標準キーボードのドライバを106/109(Ctrl+Eisu)に変更
  • Mac RDPとMac RDP Betaの両方とも試す

waagent
Sysprepと同様な機能を持つLinuxインスタンス向け構成管理ツール
sudo waagent -deprovision

VMI
Virtual Machine Image
旧Azureポータルだと少し分かりづらかった。
左カラム・VIRTUAL MACHINES → 右ウィンド・IMAGES

VMIからのWindowsインスタンスの作成
Tier / Size※ / ユーザ・PW / Cloud Service = 変更可能
Region / Storage Account = 変更不可

Immutable Infrastructure / Disposal Infrastructure
本番環境のサーバ環境設定を継続的に変更を加えるのではなく、
開発環境で新しい環境を毎度作り、それを入れ替える形で都度展開するインフラの保守方式

99.95%のSLA
仮想マシン2台以上で冗長構成すると言う条件で99.95%

Scaling Up
再起動を伴います。構成変わるから、しょうがないっすよね。
また、再起動に伴い、DHCPも振り直されます。

変更方法:インスタンスの詳細情報から、CONFIGUREタブでTier / Sizeを変更できます

Windows ServerのID
Local Security IDとDomain Security IDがあるみたいです
ここら辺は別途確認します。Win Server全然使ったことないからなぁ。。。

Intel® Xeon® Processor E5-2660 (20M Cache, 2.20 GHz, 8.00 GT/s Intel® QPI)
Intel Xeon
はい、サーバ周りも強くないので、Xeonを調べました。
下記ページを参考にさせていただきました
CPUにXeonを使う意味や違いを初心者向けに解説
プロセッサだけでなく、ECC対応のメモリがないとパフォーマンスを引き出せないんですね

リソグラフィー(Lithography)
半導体の製造技術

ECC対応メモリ
Error Check and Correctですか。
64bitごとに8bitの検出用データを付与して、
1bitは訂正、2bit以上でも検出はできる

障害ドメイン
物理的サーバラックに近い

更新ドメイン
アプリケーションの更新の単位

可用性セット
冗長構成を組むために使用する論理グループ

Affinity Group
以前は使用されていた機能らしい
当初は、複数のサーバを立てた際に、物理的に遠い
(と言ってもデータセンター内でしょうが、、、)所に配備されていたそうです。
そのため、Affinity Groupと可用性セットを組み合わせることで、
「なるべく物理的に近い、異なる障害ドメインに複数のサーバを配備」することができたらしい。
今はAffinity Groupを設定しなくても、上記のように計らってくれる。
ちなみに、設定は、旧ポータルのSETTINGS → AFFINITY GROUPSに残っています。

END POINT
Stand Alone / Load-Balanced Set

動いているインスタンスのシリーズ変更
試してみましたが、できないみたいです

ATAディスク
ATA / IDE / PATA はどれも同じものを指している。
SerialよりParallelの方が早そうなものですが、同期処理がオーバーヘッドになるそうです。
SATAがSerial-ATAだとは覚えていたが。。。

TierがBASICだと可用性セットが使用できない
書いているそばから忘れていた
Load-Balanced Set End Pointが作成できなくてはまっていましたが、
TierがBASICだとロードバランサーが使えませんでした。

Probe Protocol
HTTP or TCP
正常性確認のプロトコル
プロトコルに応じたポートとURLを指定する。
インターバルと回数で、「障害からダウン認定」と「復帰から正常認定」の最大時間が決まる

iSCSI
IPネットワークでネットワークドライブを使用するためのプロトコル

データ共有方法
  • データベース接続
  • ファイル共有
  • ディスク共有
  • データ複製

ディスクの追加
デフォルトだとWindowsに対して1つしかディスクを追加できない?
追って確認します。

追記:問題なく実行できました。ディスク名変えてないという凡ミス。

ホストキャッシュ
Guest OSのキャッシュとは別に、Azure側でもつキャッシュ

Azure Virtual Machine Diskの容量制限
1 - 1023 GBまで

2017年1月8日日曜日

Perlの復習

Perlの復習
Perl入学式のサイトを参考にさせてもらいました。

2017/01/15 再開!


メモ

localeをjaにする
$ sudo apt-get install language-pack-ja
$ sudo update-locale LANG=ja_JP.UTF-8
Ubuntuだったのでupdate-localeを使ってja_JP.UTF-8に設定する。
LAUNGUAGEとLC_ALLだけunsetだったので、手動で設定
$ export LC_ALL="ja_JP.UTF-8"
$ sudo export LANGUAGE="ja_JP.UTF-8"

perl -v
v5.18.2

nautilus
Ubuntuのファイルマネージャ
Ubuntuのデスクトップは使わないので、縁がない。。。

open
Mac OS XのFinderを開くコマンド

Encodeモジュール
文字列のエンコードを処理するモジュール

Perl5のバージョニング
5.nが偶数=安定版、奇数=開発版

サポート対象
最新版の1つ前の安定板までが基本的にサポート対象

Ubuntuのバージョン確認
lsb_release -r

CPANの読み込みでメモリ不足でuntarできない
$ sudo cpan
cpan[1]> upgrade

Running install for module 'Digest::SHA'
Running make for M/MS/MSHELOR/Digest-SHA-5.96.tar.gz
Fetching with HTTP::Tiny:
http://ftp.neowiz.com/CPAN/authors/id/M/MS/MSHELOR/Digest-SHA-5.96.tar.gz
Fetching with HTTP::Tiny:
http://ftp.neowiz.com/CPAN/authors/id/M/MS/MSHELOR/CHECKSUMS
Checksum for /home/vagrant/.cpan/sources/authors/id/M/MS/MSHELOR/Digest-SHA-5.96.tar.gz ok
Uncompressed /home/vagrant/.cpan/sources/authors/id/M/MS/MSHELOR/Digest-SHA-5.96.tar.gz successfully
Using Tar:/bin/tar xf "Digest-SHA-5.96.tar":
Couldn't untar Digest-SHA-5.96.tar: 'メモリを確保できません'
Package seems to come without Makefile.PL.
  (The test -f "/home/vagrant/.cpan/build/MSHELOR-ENMFP5/Makefile.PL" returned false.)
  Writing one on our own (setting NAME to DigestSHA)
  Had problems unarchiving. Please build manually
Running make test
  Make had some problems, won't test
Running make install
  Make had some problems, won't install

vagrant上のUbuntuへのメモリ割り当ての増加
Vagrantfileのvb.memory = "1024"の行のコメントアウトを外す
$ free
             total       used       free     shared    buffers     cached
Mem:       1017772     236296     781476        988      11732     104264
-/+ buffers/cache:     120300     897472


$  cat /proc/meminfo | grep MemTotal
MemTotal:        1017772 kB
設定する前のメモリ容量を確認し忘れていましたが、
とりあえず解決した。

perldoc モジュール
モジュールのヘルプを見れる

#!/usr/bin/env perlについて考える
自分の環境だと/usr/bin/perlなので、なんで/usr/bin/envなんだったかと調べた。
「env コマンド」で環境変数でコマンドを実行
/usr/local/binや/usr/bin/に固定すると汎用性が下がるからということですね。

use strict;
文法を「厳しく」チェックする

use warnings;
不適切なコーディングに対して警告を出す。

use Data::Dumper;
Dumperモジュールの使用
print Dumper $var;

Ubuntuでのperlアップグレードに手こずる
CPANでのupgaredeに失敗し、最終的にperlbrewというツールでアップグレードできました。
作者に感謝。こちらのサイト(perlbrewで構築するモダンなPerl環境)を参考にさせてもらいました。
$ curl -kL http://install.perlbrew.pl | bash
$ echo "source ~/perl5/perlbrew/etc/bashrc" >>  ~/.bashrc 
$ source ~/.bashrc 
$ perlbrew available # 利用可能バージョンの確認
$ perlbrew install  perl-5.24.0 # 5分ぐらいかかった
システムperlを上書いてしまうみたいです。

Perlの変数
知っているつもりだけど、改めて記載
  1. スカラ変数:$
  2. 配列:@
  3. 連想配列:#
my $hoge;
$hoge = "hoge";
# my $hoge = "hoge";

**
ベキ乗数の計算。左結合 3**4 => 3 * 3 * 3 * 3 => 81

インクリメント
後置も前置もオッケー

STDINのいい感じの処理
my $stdin = &let;STDIN>;
  chomp($stdin);
  @stdin = split(/,/,$stdin);
また、「すぐわかるPerl」深沢千尋さん著には次のいい感じのコードがあった。
while( <STDIN> ) {
  print ;
}
$_が省略されている。$_には最後に評価したものが入るみたいです。

数値と文字列の比較演算子が違う
==(数値), eq(文字列)
逆で覚えていた。。。

数値と文字列を比較した場合
数値の比較演算子(==, >=など)で、数値と文字列を比較した場合、
文字列は数値として扱われる。その文字列の左から数字が続いている範囲の数値とする。
'1234五'などの場合、1234として扱われる。左側に数字がなければ('一2345'など)、ゼロとして扱われる。
「−1234 + 5 = 5」となります(※−は「マイナス」を変換した記号で、文字のため、−1234がゼロと認識されてしまう)
また、実行時に警告が出ます。
(Argument "hoge" isn't numeric in addition (+) at calc3.pl line 10, line 2.)

一方、文字列の比較演算子で、数値と文字列を比較した場合は、
警告も出ず、数値を文字列に自動変換して比較できます。

Perlの偽値
  • undef
  • 空のリスト
  • 数値のゼロ
  • 文字列の0と""(空文字)

Perlの真値
Perlの偽値「以外」

elsif
elsifなんです。switchないそうです。
調べてみると、5.18からgivenという構文が使えるそうですね。
参考:[[Switch]] メモとかメモのようなものとか(By ルーキーの中のひと)
ただ、今の所givenはexperimental(試験中)扱いで使用時に警告が出ます。

say関数
最後に改行をつけて標準出力する関数。
use feature ':5.18';のようにfeatureプラグマをつけないと使用できない。

chomp()
端のスペースを除く。
値を返すのかと思っていて、$var = chomp();と間違った使い方をしてた。

and, &&, or, ||
全て短絡評価する。違いは優先順位。&&,||は、and, orより優先度が高い。
代入や分岐構文として使うときに注意

評価式の左項に、変化する値を、右項に(変化することが少ない)評価基準を置く
リーダブルコードに載っていて知っていたけど、逆で書き出した自分がいました。

@
arrayのa

配列の要素を取得したらスカラー変数です
一意に決まるので。

my @nums = ( 1, 2, 3 );
配列の初期化。各要素は文字列と数値を混ぜてオッケー。 配列を入れてもオッケー。

my @nums = ( 1..3);
範囲演算子..により簡潔に書けます。
小さい方から左に書く。逆に書くと要素は空になる。

for my $num ( @nums )
foreachがあっさり書ける。

my @nums = qw(1 2 3 4 5);
空白文字で区切り、配列に格納する
デリミッター(区切り文字)は、他の記号文字に変更可能。
qw@1 2 3 4 5@も有効
区切り文字を変えることで、qw内の途中にカッコが含まれていても問題なくなる。
もしくはエスケープすることで、不本意な区切りを回避できる。

split($str, $target);
$strで$targetを区切った配列を返す。

join($str, @array)
@arrayを$strで連結させた文字列を返す

シジル(sigil)
変数の前につく記号のこと

sort
文字列ソート:sortのみ, あるいはsort { $a cmp $b } @array
数値ソート :sort { $a <=> $b } @array
※ $a, $bはsortのために予約されているので、「他の部分で使ってはいけない」

=>
ファットコンマ演算子、というらしい

$hash{name}
ハッシュの値の取り出し、nameキーの値を取り出す。

my %hash = ('key1', 'value1', 'kye2', value2);
key, value,...と言うように配列と同じように仮想配列を初期化することもできる

ダックタイピング
weblio辞書
あるインターフェースの実装を宣言していなくても、そのインターフェスのメソッドを
全て実装しているクラスは、そのインターフェスを実装しているとみなす。

リファレンス
変数の参照のこと
スカラー変数に格納する。
既存の変数、配列、連想配列の前に\(バックスラッシュ)をつけることで、リファレンスを作成できる

["a", "r", "r", "a", "y"]
配列の実体を作らずに連想配列のリファレンスだけ作る方法
無名配列とも言う。

{ key => value};
連想配列の実体を作らずに、連想配列のリファレンスだけ作る方法
無名ハッシュとも言う。

配列リファレンスを、配列として使う
@array = ("hoge", "fuga" );
$array_ref = \@array;
print ${$array_ref}[0]; # hoge
{$array_ref}で配列して扱うことができるようになる
print $arra_ref->[0] # hoge
ともかける

要素数の取得
@array, %hashでもコンテキストによっては要素数を取得できる
scalar @arrayで確実
$#arrayで最後の添え字を取得

grep { /regex/ } @array;
パターンマッチしたものを配列で返す

ハッシュのforeach
foreach my $key(keys(%array)){

デリファレンス
戻すデータ構造に対応するシジルを付与する
$$ref
@$ref
%$ref

ハッシュへの追加
$hash{key} = value;
配列と混同してしまし、pushしている自分がいました。。。

ハッシュの値のソート
foreach my $key (sort { $ranks{$b} <=> $ranks{$a} } keys %ranks){

2017年1月7日土曜日

Git / メモ

GitについてWebで調べていたら、面白い発見がありました。


メモ

$ git shortlog -ns
コミッターごとのコミット数を降順で表示されます

$ git note
注釈をつけることができます

$ git citool
GUIでgitを扱えるサブコマンドなそうな。。。
まぁそういうのがあるんだっていうだけで、実際はSourceTreeとかを使いますがね。

git show-branch
わかりやすくブランチのコミット履歴を表示する

git bisect
テストスクリプトを実行して、問題があるコミットを特定するのに使える。

git bisect

Schoo / PHPフレームワーク(Laravel)

SchooでLaravel講座をやっていたので、のぞいて見ました。 下記はメモです。


メモ

Laravel homestead
Laravel公式で配布しているサンプルvagrantボックス

ssh鍵ファイル(id_rsa, id_rasa.pub)がない場合
$ ls -la ~/.ssh # で ssh鍵ファイル(id_rsa, id_rasa.pub)の有無を確認
$ ssh-keygen -t rsa # 実行場所はどこでもいい
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/hoge/.ssh/id_rsa): 
# 保存ファイル名。デフォルトで問題ないのでエンター

Enter passphrase (empty for no passphrase):             
# パスフレーズの入力

Enter same passphrase again:                                   
# パスフレーズの再入力

Your identification has been saved in /Users/hoge/.ssh/id_rsa.
Your public key has been saved in /Users/hoge/.ssh/id_rsa.pub.

$ composer create-project "laravel/laravel=5.1.*" --prefer-dist Laravel
まず、composerを使ってプロジェクトを作る。
出力見ていると、Laravelを勝手にインストールしてくれているようでした。
Installing laravel/laravel (v5.1.33)
  - Installing laravel/laravel (v5.1.33)
    Downloading: 100%    

Composerのミラーサイト
http://qiita.com/100/items/a1d73544c70fbfa7a643 参考 

リクエストクラス
$request-input(フォーム名)
でフォールの値を取得できる。
$request-all()
連想配列でHTTPリクエストに含まれるフォームの値を取得する

Eloquent
ORマッパー
クエリを書かなくてもDBにアクセスできる
マップさせているモデルクラスを使い、
$tweet = Tweet::find(id)
でidが一致するレコードを取得する
Tweet{
  id: 2,
  boyd: "hello",
  created_ad: "2017-01-01 00:00:00"
}

レコードの更新
取得したレコードのモデルオブジェクトを更新した後に、
$tweet->save();

XAMP for linux
vagrantのGUEST OS上で、wgetでinstallerの取得
chmod +xで実行権限をつける
sudo installer で実行
sudo /opt/lampp/lampp start でサービスの起動
(httpd, mysql, ftpdの起動)

bladeの分岐構文
@if()
@endif

bladeの変数の埋め込み
{{ $hoge }}

HTMLのform要素はGET/POST以外のHTTPメソッドをサポートしていない
_methodというパラメータを使うことで、独自にHTTPメソッドの解釈を実装する
<input name="_method" type="hidden" value="PUT">

Route:resource('/tweets','TweetController');
CRUDのデフォルトのルーティングを定めたルーティング定義

layout.bladeの差し替え(テンプレートの継承)
@section('page-title')
@endsection
layout.blade内のpage-titleセクションを置き換える

Laravel フラッシュデータ
1回きりセッション変数を使う場合は、PHPのセッションを使わなくてもいい。
永続化する必要性が「ない」データを扱う。
$request->session()->flash('key', 'value');

controllerのvalidateメソッド
第1引数=リクエスト変数
第2引数=リクエスト変数がもつパラメータをkey、バリデートルール文字列の配列をvalueとした連想配列
バリデーションがNGな場合は、直前のURLにリダイレクトされる

特別なフラッシュデータ
erros=エラーメッセージを格納
_old_input=入力されたパラメータ

代表的なバリデーションルール
required = 必須
string =   文字列
max:n = n文字まで

エラーメッセージの日本語化
HiroKwsさんが作ってくださったパッケージが便利
$ composer require laravel-ja/comja5
resources/langディレクトリに言語設定がある
resources/lang/ja/validation.phpにエラーメッセージ定義がある。
ただattribute変数を、プロジェクトに沿った設定にする。
    'attributes' => [
        'body' => 'ツイート本文',
        'name' => '名前',
        'email' => 'メールアドレス',
        'password' => 'パスワード',
    ],
config/app.php の
'lacele' => 'ja'にする

名前付きルートの定義
{{ route('xxx.index'} }}でaタグのリンクを埋め込む

bladeの変数埋め込み
{{ }}HTMLスケープする {!! !!}HTMLスケープしない

認証と認可は別
認証 = ユーザの特定
認可 = 権限の付与
どっちも必要なケースが多いので、混同されがち

DBマイグレーション
DBスキーマの修正を管理する
php artisan make:migration file_name で、マイグレーションの作成
php artisan migrate で、未適用のマイグレーションファイルのみを実行

Eloquentモデルの名前付のルール
モデルクラスの名前の末尾にsをつけたテーブルができる
アッパーキャメルケースのモデルクラス名は、スネークケースでsが末尾に着く。
英語のルールにsをつけてくれる。(fox → foxiesなど)

クエリビルダ
メソッドチェーンでクエリを構築する
Model::where('columun_name', 'operand', 'value')
->orderBy('column_name', 'desc')
->get(); # or ->first();

1 : nリレーション(has - n)
1側:
public function n-models(){ # 複数形
  return $this->hasMany('n-model_location');
}


n側:
public function 1-model(){ # 単数系
  return $this->belongsTo('1-model_location');
}

php artisan migrate:reset
migrationの巻き戻し

1 : 1リレーション(has - a)
A:
public function B-model(){ # 単数形
  return $this->hasOne('n-model_location');
}


B:
public function A-model(){ # 単数系
  return $this->belongsTo('1-model_location');
}

DB設定
プロジェクトルートの .envに設定する
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_DATABASE=hoge
DB_USERNAME=hoge
DB_PASSWORD=hoge

n : nリレーション(have - n)
A:
public function A-model(){ # 単数形
  return $this->belongsTo('n-model_location');
}


B:
public function B-model(){ # 単数系
  return $this->belongsTo('1-model_location');
}

attach(id);
n:nの関係において、相手先テーブルのidにひもづくレコードを中間テーブルに追加する

detach(id);
n:nの関係において、相手先テーブルのidにひもづくレコードを中間テーブルに削除

sync([id_1, id_2,.. id_n]);
n:nの関係において、相手先テーブルのidにひもづくレコードのみ残るように更新する。
指定したidに紐づかないレコードは削除する

shift + cmd + o
PhpStormの「ファイル名を指定して開く」のショートカット

PHP preg_split関数
正規表現で文字列を分割し、配列を返す

環境設定
.envファイルで設定する
環境に合わせた.envファイル(.env.local, .env.state, .env.productなど)を用意し、
適切なものを.envにリネームする。
env('DB_HOST', 'localhost')のようにDB_HOST変数が設定されていれば、その値、
DB_HOST変数が設定されていなければlocalhostが設定される

LaravelはMVCフレームワークではない
MVCも実現できるフレームワーク

Eloquentモデルの置き場所は使い手が責任を持って決める
Eloquentモデルの置き場所はユーザが自由に選べる。

migrationメソッド
increments(column_name) = 主キーの作成
timestamp() = created_at, updated_at

Schoo / プロデザイナーが実践するHTML&CSSスキル向上トレーニング 1/5

ドットインストールからSchooへ。
「SEOの勉強には、SEOに強いWebサイトを分析するのがいい」とお聞きしたことがあり、HTMLスケッチに興味を持った。
ちょうどSchooさんでそんな講義を見つけたので、月会員(プレミアム会員 980円/月)に1ヶ月だけ登録してみて視聴した。
参考になった点のメモを残します。

Schoo link


メモ

とりあえずnormalize.cssは入れとけ

HTMLスケッチとは
ソースを見ずに、あるサイトの再現を試みること

まずは大枠を決める
media, media-side, media-bodyなど

分割する
media-bodyを, header, page-changer, article, footerに分割

Sublime Textだとa*でaタグを打てる
Sublime Text欲しくなった。。。$70か。。。。

bodyの中のboxを右上に寄せたい場合は、h1の直下
ここら辺は後で追記します。
bodyの中のブロック要素の中でboxを右上に寄せるのは難しいということかな?

部品の値はタイプするが、本文などはコピー
打つの疲れるし、本文を覚えたいわけでもないですからね。

section内の左上に寄せている画像なども、h要素の下・p要素の上に書く

target_blank(別窓マーク)の実装方法
1. imgでおく 2. background-imageでおく

Clearfix
CSSのフレームワーク???

paddingのとりあえずの決め方
上はゼロで置いてみる。右下左で調整。
4つ書くと上から時計回り

li要素の点や数字を消す
list-style:none;

medio要素
片側が固定幅・もう片側が可変幅の時に有効
左サイドがナビゲーションなど。

CSSで三角形を作ることができる
ボーダーをつける
widthとheightをゼロにする
マージンを一箇所だけ残して -n pxにする
ボーダーの太さもn以上大きくする。
参考:Animation to Explain CSS Triangles

codepen
色々サンプルがある

X scope

CSSでグラデーションをかける
参考:https://css-tricks.com/css3-gradients/

Cmd+ctrl+↑ or ↓ (Sublime Text ?)
選択している行ごと移動できる

Cmd + l
1行選択

Cmd + Enter
行の途中でも、行末で改行する

初めてのスケッチには
簡単なページを探すか、普通のページの一部分だけでやってみる。

2017年1月4日水曜日

AWS / bitnamiを試す

何をやってもハマります
AWSのEC2インスタンスにlaravel用bitnamiパッケージを展開します。


メモ

bitnami
LAMP用のlaravelパッケージを使ってみました。

localeの設定に失敗する
/home/ec2-user/lampstack-5.6.29-0/mysql "****": perl: warning: Setting locale 
failed.
perl: warning: Please check that your locale settings:
 LANGUAGE = (unset),
 LC_ALL = (unset),
 LC_NUMERIC = "C",
 LC_CTYPE = "UTF-8",
 LANG = "en_US.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
デフォルトのままだからなのか?
jpの設定にしたらこのlocaleエラーは無くなりました。

export LC_ALL=ja_JP.UTF-8
シェル変数・環境変数を共にjaに変更

/etc/sysconfig/i18n
国際化用ファイルもenのままだったので"ja_JP.utf8"で上書きました。
こちらのQiitaの記事を参照にして、インスタンスを再起動しました。

Perl Module Data::Dumperを入れても、入っていないって言われる
Error: Error running /opt/lampstack-5.6.29-0/mysql/scripts/myscript.sh 
/opt/lampstack-5.6.29-0/mysql "****": FATAL ERROR: please install the following 
Perl modules before executing scripts/mysql_install_db:
Data::Dumper
makeでインストールした(パスを通してなかった?)せいでData::Dumperを実行できていなかったみたいで、
yumでインストールしたところ問題なく実行できた。
参考:orenoblog エンジニアになりたいExcel方眼紙erの物語 /usr/bin/mysql_install_db実行時にFATAL ERROR: please install the following Perl modules before executing /usr/bin/mysql_install_db:

perl -e 'use モジュール名;'
モジュールがインストールされているかのチェックに使える。
Data::Dumperですが、Dumperだけの指定でよかった
また、当たり前のような話ですが、パス通ってなかったら直下で実行する。 参照:Perlモジュールのインストール方法

上のゴタゴタが片付いてもまだエラーが出る
/opt/lampstack-5.6.29-0/php/bin/fixreg.php 
/opt/lampstack-5.6.29-0/php/lib/php/.registry @@BITROCK_PHP_ROOT@@ 
/opt/lampstack-5.6.29-0/php
Press [Enter] to continue:

Error: Unknown error while running /opt/lampstack-5.6.29-0/php/bin/php -q 
/opt/lampstack-5.6.29-0/php/bin/fixreg.php 
/opt/lampstack-5.6.29-0/php/lib/php/.registry/.channel.pear.amazonwebservices.com
 @@BITROCK_PHP_ROOT@@ /opt/lampstack-5.6.29-0/php
Press [Enter] to continue:

Error: Unknown error while running /opt/lampstack-5.6.29-0/php/bin/php -q 
/opt/lampstack-5.6.29-0/php/bin/fixreg.php 
/opt/lampstack-5.6.29-0/php/lib/php/.registry @@BITROCK_APACHE_ROOTDIR@@ 
/opt/lampstack-5.6.29-0/apache2
Press [Enter] to continue:

Error: Unknown error while running /opt/lampstack-5.6.29-0/php/bin/php -q 
/opt/lampstack-5.6.29-0/php/bin/fixreg.php /opt/lampstack-5.6.29-0/php/etc 
@@BITROCK_PHP_ROOT@@ /opt/lampstack-5.6.29-0/php
Press [Enter] to continue:
Warning: Problem running post-install step. Installation may not complete 
correctly
 Unknown error while running chown -R root:daemon 
/opt/lampstack-5.6.29-0/frameworks/laravel/storage
Press [Enter] to continue:

Error: Unknown error while running /opt/lampstack-5.6.29-0/ctlscript.sh start 
apache & > /dev/null

結論
手動で設定しよ!

2017年1月3日火曜日

Dockerでハマる

Dockerの設定でハマりましたので、メモを残していきます。
localはMac OS X
vagrant Guest OSはubuntu trusty 14 ubuntuからさらにdocker centos


メモ

docker search centos
コンテナの検索

docker pull コンテナ名
コンテナのプル

docker images
ローカルにあるコンテナの一覧を表示
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
bitnami/laravel     latest              f4d49b3f87fa        4 days ago          498.8 MB
bitnami/mariadb     latest              c6af5faf5034        4 days ago          560 MB
centos              latest              67591570dd29        2 weeks ago         191.8 MB
hello-world         latest              c54a2cc56cbb        6 months ago        1.848 kB

docker inspect centos:latest
レポジトリ名:タグでコンテンを指定する
もしくはIMAGE IDを指定する。一意に特定できれば頭の数文字でもオッケー
JSON形式だそうです。

docker rmi コンテナ名
ReMove Imageの略だそうです。

docker rm コンテナ名
コンテナの削除

docker run centos [コマンド]
コンテナ上でコマンドの実行

docker ps [-a] [-n=n]
コンテナの起動履歴
-aをつけると終了したコンテナも確認できる
-n=5とオプションをつけると最新の5件を確認できる
Exited (0)は正常終了。普通のlinuxコマンド同様みたいですね。
docker ps -l -qで直近で起動したコンテナの ID を取得
-lはlatest、-qはquite

docker run -d コンテナ名
バックグランドでコンテナを実行

docker attach [--sig-proxy=false] コンテナID
バックグランドコンテナ(?)をフォアグランドに持ってくる
[--sig-proxy=false]をつけることでCtrl+cで抜けることができる。

実行中のコンテナの停止
docker コンテナID

docker start コンテナID
コンテナの再起動(再開)

docker run -i -t コンテナ名 シェル
-i インタラクティブモード
-t ターミナルでログイン
コンテナをフォアグランドで起動してターミナルでログイン

ターミナルでログインしたコンテナを終了する
exit
だけ

docker commit コンテナID 新しいイメージ名
既存コンテナからイメージを作成します。

Dockerfile
#コメント
FROM命令:スペースに続いて元となるイメージを指定する
MAINTAINER:スペースに続いて作成者名を記載する
RUN:スペースに続いてコマンドを指定。構築時に実行される。
CMD:スペースに続いてコマンドを指定。exec形式が推奨されている["実行バイナリ", "引数"[, "引数"] ]。
コンテナ実行時に実行される。1行しか実行されない。複数行ある場合は最後だけ。

2017年1月2日月曜日

PHP / 画像のアップロード

今回は画像アップロードについてのメモを残していきます。


メモ

PHP / GDライブラリ
画像ファイルの作成・操作をするPHPライブラリ

ini_set('display_errors',1);
エラー情報を画面に出力する設定

PHP header関数
生のHTTPヘッダーを送信する
覚えておいて頂きたいのは、header() 関数は、 通常の HTML タグまたは PHP からの出力にかかわらず、すべての実際の 出力の前にコールする必要があることです。
引用元:公式ドキュメント

uploadフォーム例
<form enctype="multipart/form-data" action="" method="POST">
    <input type="hidden" name="MAX_FILE_SIZE" value="30000" />
    アップロードファイル: <input name="userfile" type="file" />
    <input type="submit" value="UPLOAD" />
</form>
MAX_FILE_SIZEはtype=fileのインプットフォームより先に指定しないといけない

ファイルアップロード時の各種エラーメッセージ
KEY:VALUE:意味
UPLOAD_ERR_OK:0:アップロード成功
UPLOAD_ERR_INI_SIZE:1:php.iniの upload_max_filesize ディレクティブを超えている
UPLOAD_ERR_FORM_SIZE:2:HTMLフォームに指定したMAX_FILE_SIZE を超えている
などなど

PHP exif_imagetype関数
画像ファイルの拡張子を判定して対応したint値を返す
適切な拡張子を判別できない場合は、falseを返す

Imagetype 定数
画像ファイルの拡張子を表す定数群

sprintf
フォーマットした文字列を返す
一方、よく似ている"printf"は出力する

PHP sha1関数
そのまんま、引数の文字列のsha1ハッシュ値を返します。
第二2引数でtrueを渡すと、20 バイト長のバイナリ形式になってしまう。
今回は、デフォルト(false)で40文字の16進数の値を使用しました。

PHP imagecreatefromgif関数
新しいGIF画像ファイルを作る
URLかファイルパスを引数に渡す
成功した場合は、作成した画像ファイルのID、失敗した場合はFLASEを返す

PHP で h() を書くなら一緒に echo しよう。
ググっているうちに目に留まった記事ですが、確かにそうですね。

PHP uniqid関数
引数なしで、13文字の文字列を返す。
第1引数に、プレフィックストなる文字列を渡すことができる

PHP list()
言語構造。
配列を代入することで、引数に指定した複数の変数に同時に代入することができる

Google社がホストしているjQueryライブラリを使用する
Google Hosted Librariesから
1.x snippet:のscript要素を拝借します。
今回はbody要素の閉じタグ直前に配置しました。

jQuery $('セレクタ').fadeOut(ミリ秒)
選択した要素をフェードアウトさせます。

テキストをフェードアウトさせても高さを残してくにはどうしたらイイんでしょう
ブロック要素のheightをdefaultのautoから固定に変える
文字がフェードアウトすると、ガクッと下の要素が上に移動したのがいけていなかった。
高さを固定することで防げた。

2017年1月1日日曜日

PHP / カレンダー

あけましておめでとうございます。
PHPをじゃんじゃかやっていきましょう。
またまたドットインストールを参考にして、カレンダーを作った時のメモです。


メモ

&laquo;と&raquo;
<<と>>

Atomのコマンドパレット => cmd + shift + p
コマンドパレットという言葉もショートカットも忘れて途方にくれた。

Atom theme "Atom Monokai Dark"
黒背景・行番号エリアも黒くなる・行のハイライトなし
見やすくてオススメ。

PHP DatePeriodクラス
コンストラクタは3つあるが、今回使ったのはこちら。
public __construct ( DateTimeInterface $start , DateInterval $interval , DateTimeInterface $end [, int $options ] )
注意:$endは含まれません。

PHP DateTimeクラス
'2012-07-01'や'first day of this month'といった書き方が可能
「nowで今日の日付とって、dayの部分だけ1にしてDateクラス作って。。。」
みたいなPerlやJavaでありがちな処理にしなくて良い

PHP Intervalクラス
引数に"P"から始まる文字列を入れる
new DateInterval('P1D');
new DateInterval('P1Y1M1DT12H10M');など
MonthもMinuteも同じ"M"ですが、時間部分の前には"T"を入れます。

htmlspecialchars($s, ENT_QUOTES, 'UTF-8');
htmlエンコード関数。

PHP オブジェクトのコピー
$new = clone $orig
$new = $origだと参照渡しになるとのこと

PHP / laravel入門3

引き続きドットインストールのお世話になります。
今回もlaravelフレームワークのメモを残していきます。

version info
  • PHP 5.6.29
  • Laravel Framework version 5.3.28

メモ

@yeild('xxx')
セクション名(?)を決める。
ここに埋め込む内容を@sectionブロックに書く。

@extends('layouts.default')
テンプレートの指定

@section('xxx')
hoge @endsection
セクションに埋め込む内容を記述

@section('xxx' ,'hoge')
埋め込む内容を第2引数にして1行で書くこともできる。

php artisan make:controller Controller
artisanコマンドでコントローラーの作成
app/Http/Controllersディレクトリ配下にController.phpが作成されます。

dd($posts->toArray());
Dump & Die
オブジェクトを出力して、廃棄する?
改めて調べます。

途中のコントローラ
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PostController extends Controller
{
    //
  public function index() {
//    $posts = \App\Post::all();
    $posts = App\Post::all();
    dd($posts->toArray());
    return view('posts.index');
  }
}

Post::orderBy('created_at', 'desc')->get();
オブジェクトの取得、指定したカラムの降順

$posts = Post::latest('created_at')->get();
同じく、オブジェクトの取得、指定したカラムの降順

return view('posts.index', ['applicants' => $applicants]);
ビューに値・オブジェクトを渡す。
この例だと、applicantsというキーで、$applicantsを渡している。

return view('posts.index')->with('posts' ,$posts);
上の例と同じ。書き方のバリエーションありすぎ困る。。。

    @foreach ( $posts as $post )
      <li><a href="">{{ $post->title }}</a></li>
    @endforeach
bladeでのforeachの埋め込み。
foreachのオルタネイティブな書き方とにている。
{{ }} によるhtml encode(エスケープ)してくれる
試しに<script>を表示させて見たら、
ちゃんと「&lt:script&gt」と表示された

{{-- --}}
bladeのコメント
パースしてあげれば消える

foreach・オブジェクトが空の時の分岐付き
    <ul>
    @forelse ( $posts as $post )
      <li><a href="">{{ $post->title }}</a></li>
    @empty
      <li>empty</li>
    @endforelse
    </ul>
これイイすね。
Thymeleafだと一回リストが空か判定をいれるから、
ネストが深くなって読みづらくなります。forelseだとスッキリしますね。

URLの埋め込み方いろいろ
  • /comment/{{ $comment->id }}
  • {{ url('/comment', $comment->id }}
  • {{ action('CommentController@show', $comment->id) }}
'CommentController@show'は
CommentControllerのshowメソッドを実行

$comments = Comment::findOrFail($id) ;
該当するidのレコードが見つからない場合は、例外を返す

"{!! !!}" と "{{ }}"
"{!! !!}" :HTMLエスケープしない
"{{ }}" :HTMLエスケープする(PHPのhtmlentities関数を通す)

nl2br(string [,bool = true] )
PHPの関数
string内の改行コードを<br>(false時)または<br />(true時)に置き換える 改行

laravelのe()関数(ヘルパー関数)
PHPのhtmlentites関数を実行する

{!! nl2br(e($comment->body)) !!}
安全に文字列を埋め込むには、これだと覚えるしかないですかね。。。
  1. e()でエスケープ
  2. 改行を<br>タグに置き換える
  3. エスケープなしで出力(e()でエスケープ済み)

ルーティングの注意
上から見ていって先にマッチしたマッピングが動作する
ファイル指定のルーティングをパラメータ指定のルーティングより先に書く

CSS: input [type=text] { }
textのinputのブロック
最近全然CSS書いてなかったのでメモ_φ(・_・

MethodNotAllowedHttpException
ルーティングしていないURLにアクセスすると、この例外がでる

public function store(Request $request )
Illuminate\Http\Requestクラスを引数に取ることで、
HTTPリクエストのインスタンスを取得できる。

laravel Eloquentのsaveメソッド
データベースに結びついているオブジェクトを更新する

TokenMismatchException
laravel5の標準でPostのHTTPリクエストを受けると、
TokenMismatchExceptionを投げる。

SQLの失敗例外
QueryException in Connection.php line 770:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'body' cannot be null (SQL: insert into `posts` (`title`, `body`, `updated_at`, `created_at`) values (fasdf, , 2016-12-31 15:32:15, 2016-12-31 15:32:15))
フォームのnameが間違っていて、not null例外が発生したもの

{{ csrf_field() }}
このトークンをpostを投げるform内に配置することで、
TokenMismatchExceptionを回避できる。
<form method="post" action="{{ url('/') }}">
  {{ csrf_field() }}

フラッシュデータを出力する
return redirect('/')->with('msg', 'You did it!');

session('msg')
セッションの要素を取り出す。

onclick="this.classList.add('hidden')"
DOMの操作。onclickを書いた要素にhiddenクラスを追加

laravel validation
コントローラでvalidateメソッドを呼ぶ
$this->validate($request, [
  'title' => 'required|min:5',
  'body'  => 'required'
]);
バリデートに失敗すると、エラーメッセージとともに元のページに帰る

今時な(?)バリデーションエラーメッセージの表示箇所
上にまとめてとかではなく、該当箇所の横か下が良い。
ただ、入力項目が多いと微妙ですね。
エラーの時にクラスつけて表示をイイ感じにすることなどの方が大事な気がした。

今時な(?)バリデーションエラーメッセージの表示箇所
上にまとめてとかではなく、該当箇所の横か下が良い。
ただ、入力項目が多いと微妙ですね。
エラーの時にクラスつけて表示をイイ感じにすることなどの方が大事な気がした。

The title must be at least 3 characters.
"min:n"のバリデートに失敗した時のデフォルトメッセージ

The body field is required.
"required"のバリデートに失敗した時のデフォルトメッセージ

oldヘルパー関数
直前のリクエストの際の属性の値を取得する
入力フォームで便利

old('column' [, xxx ] )
old(フラッシュデータ)がない時は、
第二引数を返す

$errors->has('colum')
バリデートエラーの際に、columにエラーがあったかを判別

$errors->first('column')
エラーオブジェクトが持つ、要素のうち、最初のcolumnの値を返す

$errors->all()
バリデートエラーを全件取得。
foreachでぐるぐるするという使い方ができる

{{ method_field('patch') }}
ルーティングでpathcメソッドを使えるようにする

プレースホルダー
input:textはplaceholder属性
textareaは要素で挟んだ文字列
よく忘れる!特にtextarea!!

php artisan make:request name
Requestクラスを作成するartisanコマンド
app/Http/Requests/配下に作成されます。

Requestクラスの認証
    public function authorize()
    {
        return false;
    }
認証をしない(全部通す)場合は、 return true;

useの指定
use App\Http\Requests\PostRequest;
とクラス名まで指定(この例では、PostRequestはクラス)

a要素のhref="#" とhref=""は異なる
少しはまっていたので、メモ
「Re:href="#" onclick の悪習」という記事を参考にさせてもらいました。
a要素のhref属性に値が入ってるとonclick属性の内容を実行後にhref属性の値を参照しようとする。
逆にいうと、href=""だとdatasetに値を渡せないみたいでした。
php::
  <form id="form_{{$comment->id}}" >
    <a href="#" data-id="{{ $comment->id }}" onclick="delete(this);" >hoge</a>
  </form>
JS::
  function delete(e) {
    document.getElementById('form_' + e.dataset.id).submit();
}
一応onclickでJS自体は呼び出せてたので紛らわしかったです。
仕様はちゃんと確認できていないですが、
href=""では動かず、href="#"でgetElementできていました。

php artisan make:model Comment --migration
Modelクラスとmigrationを作成する
migrationは、database/migrations/配下
Modelクラスは、app/配下にできます。

belongsTo()

hasMany()

php artisan migrate
マイグレートの実行
間違えても親切なエラーが出る
 [Symfony\Component\Console\Exception\CommandNotFoundException]  
  Command "migration" is not defined.                             
  Did you mean one of these?                                      
      migrate                                                     
      migrate:refresh                                             
      migrate:status                                              
      migrate:reset                                               
      migrate:rollback                                            
      migrate:install                                             
      make:migration

show variables ;
SQLの環境変数の表示
ただ、数が多いので、
show variables like 'port';
show variables where Variable_name = 'port';
のように絞るとイイ。

[Illuminate\Database\QueryException]
Connection refused
vagrantでPHP/MySQL動かしていたのに、Host OSでphp artisan migrateしていた。
Guest OS上で実行して、問題なくDBにアクセスできた。

php artisan migrate:status
migrateの個々の実行状況を出力

php artisan make:migration <マイグレーション名> --table=<変更対象テーブル>
既存テーブル変更のマイグレーション作成
database/migrations/配下にできます。