$ pgrep -a chrony
1951 /usr/sbin/chronyd
$ chronyc sources -v
インストール不要で、デフォルトでchronydが起動しているのね
随机应变 ABCD: Always Be Coding and … : хороший
$ pgrep -a chrony
1951 /usr/sbin/chronyd
$ chronyc sources -v
インストール不要で、デフォルトでchronydが起動しているのね
UsersController.php
use Cake\Auth\DefaultPasswordHasher;
use Cake\Event\Event;
public function initialize(){
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Flash');
$this->loadComponent('Auth', [
'authorize' => ['Controller'],
'authenticate' => [
'Form' => [
'fields' => [
'username' => 'username',
'password' => 'password'
]
]
],
'loginRedirect' => [
'controller' => 'Users',
'action' => 'login'
],
'logoutRedirect' => [
'controller' => 'Users',
'action' => 'login'
],
'logoutRedirect' => [
'controller' => 'Users',
'action' => 'logout',
],
'authError' => 'ログインしてください。',
]);
}
function login(){
if($this->request->isPost()){
$user = $this->Auth->identify();
if(!empty($user)){
$this->Auth->setUser($user);
return $this->redirect($this->Auth->redirectUrl());
}
$this->Flash->error('ユーザ名かパスワードが間違っています。');
}
}
public function logout(){
$this->request->session()->destroy();
return $this->redirect($this->Auth->logout());
}
public function beforeFilter(Event $event){
parent::beforeFilter($event);
$this->Auth->allow(['login', 'index', 'add']);
}
public function isAuthorized($user = null){
if($user['role'] === 'admin'){
return true;
}
if($user['role'] === 'user'){
return false;
}
return false;
}
authorize, authenticate, loginRedirect, logoutRedirect, authError
$this->request->session()->destroy();
### login.ctpを作成
<div class="users form">
<?= $this->Flash->render('auth') ?>
<?= $this->Form->create() ?>
<fieldset>
<legend>アカウント名とパスワードを入力して下さい。</legend>
<?= $this->Form->input('username') ?>
<?= $this->Form->input('password') ?>
<fieldset>
<?= $this->Form->button(__('Login')); ?>
<?= $this->Form->end() ?>
</div>
AuctionBaseController.phpを作成し、継承させる
なるほどー
$ php composer.phar create-project –prefer-dist cakephp/app:3.* auction
bin/cake bake migration CreateUsers username:string[100] password:string[100] role:string[20]
bin/cake bake migration CreateBiditems user_id:integer name:string[100] finished:boolean endtime:datetime created
bin/cake bake migration CreateBidinfo bititem_id:integer user_id:integer price:integer created
bin/cake bake migration CreateBidrequests biditem_id:integer user_id:integer price:integer created
bin/cake bake migration CreateBidmessages bidinfo_id:integer user_id:integer message:text created
bin/cake migrations migrate
bin/cake bake all users
bin/cake bake all biditems
bin/cake bake all bidinfo
bin/cake bake all bidrequests
bin/cake bake all bidmessages
– コントローラのページネーション: 一定数ごとにレコードを取り出す
– ビューテンプレートのリンク
controller
$this->loadComponent('Paginator');
PeopleController.php
public $paginate = [
'limit' => 5,
'sort' => 'id',
'direction' => 'asc',
'contain' => ['Messages'],
];
public function initialize(){
parent::initialize();
$this->loadComponent('Paginator');
}
public function index(){
$data = $this->paginate($this->People);
$this->set('data', $data);
}
template
<p>This is People table records.</p>
<table>
<thead><tr>
<th>id</th><th>name</th><th>mail</th><th>age</th><th>message</th>
</tr></thead>
<?php foreach($data->toArray() as $obj): ?>
<tr>
<td><?=h($obj->id) ?></td>
<td><a href="<?=$this->Url->build(["controller"=>"People", "action"=>"edit"]); ?>?id=<?=$obj->id ?>"><?=h($obj->name) ?></a></td>
<td><?=h($obj->mail) ?></td>
<td><?=h($obj->age) ?></td>
<td><?php foreach($obj->messages as $item): ?>
"<?=h($item->message) ?>"<br>
<?php endforeach; ?></td>
<td><a href="<?=$this->Url->build(["controller"=>"People", "action"=>"delete"]); ?>?id=<?=$obj->id ?>">delete</a></td>
</tr>
<?php endforeach; ?>
</table>
<div class="paginator">
<ul class="pagination">
<?=$this->Paginator->first(' |<< ' . '最初へ') ?>
<?=$this->Paginator->prev(' << ' . '前へ') ?>
<?=$this->Paginator->next('次へ ' . ' >> ') ?>
<?=$this->Paginator->last('最後へ' . ' >>| ') ?>
</ul>
</div>
custom finderを利用することもできる
なるほど、とりあえずOK 次に行こう
$this->Html->doctype(document type)
$this->Html->charset(charset)
$this->Html->css(file name)
$this->Html->style()
$this->Html->script()
$this->Html->scriptStart()
$this->Html->scriptEnd()
$this->Html->link()
$this->Html->image()
$this->Html->script()
$this->Html->tableHeaders()
$this->Html->tableCells()
<table> <?=$this->Html->tableHeaders(["title", "name", "mail"], ["style"=>["background:#006; color:white"]]) ?> <?=$this->Html->tableCells([["this is sample", "taro", "taro@yamada"],["this is sample", "taro", "taro@yamada"],["this is sample", "taro", "taro@yamada"]], ['style'=>['background:#ccf']], ['style'=>['background:#ccf']]) ?> </table>
$this->Html->nestedList()
アクションの指定、クエリパラメータの指定、拡張子の指定などもUrlBuilderで指定できる
### Textヘルパー
<?=$this->Text->autoLinkUrls('http://google.com') ?>
<?=$this->Text->autoLinkEmails('hoge@gmail.com') ?>
<?=$this->Text->autoParagraph('one\ntwo\nthree') ?>
Numberヘルパー
<p>金額は、<?=$this->Number->currency(1234567, 'JPY') ?>です。</p> <p>2桁で表すと、<?=$this->Number->precision(1234.56789, 2) ?>です。</p> <p>2桁で表すと、<?=$this->Number->toPercentage(0.12345, 2, ['multiply'=>true]) ?>です。</p>
OK、大分いいところまで来た気がする
config/bootstrap.php
Plugin::load('Migrations');
$ cake bake migration Create 項目1:タイプ
$ bin/cake bake migration CreateMoview title:string content:text stars:integer created:datetime
$ bin/cake bake migration CreateMovie title:string content:text stars:integer created:datetime
Creating file /home/vagrant/dev/cake/mycakeapp/config/Migrations/20220715040907_CreateMoview.php
Wrote `/home/vagrant/dev/cake/mycakeapp/config/Migrations/20220715040907_CreateMoview.php`
$ bin/cake migrations migrate
/config/Migrations/20220715040907_CreateMoview.php
$ bin/cake bake all movies
http://192.168.56.10:8080/movies
src/Model/Entity/Movie.php
protected $_accessible = [
'title' => true,
'content' => true,
'stars' => true,
'created' => true,
];
src/Model/Table/MoviesTable.php
public function validationDefault(Validator $validator)
{
$validator
->integer('id')
->allowEmptyString('id', null, 'create');
$validator
->scalar('title')
->maxLength('title', 255)
->requirePresence('title', 'create')
->notEmptyString('title');
$validator
->scalar('content')
->requirePresence('content', 'create')
->notEmptyString('content');
$validator
->integer('stars')
->requirePresence('stars', 'create')
->notEmptyString('stars');
return $validator;
}
src/Controller/MoviesController.php
public function index()
{
$movies = $this->paginate($this->Movies);
$this->set(compact('movies'));
}
/**
* View method
*
* @param string|null $id Movie id.
* @return \Cake\Http\Response|null
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function view($id = null)
{
$movie = $this->Movies->get($id, [
'contain' => [],
]);
$this->set('movie', $movie);
}
/**
* Add method
*
* @return \Cake\Http\Response|null Redirects on successful add, renders view otherwise.
*/
public function add()
{
$movie = $this->Movies->newEntity();
if ($this->request->is('post')) {
$movie = $this->Movies->patchEntity($movie, $this->request->getData());
if ($this->Movies->save($movie)) {
$this->Flash->success(__('The movie has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The movie could not be saved. Please, try again.'));
}
$this->set(compact('movie'));
}
/**
* Edit method
*
* @param string|null $id Movie id.
* @return \Cake\Http\Response|null Redirects on successful edit, renders view otherwise.
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function edit($id = null)
{
$movie = $this->Movies->get($id, [
'contain' => [],
]);
if ($this->request->is(['patch', 'post', 'put'])) {
$movie = $this->Movies->patchEntity($movie, $this->request->getData());
if ($this->Movies->save($movie)) {
$this->Flash->success(__('The movie has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The movie could not be saved. Please, try again.'));
}
$this->set(compact('movie'));
}
/**
* Delete method
*
* @param string|null $id Movie id.
* @return \Cake\Http\Response|null Redirects to index.
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function delete($id = null)
{
$this->request->allowMethod(['post', 'delete']);
$movie = $this->Movies->get($id);
if ($this->Movies->delete($movie)) {
$this->Flash->success(__('The movie has been deleted.'));
} else {
$this->Flash->error(__('The movie could not be deleted. Please, try again.'));
}
return $this->redirect(['action' => 'index']);
}
<p>This is People table records.</p>
<?=$this->Form->create($entity,
['type'=>'post',
'url'=>['controller'=>'Messages',
'action'=>'index']]) ?>
<fieldset class="form">
person id
<?= $this->Form->error('Messages.person_id'); ?>
<?= $this->Form->text('Messages.person_id'); ?>
Message
<?= $this->Form->error('Messages.message'); ?>
<?= $this->Form->text('Messages.message'); ?>
<?= $this->Form->submit('投稿') ?>
</fieldset>
<?=$this->Form->end() ?>
<hr>
<table>
<thead>
<tr><th>ID</th><th>Message</th><th>name</th><th>created at</th>
</tr>
</thead>
<?php foreach($data->toArray() as $obj): ?>
<tr>
<td><?=h($obj->id) ?></td>
<td><?=h($obj->message) ?></td>
<td><?=h($obj->person->name) ?></td>
<td><?=h($obj->created_at) ?></td>
</tr>
<?php endforeach; ?>
</table>
<p>This is People table records.</p>
<?=$this->Form->create(null, ["type"=>"post", "url"=>["controller"=>"People", "action"=>"index"]]) ?>
<div>find</div>
<div><?=$this->Form->text("People.find") ?></div>
<div><?=$this->Form->submit("検索") ?></div>
<?=$this->Form->end() ?>
<table>
<thead><tr>
<th>id</th><th>name</th><th>messages</th>
</tr></thead>
<?php foreach($data->toArray() as $obj): ?>
<tr>
<td><?=h($obj->id) ?></td>
<td><a href="<?=$this->Url->build(["controller"=>"People", "action"=>"edit"]); ?>?id=<?=$obj->id ?>"><?=h($obj->name) ?></a></td>
<td><?php foreach($obj->messages as $item): ?>
"<?=h($item->message) ?>"<br>
<?php endforeach; ?></td>
<td><?=h($obj->age) ?></td>
<td><a href="<?=$this->Url->build(["controller"=>"People", "action"=>"delete"]); ?>?id=<?=$obj->id ?>">delete</a></td>
</tr>
<?php endforeach; ?>
</table>
$ sudo apt update
$ sudo apt install redis-server
$ sudo vi /etc/redis/redis.conf
supervised systemd
$ sudo systemctl restart redis.service
$ sudo systemctl status redis
● redis-server.service – Advanced key-value store
Loaded: loaded (/lib/systemd/system/redis-server.service; enabled; vendor >
Active: active (running) since Thu 2022-07-14 09:02:47 UTC; 11s ago
Docs: http://redis.io/documentation,
man:redis-server(1)
Process: 273821 ExecStart=/usr/bin/redis-server /etc/redis/redis.conf (code>
Main PID: 273833 (redis-server)
Tasks: 4 (limit: 4677)
Memory: 2.0M
CGroup: /system.slice/redis-server.service
└─273833 /usr/bin/redis-server 127.0.0.1:6379
$ sudo apt install php-redis
$ redis-cli
127.0.0.1:6379> ping
set
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->set('key', 'PHP');
$redis->close();
get
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$value = $redis->get('key');
print($value);
$redis->close();
ほうほう、php-redisも何となく理解した
### Cookieで持つ場合
■メリット
サーバにデータをため込まないので、サーバサイドの負荷を気にしないで良い
アプリケーションサーバを分散させても一貫性を持たせられる
■デメリット
ユーザ側にデータがあるため、改ざんリスクが高まる(Railsは暗号化によって対策してますが)
Cookieの仕様上、4KBの容量制限がある
Cookieを乗っ取られた場合等でもサーバサイドからセッションを破棄する手段がない
ユーザがcookieを有効にしていない場合、ログイン情報などがうまく保存されない
### サーバ側でファイルで持つ場合
CakePHP、Laravelのでファオルトで、CookieにセッションIDだけ持たせて、サーバサイドに実データをファイルとして置く方法
■メリット
サーバサイドにデータがあるので改ざんを回避できる
データ容量制限がない
サーバサイドでセッションの破棄ができる
■デメリット
アプリケーションサーバを分散させた場合、一貫性が確保できない
1セッションにつき1ファイル生成されるので、大量にセッションファイルが出来てファイルシステムに負担が掛かる
### KVS(NoSQL)
CookieにセッションIDだけ持たせて、Memcached、RedisなどサーバサイドのKVSに実データを置く方法。
■メリット
– サーバサイドにデータがあるので改ざんを回避できる
– データ容量制限がない
– サーバサイドでセッションの破棄ができる
– アプリケーションサーバを分散させても一貫性を持たせられる
– 大量の同時I/Oに強く、アクセスが増大しても大丈夫!
■デメリット
セッション専用にひとつデータベースが追加されるのでコストが増
https://qiita.com/SuguruOoki/items/6ca36ad1d366df6c98af
コストに問題なければredis(NoSQL)が良さそうではある
create database test;
use test;
create table TBL_SESSION (
SESSION_ID varchar(50) NOT NULL,
SESSION_DATA text,
CRA¥EATE_DATE int(10),
PRIMARY KEY (SESSION_ID));
class MySessionHandler implements SessionHandlerInterface {
function close(){
return true;
}
function destroy($session_id) {
$db = get_db();
if($stmt = $db->prepare("DELETE FROM TBL_SESSION WHERE SESSION_ID = ?")){
$stmt->bind_param("s", $session_id);
$stmt->execute();
$stmt->close();
$stmt = null;
}
$db->close();
$db = null;
return true;
}
function open($save_path, $name) {
return true;
}
function read($session_id) {
$session_data = "";
$db = get_db();
if($stmt = $db->prepare("SELECT SESSION_DATA FROM TBL_SESSION WHERE SESSION_ID = ?")){
$stmt->bind_param("s", $session_id);
$stmt->bind_result($session_data);
$stmt->execute();
$stmt->fetch();
$stmt->close();
$stmt = null;
}
$db->close();
$db = null;
if(is_null($session_data)){
$session_data = "";
}
return $session_data;
}
function write($session_id, $sesion_data){
$affect_rows = 0;
$create_date = time();
$db = get_db();
if($stmt = $db->prepare("INSERT INTO TBL_SESSION (SESSION_ID, SESSION_DATA, CREATE_DATE) VALUES(?, ?, ?) ON DUPLICATE KEY UPDATE SESSION_DATA = ?, CREATE_DATE = ?")){
$stmt->bind_param("ssisi", $session_id, $session_data, $create_date, $session_data, $create_date);
$stmt->execute();
$affected_rows = $stmt->affected_rows;
$stmt->close();
$stmt = null;
}
$db->close();
$db = null;
return $affected_rows ? true : false;
}
}
function get_db(){
return new mysqli('localhost:3306', 'user', 'password', 'db_name');
}
session_set_save_handler(new MySessionHandler(), true);
session_start();
$_SESSION['data'] = 0;
Railsは全てのセッション情報をcookieに保存