CentOS + Tomcat

まずJavaのversionから

[vagrant@localhost ~]$ java -version
openjdk version “1.8.0_171”
OpenJDK Runtime Environment (build 1.8.0_171-b10)
OpenJDK 64-Bit Server VM (build 25.171-b10, mixed mode)

ふむ。
続いて、Tomcatを入れたい。

Tomcatとは?
->ソフトウェア
->Java Servletを動かすときに使う
->簡易的なWebサーバーの機能も付いている

Java Servletを動かすときに必要なソフト(サーブレットコンテナ)のひとつ
Javaはプログラミング言語
「Webサーバ上で動くJavaプログラム」を「Java Servlet(サーブレット、Servlet)」と言う
サーブレットコンテナさんが、Java Servletさんを、ちまちま動かす
サーブレットコンテナと呼ばれるソフトは、いろいろあり、その「いろいろあるサーブレットコンテナのひとつ」が「Apache Tomcat」
Java Servletの動作確認ができるように(簡易的な)Webサーバとしての機能も持っている。

Tomcat:サーブレットコンテナ
Apache:Webサーバ

本格的にやるときはApacheとTomcatを連携させて両方使う
サーブレットコンテナとしてのお仕事はTomcatが行う

Tomcatとは?
サーブレットコンテナ(Java Serveletを動かすソフト)。
正式名称は「Apache Tomcat」。
初版は1999年。
最新バージョンは8.5。
簡易的なWebサーバとしての機能も持つ。

Java Servletを動かすためのソフト。
サーバ上で動くJavaプログラム 。動的なページが生成可能。

Scrum Allianceとは

アジャイル開発手法には複数の手法あるいはプラクティスと呼ばれるものがありますが、その中で「スクラム」はもっともよく使われている手法として知られており、マイクロソフトやIBMをはじめ多くの企業がソフトウェア開発の現場で採用している。

そのスクラムを実践するための「スクラムガイド(Scrum Guide in Japanese)」が、スクラムの普及促進のための団体「Scrum Alliance」から公開

スクラム入門
正しくは、様々なプロセスや技術を取り込むことのできるフレームワークである。スクラムの役割は、複雑なプロダクト開発が可能なフレームワークを提供することで、開発プラクティスの効果を相対的に浮き彫りにし、改善することである。

スクラムの内容
スクラムフレームワークは、スクラムチームとその役割、タイムボックス、成果物、およびルールで構成される。
スクラムチームは、柔軟性と生産性の最適化を目指すものである。チームは、自己組織化しており、クロスファンクショナルであり、反復的に作業をする。
(略)
スクラムがタイムボックスを採用しているのは、規則的なリズムをつけるためである。タイムボックスには、リリース計画ミーティング、スプリント計画ミーティング、スプリント、デイリースクラム、スプリントレビュー、スプリントレトロスペクティブが含まれる。
(略)
ルールは、スクラムのタイムボックス、役割、および成果物を結びつけるものである。

—–
スクラム(英: Scrum)は、ソフトウェア開発における反復的で漸進的なアジャイルソフトウェア開発手法の1つである。この方法論は「柔軟かつ全人的なプロダクト開発ストラテジーであり、共通のゴールに到達するため、開発チームが一体となって働くこと」とされる。この方法論は、製品開発における伝統的な、シーケンシャルなアプローチとは大きく異なる。この方法論は、チームが自発的に組織だって行動することを可能にする。この自己組織化を実現するのは、すべてのチームメンバーが物理的に同じ場所にいること、あるいは密なオンライン共同作業を通じ、全員が日々直接会ってお互いにコミュニケーションをとり、プロジェクトにおける規律を守ることである。

スクラムのカギとなる基本原則は、プロジェクト開発の途中で、顧客は、要求や必要事項を変えられるという認識である。予想できない変更について、計画に基づく方法で対処することは、容易ではない。したがって、スクラムは経験に基づくアプローチを採用する。問題を十分に理解することも、定義することもできないので、現れた要求へ素早く対応するためのチームの能力を最大化することに集中する、というアプローチである。
—–

開発途中での仕様変更を認めるということでしょうか。こういう資格があること自体知らんかった。

modelを編集していく

app直下のcomment.php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    //
    protected $fillable = ['body'];

    // $comment->post
    public function(){
    	return $this->belongsTo('App\Post');
    	
    }
}

post.php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    //
    protected $fillable = ['title', 'body'];

    public function comments(){
    	return $this->hasMany('App\Comment');
    }
}
<h2>Comments</h2>
<ul>
	@forelse ($post->comments as $comment)
	<li>
		{{ $comment->body }}
	</li>
	@empty
	<li>No comments yet</li>
	@endforelse
</ul>
@endsection

しまったーーーーーーーーー ファイル保存する前にmigrateしてバグってしまった。
なんてことを。。
まぁ、Laravelに慣れる、という目的は少し達成したので良しとしよう。

commentのclassを作っていく

[vagrant@localhost myblog]$ php artisan make:model Comment –migration
Model created successfully.
Created Migration: 2018_09_09_162004_create_comments_table

