[CakePHP3.10] フォームの利用

<body>
	<header class="row">
		<h1><?=$title ?></h1>
	</header>
	<div class="row">
		<table>
			<form method="post" action="/mycakeapp/hello/form">
                                <input type="hidden" name="_csrfToken" value="<?= $this->request->getParam('_csrfToken') ?>">
				<tr><th>name</th><td><input type="text" name="name"></td></tr>
				<tr><th>mail</th><td><input type="text" name="mail"></td></tr>
				<tr><th>age</th><td><input type="number" name="age"></td></tr>
				<tr><th></th><button>Click</button></tr>
			</form>
		</table>
	</div>
</body>
<body>
	<header class="row">
		<h1><?=$title ?></h1>
	</header>
	<div class="row">
		<p><?=$message ?></p>
	</div>
</body>

HelloController

class HelloController extends AppController {

	public function index(){
		$this->viewBuilder()->autoLayout(false);
		$this->set('title', 'Hello!');
	}

	public function form(){
		$this->viewBuilder()->autoLayout(false);
		$name = $this->request->data['name'];
		$mail = $this->request->data['mail'];
		$age = $this->request->data['age'];
		$res = "こんにちは、" . $name . "(" . $age . 
			")さん。メールアドレスは、" . $mail . " ですね?";
		$values = [
			"title" => "Result",
			"message" => $res
		];
		$this->set($values);
	}
}

$this->request->data[“name”] でデータを取り出している

### エスケープ処理

<body>
	<header class="row">
		<h1><?=h($title) ?></h1>
	</header>
	<div class="row">
		<p><?=h($message) ?></p>
	</div>
</body>

### フォームヘルパー

		<table>
			<?=$this->Form->create(null, ["type"=>"post", "url"=>["controller"=>"Hello", "action"=>"index"]])?>
				<input type="hidden" name="_csrfToken" value="<?= $this->request->getParam('_csrfToken') ?>">
				<tr><th>name</th><td><?=$this->Form->text("Form1.name") ?></td></tr>
				<tr><th>mail</th><td><?=$this->Form->text("Form1.mail") ?></td></tr>
				<tr><th>age</th><td><?=$this->Form->text("Form1.age") ?></td></tr>
				<tr><th></th><td><?=$this->Form->submit("送信") ?></td></tr>
			<?=$this->Form->end() ?>
		</table>

