[vagrant@localhost ~]$ cd cake [vagrant@localhost cake]$ cd myblog [vagrant@localhost myblog]$ bin/cake bake migration_snapshot Initial Welcome to CakePHP v3.3.8 Console --------------------------------------------------------------- App : src Path: /home/vagrant/cake/myblog/src/ PHP : 5.6.27 --------------------------------------------------------------- [vagrant@localhost myblog]$ bin/cake migrations status Welcome to CakePHP v3.3.8 Console Status Migration ID Migration Name ----------------------------------------- up 20161118150335 Initial [vagrant@localhost myblog]$ bin/cake bake migration CreateComments post_id:integer body;string created modified Status Migration ID Migration Name ----------------------------------------- up 20161118150335 Initial down 20161118150459 CreateComments [vagrant@localhost myblog]$ bin/cake migrations migrate Status Migration ID Migration Name ----------------------------------------- up 20161118150335 Initial up 20161118150459 CreateComments
delete post
index.ctp
<?php foreach($posts as $post) : ?> <!-- <li><?= $this->Html->link($post->title, ['controller'=>'Post', 'action'=>'view',$post->id]); ?></li> --> <li><?= $this->Html->link($post->title, ['action'=>'view',$post->id]); ?> <?= $this->Html->link('[Edit]', ['action'=>'edit',$post->id],['class'=>'fs12']); ?> <?= $this->Form->postLink( '[x]', ['action'=>'delete', $post->id], ['confirm'=>'Are you sure?', 'class'=>'fs12'] ); ?> </li> <?php endforeach; ?>
PostsController.ctp
public function delete($id = null) { $this->request->allowMethod(['post', 'delete']); $post = $this->Posts->get($id); if($this->Posts->delete($post)){ $this->Flash->success('Delete Success!'); } else { $this->Flash->error('Delete Error!'); } return $this->redirect(['action'=>'index']); }
update post
PostController.php: editの関数を追記します。requestはpostにpatch, putを追加することが推奨されています。
public function edit($id = null) { $post = $this->Posts->get($id); if ($this->request->is(['post', 'patch', 'put'])) { $post = $this->Posts->patchEntity($post, $this->request->data); if($this->Posts->save($post)){ $this->Flash->success('Edit Success!'); return $this->redirect(['action'=>'index']); } else { $this->Flash->error('Edit Error!'); } } $this->set(compact('post')); }
edit.ctp: addと同じようにviewを作成します。buttonはUpdateになります。
<?php $this->assign('title', 'Edit Post'); ?> <h1> <?= $this->Html->link('Back', ['action'=>'index'], ['class'=>['pull-right', 'fs12']]); ?> Edit Post </h1> <?= $this->Form->create($post); ?> <?= $this->Form->input('title'); ?> <?= $this->Form->input('body', ['row'=>'3']); ?> <?= $this->Form->button('Update'); ?> <?= $this->Form->end(); ?>
Flash helper
my_layout.ctp
<body> <?= $this->element('my_header'); ?> <?= $this->Flash->render();?> <div class="container"> <?= $this->fetch('content') ?> </div> </body>
Posts.Controller.php
public function add() { $post = $this->Posts->newEntity(); if ($this->request->is('post')) { $post = $this->Posts->patchEntity($post, $this->request->data); if($this->Posts->save($post)){ $this->Flash->success('Add Success!'); return $this->redirect(['action'=>'index']); } else { $this->Flash->error('Add Error!'); } } $this->set(compact('post')); } }
veiw ctpの書き方
コントローラーにメソッドを追加
<?php // /posts/index // /posts // /(controller)/(action)/(options) namespace App\Controller; class PostsController extends AppController { public function index() { $posts = $this->Posts->find('all'); // ->order(['title' => 'DESC']) // ->limit(2) // ->where(['title like' => '%3']); $this->set('posts', $posts); } public function view($id = null) { $post = $this->Posts->get($id); $this->set(compact('post')); } }
src->template->view.ctp
<?php $this->assign('title', 'Blog Detail'); ?> <h1> <?= $this->Html->link('Back', ['action'=>'index'], ['class'=>['pull-right', 'fs12']]); ?> <?= h($post->title); ?> </h1> <p><?= nl2br(h($post->body)); ?></p>
Postの追加: NewEntity
<h1> <?= $this->Html->link('Add New', ['action'=>'add'], ['class'=>['pull-right', 'fs12']]); ?> Blog Posts </h1>
public function add() { $post = $this->Posts->newEntity(); $this->set(compact('post')); }
Cakeのformヘルパー: src->template->view.ctp
<?= this->Form->create($post); ?> <?= this->Form->input('title'); ?> <?= this->Form->input('body', ['row'=>'3']); ?> <?= this->Form->button('Add'); ?> <?= this->Form->end(); ?>
データの入力
if ($this->request->is('post')){ $post = $this->Posts->patchEntity($post, $this->request->data); $this->Posts->save($post); return $this->redirect(['action'=>'index']); }
validation:PostsTable.php
<?php namespace App\Model\Table; use Cake\ORM\Table; use Cake\Validation\Validator; class PostsTable extends Table { public function initialize(array $config) { $this->addBehavior('Timestamp'); } public function validationDefault(Validator $validator) { $validator ->notEmpty('title') ->requirePresence('title') ->notEmpty('body') ->requirePresence('body') ->add('body', [ 'length' => [ 'rule' => ['minLength', 10], 'message' => 'body length must be 10+' ] ]); return $validator; } }
PostsController
public function add() { $post = $this->Posts->newEntity(); if ($this->request->is('post')) { $post = $this->Posts->patchEntity($post, $this->request->data); if($this->Posts->save($post)){ return $this->redirect(['action'=>'index']); } else { } } $this->set(compact('post')); } }
Cakeコマンド
MVCを一気に作成するbakeコマンド
[vagrant@localhost myapp]$ bin/cake bake all posts [vagrant@localhost myapp]$ bin/cake server -H 192.168.33.10 -p 8000
データベースの条件抽出
class PostsController extends AppController { public function index() { $posts = $this->Posts->find('all') ->order(['title' => 'DESC']) ->limit(2) ->where(['title like' => '%3']); $this->set('posts', $posts); } }
デフォルトレイアウト
src->Template->Layout->default.ctp
レイアウトのカスタマイズ
<!DOCTYPE html> <html lang="ja"> <head> <?= $this->Html->charset() ?> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title> <?= $cakeDescription ?>: <?= $this->fetch('title') ?> </title> <?= $this->Html->css('styles.css') ?> </head> <body> <div class="container"> <?= $this->fetch('content') ?> </div> </body> </html>
PostsController.phpの編集
class PostsController extends AppController { public function index() { $this->viewBuilder()->layout('my_layout'); $posts = $this->Posts->find('all'); // ->order(['title' => 'DESC']) // ->limit(2) // ->where(['title like' => '%3']); $this->set('posts', $posts); } }
cssファイルはwebroot/cssにあります。
titleはindex.ctpに書くことが推奨されています。
<?php $this->assign('title', 'blog Posts'); ?>
パーツ
src->header->elementに書き込み、layoutに追記
<header>My Blog</header>
<body> <?= $this->element('my_header'); ?> <div class="container"> <?= $this->fetch('content') ?> </div> </body>
PostsController.phpはclass PostsController extends AppControllerと、AppControllerを継承しているので、AppControllerのpublic function initialize()に$this->viewBuilder()->layout(‘my_layout’);を書き込むこともあります。
リンクの張り方
HTMLヘルパー
<li><?= $this->Html->link($post->title, ['action'=>'view',$post->id]); ?></li>
URLヘルパー
<a href="<?= $this->Url->build(['action'=>'view', $post-id>]); ?>"> <?= h(post->title); ?> </a>
Cake.phpのインストール
Cakeは人気のあるphpのwebアプリケーションフレームワークです。centOSへのインストールは、まずcomposerをディレクトリに入れます。
curl -sS https://getcomposer.org/installer | php
次に、composerを使って、cakeをインストールしていきます。
公式サイトを参考にすると、エラーなくいけると思います。
http://book.cakephp.org/3.0/en/installation.html
[vagrant@localhost cake]$ php composer.phar create-project --prefer-dist cakephp/app myapp
myappに移動し、コマンドラインからサーバーを立ち上げます。
[vagrant@localhost myapp]$ bin/cake server -H 192.168.33.10 -p 8000
以下のように表示されれば、OKです。
完了したら、configファイルのapp.phpよりDatasourcesを探し、データベースの接続を設定していきます。東京のtimezoneは’timezone’ => ‘+09:00’,です。
加えて、bootstrap.phpでもタイムゾーンを変更します。
date_default_timezone_set('Asiz/Tokyo');
ログイン機能の実装
下のキャプチャのように、controller, model, viewにファイルを分けて作成しています。サインインデータはMysqlに格納して、ログイン時に呼び出して、判別しています。また、PostとGetでトークンの正誤判定も行っています。
controller.php
<?php namespace MyApp; class Controller { private $_errors; private $_values; public function __construct(){ if(!isset($_SESSION['token'])){ $_SESSION['token'] = bin2hex(openssl_random_pseudo_bytes(16)); } $this->_errors = new \stdClass(); $this->_values = new \stdClass(); } protected function setValues($key, $value){ $this->_values->$key = $value; } public function getValues(){ return $this->_values; } protected function setErrors($key, $error){ $this->_errors->$key = $error; } public function getErrors($key){ return isset($this->_errors->$key) ? $this->_errors->$key : ''; } protected function hasError(){ return !empty(get_object_vars($this->_errors)); } protected function isLoggedIn() { // $_SESSION['me'] return isset($_SESSION['me']) && !empty($_SESSION['me']); } public function me(){ return $this->isLoggedIn() ? $_SESSION['me'] : null; } }
facebook SDK with composer
composerを使ったfacebook sdk
https://developers.facebook.com/docs/php/gettingstarted
[vagrant@localhost facebook]$ curl -sS https://getcomposer.org/installer | php All settings correct for using Composer Downloading 1.2.2... Composer successfully installed to: /home/vagrant/facebook/composer.phar Use it: php composer.phar
続いて、composer.jsonを作成
{ "require" : { "facebook/php-sdk-v4" : "~5.0" } }
その後、php composer.phar installで完了です。
jsonにautoloadを追加
{ "require" : { "facebook/php-sdk-v4" : "~5.0" }, "autoload":{ "psr-4": { "MyApp\\": "lib/" } } }
コマンドライン
[vagrant@localhost facebook]$ php composer.phar dump-autoload
twitter bot
まう、開発環境にcomposerをインストールします。
curl -sS https://getcomposer.org/installer | php
続いてtwitteroauthを入れます。
[vagrant@localhost bot]$ php composer.phar require abraham/twitteroauth
twitteroauthのHPに沿って、PHPを書いていきます。なお、 CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRETはtwitter developersのmy appから取得する必要があります。
https://twitteroauth.com/
<?php require_once(__DIR__ . '/config.php'); // package // -Composer use Abraham\TwitterOAuth\TwitterOAuth; $connection = new TwitterOAuth( CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET); // $content = $connection->get("account/verify_credentials"); $content = $connection->get("statuses/home_timeline", ['count'=>3]); var_dump($content);
crontabで指定した日時につぶやきをセットすることができます。