databaseの中のmigrationファイル

commentのmigration fileを編集する。

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateCommentsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('comments', function (Blueprint $table) {
            $table->increments('id');
            $table->unsignedInteger('post_id')
            $table->string('body')
            $table->timestamps();
            $table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('comments');
    }
}

ここまで出来たらmigrateする。
[vagrant@localhost myblog]$ php artisan migrate
Migrating: 2018_09_09_162004_create_comments_table
Migrated: 2018_09_09_162004_create_comments_table

なんだこれー

deleteできるようにする

@section('container')
<h1>
	<a href="{{ url('/posts/create') }}" class="header-menu">New Post</a>
	Blog Posts
</h1>
<ul>
	{{-- 
	@foreach ($posts as $post)
	<li><a href="">{{ $post->title }}</a></li>
	@endforeach
	--}}

	@forelse ($posts as $post)
	<li>
		<a href="{{ action('PostsController@show', $post) }}">{{ $post->title }}</a>
		<a href="{{ action('PostsController@edit', $post) }}" class="edit">[Edit]</a>
		<a href="#" class="del" data-id="{{ $post->id }}">[x]</a>
		<form method="post" action="{{ url('/post', $post->id) }}" id="form_{{ $post->id }}">
			{{ csrf_field() }}
			{{ method_field('delete') }}
		</form>
	</li>
	@empty
	<li>No posts yet</li>
	@endforelse
</ul>
<script src="/js/main.js"></script>
@endsection

jsはpublic/jsの中に記述する。

(function(){
‘use strict’;

var cmds = document.getElementsByClassName(‘del’);
var i;

for(i = 0; i < cmds.length; i++){ cmds[i].addEventListner('click', function(e){ e.preventDefault(); if(comfirm('are you sure?')){ document.getElementById('form_' + this.dataset.id).submit(); } }); } })(); [/javascript] routing [php] Route::get('/', 'PostsController@index'); // Route::get('/posts/{id}', 'PostsController@show'); Route::get('/posts/{post}', 'PostsController@show')->where(‘post’,'[0-9]’);
Route::get(‘/posts/create’, ‘PostsController@create’);
Route::post(‘/posts’, ‘PostsController@store’);
Route::get(‘/posts/{post}/edit’, ‘PostsController@edit’);
Route::patch(‘/posts/{post}’, ‘PostsController@update’);
Route::delete(‘/posts/{post}’, ‘PostsController@destroy’);
[/php]

controller

public function destroy(Post $post){
    	$post->delete();
    	return redirect('/');
    }

main.js
スペルを間違いまくってる。。

(function(){
‘use strict’;

var cmds = document.getElementsByClassName(‘del’);
var i;

for(i = 0; i < cmds.length; i++){ cmds[i].addEventListener('click', function(e){ e.preventDefault(); if(confirm('are you sure?')){ document.getElementById('form_' + this.dataset.id).submit(); } }); } })(); [/javascript]

PostRequest Classを作る

なるほど、classを作る際はphp artisan make:hogeね。
[vagrant@localhost myblog]$ php artisan make:request PostRequest
Request created successfully.

post request classが出来た。

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class PostRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'title' => 'required|min:3',
            'body' => 'required',
        ];
    }

    public function messages(){
        return [
            'title.required' => 'please enter title!!!'
        ];
    }    
}

PostsController.phpも変更する。

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Post;
use App\Http\Requests\PostRequest;

class PostsController extends Controller
{
    //
    public function index(){
    	// $posts = Post::orderBy('created_at', 'desc')->get();
    	$posts = Post::latest()->get();
    	// $posts = [];
    	// dd($posts->toArray()); // dump die
    	// return view('posts.index', ['posts' => $posts]);
    	return view('posts.index')->with('posts', $posts);
    }

    public function show(Post $post){
    	// $post = Post::find($id);
    	// $posts = Post::findOrFail($id);
		return view('posts.show')->with('post', $post);
    }

    public function create(){
    	return view('posts.create');
    }

    public function store(PostRequest $request){
    	$post = new Post();
    	$post->title = $request->title;
    	$post->body = $request->body;
    	$post->save();
    	return redirect('/');
    }

    public function edit(Post $post){
		return view('posts.edit')->with('post', $post);
    }

    public function update(PostRequest $request, Post $post){
    	$post->title = $request->title;
    	$post->body = $request->body;
    	$post->save();
    	return redirect('/');
    }
}

laravel postをeditしよう

postController

public function edit(Post $post){
		return view('posts.edit')->with('post', $post);
    }

updateはget, postではなくpatch

@section('container')
<h1>
	<a href="{{ url('/') }}" class="header-menu">Back</a>
	Edit Post</h1>
<form method="post" action="{{ url('/posts', $post->id) }}">
	{{ csrf_field() }}
	{{ method_field('patch') }}
	<p>
		<input type="text" name="title" placeholder="enter title" value="{{ old('title', $post->title) }}">
		@if ($errors->has('title'))
		<span class="error">{{ $errors->first('title')}}</span>
		@endif
	</p>
	<p>
		<textarea name="body" placeholder="enter body">{{ old('body', $post->body)}}</textarea>
		@if ($errors->has('body'))
		<span class="error">{{ $errors->first('body')}}</span>
		@endif
	</p>
	<p>
		<input type="submit" value="Update">
	</p>