Controller

	public function index(){
		$this->viewBuilder()->autoLayout(false);
		$this->set('title', 'Hello!');

		if($this->request->isPost()) {
			$this->set('data', $this->request->data['Form1']);
		} else {
			$this->set('data', []);
		

フォームヘルパーはcontrollerで呼び出さずに利用できる
なるほど

[CakePHP3.10] ビューテンプレート

public $autoRender = false; を外すとviewテンプレートが使える様になる

view templateとlayoutがある
layoutにビューテンプレートをはめ込む

src/Template/Hello/index.ctp

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Hello</title>
	<style>
		h1 {
			font-size: 60pt;
			margin: 0px 0px 10px 0px; padding: 0px 20px; color: white;
			background: linear-gradient(to right, #aaa, #fff);
		}
		p { font-size: 14pt; color: #666; }
	</style>
</head>
<body>
	<header class="row">
		<h1><?=$title ?></h1>
	</header>
	<div class="row">
		<p><?=$message ?></p>
	</div>
</body>
</html>

HelloController.php

class HelloController extends AppController {

	public function index(){
		$this->viewBuilder()->autoLayout(false);
		$this->set('title', 'Hello!');
		$this->set('message', 'This is message!');
	}
}

配列で渡す場合

	public function index(){
		$this->viewBuilder()->autoLayout(false);
		$values = [
			'title' => "hello!",
			"message" => "this is message!!!"
		];
		$this->set($values);
	}

autoLayout(false);で自動レイアウトをoffにしている

OK, controllerとviewの関係性はなんとなく分かったぞ!

CakePHP3系

内蔵サーバー
$ php ./bin/cake.php server -H 0.0.0.0 –port 8080

### View
webroot/hello.html

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Hello</title>
	<style>
		h1 {
			font-size: 60pt;
			margin: 0px 0px 10px 0px; padding: 0px 20px; color: white;
			background: linear-gradient(to right, #aaa, #fff);
		}
		p { font-size: 14pt; color: #666; }
	</style>
</head>
<body>
	<header class="row">
		<h1>Welcome!</h1>
	</header>
	<div class="row">
		<p>This is sample HTML page.</p>
	</div>
</body>
</html>

### Controller
src/Controller/HelloController.php

namespace App\Controller;

use App\Controller\AppController;

class HelloController extends AppController {
	public $autoRender = false;

	public function index(){
		echo "<html><body><h1>Hello!</h1>";
		echo "<p>This is sample page.</p></body></html>";
	}
}

http://192.168.56.10:8080/hello
### クエリパラメータ

	public function index(){
		$id = $this->request->query['id'];
		$pass = $this->request->query['pass'];
		echo "<html><body><h1>Hello!</h1>";
		echo "<ul><li>your id: " . $id . "</li>";
		echo "<li>password: " . $pass . "</li></ul>";
		echo "</body></html>";
	}

http://192.168.56.10:8080/hello?id=taro&pass=yamada

パラメータなしに対応
-> if文で制御する

	public function index(){
		$id = "no name";
		if(isset($this->request->query['id'])){
			$id = $this->request->query['id'];
		}
		$pass = "no password";
		if(isset($this->request->query['pass'])){
			$id = $this->request->query['pass'];
		}

		echo "<html><body><h1>Hello!</h1>";
		echo "<ul><li>your id: " . $id . "</li>";
		echo "<li>password: " . $pass . "</li></ul>";
		echo "</body></html>";
	}

オブジェクトをjsonで返す

namespace App\Controller;

use App\Controller\AppController;

class HelloController extends AppController {
	public $autoRender = false;

	private $data = [
		["name"=>"taro", "mail"=>"taro@yamada", "tel"=>"090-999-999"],
		["name"=>"hanako", "mail"=>"hanako@flower", "tel"=>"080-888-888"],
		["name"=>"sachiko", "mail"=>"sachiko@happy", "tel"=>"070-777-777"]
	];

	public function index(){
		$id = 0;
		if(isset($this->request->query['id'])){
			$id = $this->request->query['id'];
		}
		echo json_encode($this->data[$id]);
	}
}

なるほどー ちょっと理解した

CakePHPでのAWS-SDK-PHP実装の手順

1. composer require aws/aws-sdk-php で、cakephpルートディレクトリでインストール
2. IAM資格情報をenvファイルに追記
3. S3Clinetコンポーネント生成
4. componentの中で、initialize, getList, putFile, getFile, moveFileなどの関数を書く

参考サイト: https://www.ritolab.com/entry/104

なるほど、わかったようなわからんような…

[CakePHP4.x] 3系との違いを考える

$ php composer.phar create-project –prefer-dist cakephp/app:4.* blog
$ bin/cake server -H 192.168.56.10 -p 8000
$ bin/cake migrations migrate

migrations migrate
migrations migrate -t migrationID
migrations rollback
migrations rollback -t migrationID
migrations status

PostsTable.php

    public function validationDefault(Validator $validator): Validator
    {
        $validator
            ->integer('id')
            ->allowEmptyString('id', null, 'create');

        $validator
            ->scalar('title')
            ->maxLength('title', 150, '150文字以上で入力してください。')
            ->minLength('title', 5, '5文字以上で入力してください。')
            ->notEmptyString('title', 'タイトルは必ず入力してください');

        $validator
            ->scalar('description')
            ->maxLength('description', 255, '150文字以上で入力してください。')
            ->allowEmptyString('description');

        $validator
            ->scalar('body')
            ->allowEmptyString('body');

        $validator
            ->boolean('published')
            ->notEmptyString('published');

        return $validator;
    }

OK、続いて、デプロイ周りか…

[CakePHP] 3.xの復習

– データベースの作成から(mysql)
create database cake3
use cake3

create table posts (
id int unsigned auto_increment primary key,
title varchar(255),
body text,
created datetime default null,
modified datetime default null
);
insert into posts (title, body, created) values
(‘title 1’, ‘body 1’, now()),
(‘title 2’, ‘body 2’, now()),
(‘title 3’, ‘body 3’, now());
select * from posts;

– cakephpのインストール
composerでインストールする
$ php composer.phar create-project –prefer-dist cakephp/app:3.* myapp

### ディレクトリ構成の変更
– srcフォルダ新設
– webrootがWebブラウザからアクセスしたときに見るフォルダ

### 2系と3系の違い
1
ディレクトリ構成の変更
app, lib, plugins, vendors
bin, config, plugins, src, tests, tmp, vendor, webroot
-srcの中に、controller, model viewが入る
-webrootにpublicなファイルを配置
2
intl拡張モジュール
不要
必要
php-intlインストール
2
ビルトインサーバー
なし
bin/cake server -H 192.168.56.10 -p 8000

3
データベースの設定
app/Config/database.php
config/app.php

4
タイムゾーンの設定
app/Config/core.php
config/app.php

5
MVCファイルの作成
手動
bin/cake bake all ${app}

6
Modelファイル
app/Model/Post.php
src/Model/Table/PostsTable.php

7
Modelの書き方
class Post extends AppModel{
}
name space App\Model\Table
use Cake\ORM\Table;
class PostsTable extends Table{
}
名前空間を定義
ORM, Validation等を使用
Classの中にinitializeで初期化
8
Viewファイル
app/View/Posts/index.ctp
src/Template/Posts/index.ctp
titleなどはviewの中に記載
elementを追加できる
9
Controllerファイル
app/Controller/PostsController.php
src/Controller/PostsController.php

10
Controllerの書き方

namespace App\Controller;
class PostsController extends AppController { 
}
レコードの作成は$this->Posts->newEntity();と書く
11
Controllerでのfindの書き方
$this->Post->find(‘all’, $params);
$this->Post->find(‘all’)->order([‘title’=>’DESC’]);
繋げて条件を指定できる
12
Routing
app/Config/routes.php
config/routes.php

13
Template
app/View/Layouts/default.ctp
src/Template/Layout/default.ctp
controllerに$this->viewBuilder()->layout(‘my_layout‘);で独自テンプレートを表示できる
14
Validation
modelでarrayで定義
modelでValidationDefaultで定義

うーむ、これ3系と4系の違いもやらんといけんのか…

[CakePHP] 2.xの復習

公式サイト
https://cakephp.org/jp
ドキュメント
https://book.cakephp.org/4/ja/index.html

PHP/MySQL/HTMLCSSJS

– 覚えておいた方が良い用語
MVC -> Model, View, Controller
CoC: Convention over Configuration

CakePHP 2.xをインストールしようと思ったが…
$ git clone -b 2.x git://github.com/cakephp/cakephp.git
Cloning into ‘cakephp’…
fatal: remote error:

composerで入れるか…
$ curl -sS https://getcomposer.org/installer | php
$ php composer.phar create-project –prefer-dist ‘cakephp/app:2.10.*’ myapp
Creating a “cakephp/app:2.10.*” project at “./myapp”

[InvalidArgumentException]
Could not find package cakephp/app with version 2.10.*.

composerでももはや無理なので、githubから無理やり取得します
https://github.com/cakephp/cakephp/tree/2.10.22

ここまででそこそこ時間がかかってしまった…orz
$ cd cakephp-2.10.22

appを使う
controller, model, view

書き込み権限
$ sudo chown -R vagrant app/tmp/

create table posts(
id int not null auto_increment primary key,
title varchar(50),
body text,
created datetime default null,
modified datetime default null
);

insert into posts (title, body, created, modified) values
(‘title 1’, ‘body 1’, now(), now()),
(‘title 2’, ‘body 2’, now(), now()),
(‘title 3’, ‘body 3’, now(), now());

Model/Post.php

class Post extends AppModel {
	
}

Controller/PostsController.php

class PostsController extends AppController {

	public $helpers = array('Html', 'Form');

	public function index(){
		$params = array (
			'order' => 'modified desc',
			'limit' => 2
		);
		$this->set('posts', $this->Post->find('all', $params));
		$this->set('title', '記事一覧');
	}
}

/View/posts/index.ctp

<h2></h2>

<ul>
<?php foreach ($posts as $post) : ?>
<li>
<?php
// debug($post);
echo h($post['Post']['title']);
?>
</li>
<?php endforeach; ?>
</ul>

config/core.php

	Configure::write('debug', 0);

config/routes.php

	Router::connect('/', array('controller' => 'posts', 'action' => 'index'));

View/Layouts/default.ctp
-> templateが書かれている

URL -> /${controller}/${method}/

postscontroller.php

	public function view($id = null){
		$this->Post->id = $id;
		$this->set('post', $this->Post->read());
	}

/View/posts/view.ctp

<h2><?php echo h($post['Post']['title']); ?></h2>

<p><?php echo h($post['Post']['body']); ?></p>

index.ctp

echo $this->Html->link($post['Post']['title'], '/posts/view/'.$post['Post']['id']);

<h2>Add Post</h2>
<?php echo $this->Html->link('Add post', array('controller'=>'posts', 'action'=>'add')); ?>

add.ctp

<h2>Add post</h2>

<?php
echo $this->Form->create('Post');

echo $this->Form->input('title');
echo $this->Form->input('body', array('rows'=>3));
echo $this->Form->end('Save Post');
?>

エラーチェックはmodelにvalidationを書いていく
Mode/Post.php

class Post extends AppModel {
	public $validate = array(
		'title' => array(
			'rule' => 'notEmpty',
		),
		'body' => array(
			'rule' => 'notEmpty',
		)
	);
}

Posts/edit.ctp

<h2>Edit Post</h2>

<?php
echo $this->Form->create('Post'. array('action'=>'edit'));

echo $this->Form->input('title');
echo $this->Form->input('body', array('rows'=>3));
echo $this->Form->end('Save!');

2系はかなり古いか…
Cake自体があまり人気ないかも…

CakePHPのControllerやRouteの書き方

/src/Model/Table/PostsTable.php

namespace App\Model\Table;

use Cake\ORM\Table;

class PostsTable extends Table
{
	public function initialize(array $config) : void {
		$this->addBehavior('Timestamp');
	}
}

/templates/Posts/index.php
L 拡張子はctpではなくphpにする
https://book.cakephp.org/4/ja/views.html

<h1>Blog Posts</h1>

<ul>
	<?php foreach($posts as $post) : ?>
		<li><?= h($post->title); ?></li>
	<?php endforeach;?>
</ul>

/src/Controller/PostsController.php

// /posts/index
// /(controller)/(action)/(options)

namespace App\Controller;

class PostsController extends AppController{

	public function index(){
		$posts = $this->Posts->find('all');
		$this->set('posts', $posts);
	}
}

config/routes.php

    $builder->connect('/', ['controller' => 'Posts', 'action' => 'index']);

controller

$posts = $this->Posts->find('all')->order(['title'=>'DESC'])->limit(2)->where(['title like'=> '%3']);

3系と4系だと、大分書き方が変わってるな。特にctpからphpに変わってるのは驚きだな。

CakePHPの環境構築

$ php -i | grep intl
$ sudo yum -y install php-intl
$ sudo vi /etc/php.d/intl.ini

extension=intl.so

$ php -i | grep intl
PHP Warning: Module ‘intl’ already loaded in Unknown on line 0
/etc/php.d/20-intl.ini,
/etc/php.d/intl.ini
intl
intl.default_locale => no value => no value
intl.error_level => 0 => 0
intl.use_exceptions => 0 => 0

### mysql
create database cakephp;
use cakephp;
create table posts (
id int unsigned auto_increment primary key,
title varchar(255),
body text,
created datetime default null,
modified datetime default null
);

insert into posts (title, body, created) values
(‘title 1’, ‘body 1’, now()),
(‘title 2’, ‘body 2’, now()),
(‘title 3’, ‘body 3’, now());

select * from posts;

### cake install
$ composer create-project –prefer-dist cakephp/app myapp

config/app_local.php

            'username' => 'root',
            'password' => 'hoge',

            'database' => 'cakephp',

config/app.php

        'defaultLocale' => env('APP_DEFAULT_LOCALE', 'ja_JP'),
        'defaultTimezone' => env('APP_DEFAULT_TIMEZONE', 'Asia/Tokyo'),

$ bin/cake bake all posts
$ bin/cake server -H 192.168.33.10 -p 8000
http://192.168.33.10:8000/posts

あああああああああ、ちょっと思い出してきたー

さくら共有サーバー cake3.5インストール後の.htaccessの設定

www/cake/に testというappを作っています。
それぞれのhtaccessのRewriteBaseでカレントディレクトリを指定してあげます。

/cake/.htaccess

  
   RewriteEngine on  
   RewriteRule    ^$ test/webroot/    [L]  
   RewriteRule    (.*) app/webroot/$1 [L]  
   RewriteBase /  
  

/cake/test/.htaccess

  
    RewriteEngine on  
    RewriteRule    ^$    webroot/    [L]  
    RewriteRule    (.*) webroot/$1    [L]  
    RewriteBase /test
  

/cake/test/webroot/.htaccess


    RewriteEngine On
    RewriteBase /test/webroot
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]

きたー

ここまでもってくるの、結構煩雑だな~
VPSの方が簡単にセットアップできるという謎現象ですね。