</form>
@endsection

なるほど、慣れるまで少し時間がかかるかも。

Routingはpatchにする。

Route::get('/', 'PostsController@index');
// Route::get('/posts/{id}', 'PostsController@show');
Route::get('/posts/{post}', 'PostsController@show')->where('post','[0-9]');
Route::get('/posts/create', 'PostsController@create');
Route::post('/posts', 'PostsController@store');
Route::get('/posts/{post}/edit', 'PostsController@edit');
Route::patch('/posts/{post}', 'PostsController@update');

PostsController.php
functionのupdateを追加

public function update(Request $request, Post $post){
    	$this->validate($request, [
    		'title' => 'required|min:3',
    		'body' => 'required',
    	]);
    	$post->title = $request->title;
    	$post->body = $request->body;
    	$post->save();
    	return redirect('/');
    }

laravel formのvalidation

public function store(Request $request){
    	$this->validate($request, [
    		'title' => 'required|min:3',
    		'body' => 'required',
    	]);
    	$post = new Post();
    	$post->title = $request->title;
    	$post->body = $request->body;
    	$post->save();
    	return redirect('/');
    }
}
@section('container')
<h1>
	<a href="{{ url('/') }}" class="header-menu">Back</a>
	New Post</h1>
<form method="post" action="{{ url('/posts') }}">
	{{ csrf_field() }}
	<p>
		<input type="text" name="title" placeholder="enter title" value="{{ old('title') }}">
		@if ($errors->has('title'))
		<span class="error">{{ $errors->first('title')}}</span>
		@endif
	</p>
	<p>
		<textarea name="body" placeholder="enter body">{{ old('body')} }</textarea>
		@if ($errors->has('body'))
		<span class="error">{{ $errors->first('body')}}</span>
		@endif
	</p>
	<p>
		<input type="submit" value="Add">
	</p>
</form>
@endsection

ぎょえーーーーーーーーーーーーーー

記事の新規作成

routing

Route::get('/', 'PostsController@index');
// Route::get('/posts/{id}', 'PostsController@show');
Route::get('/posts/{post}', 'PostsController@show')->where('post','[0-9]+');
Route::get('/posts/create', 'PostsController@create');

index.blade.php

@section('container')
<h1>
	<a href="{{ url('/posts/create') }}" class="header-menu">New Post</a>
	Blog Posts
</h1>
<ul>
	{{-- 
	@foreach ($posts as $post)
	<li><a href="">{{ $post->title }}</a></li>
	@endforeach
	--}}

	@forelse ($posts as $post)
	<li><a href="{{ action('PostsController@show', $post) }}">{{ $post->title }}</a></li>
	@empty
	<li>No posts yet</li>
	@endforelse
</ul>
@endsection

@extends('layouts.default')

@section('title', 'New Post')

@section('container')
<h1>
	<a href="{{ url('/') }}" class="header-menu">Back</a>
	New Post</h1>
<form method="post" action="{{ url('/posts') }}">
	{{ csrf_field() }}
	<p>
		<input type="text" name="title" placeholder="enter title">
	</p>
	<p>
		<textarea name="body" placeholder="enter body"></textarea>
	</p>
	<p>
		<input type="submit" value="Add">
	</p>
</form>
@endsection

なんじゃこりゃー 洒落にならん。

getではなく、postにします。

Route::get('/', 'PostsController@index');
// Route::get('/posts/{id}', 'PostsController@show');
Route::get('/posts/{post}', 'PostsController@show')->where('post','[0-9]');
Route::get('/posts/create', 'PostsController@create');
Route::post('/posts', 'PostsController@store');

resources/viewsの中に共通化コンポーネント

resources/viewsの中に共通化コンポーネントを作成する
ああああああああああ、cake.phpを思い出してきた。。。

default.blade.php

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="utf-8">
	<title>@yield('title')</title>
	<link rel="stylesheet" href="/css/styles.css">
</head>
<body>
	<div class="container">
		@yield('content')
	</div>
</body>
</html>

index.blade.php


@extends('layouts.default')

{{-- 
@section('title')
Blog Posts
@endsection
--}}

@section('title', 'Blog Posts')

@section('container')
<h1>Blog Posts</h1>
<ul>
	{{-- 
	@foreach ($posts as $post)
	<li><a href="">{{ $post->title }}</a></li>
	@endforeach
	--}}

	@forelse ($posts as $post)
	<li><a href="{{ action('PostsController@show', $post) }}">{{ $post->title }}</a></li>
	@empty
	<li>No posts yet</li>
	@endforelse
</ul>
@endsection

show.blade.php

@extends('layouts.default')

@section('title', $post->title)

@section('container')
<h1>{{ $post->title }}</h1>
<p>{!! nl2br(e($post->body)) !!}</p>
@endsection

うわーーーーーーーーーーー 酒飲みてーーーーーーーーーーーーーーー