MPEGは「音声、映像関連の規格」
MP3は「音声データを扱うときの規格のひとつ」
MIMEタイプは「ファイルの種類を表す情報」
mp3ファイルはaudioタグで囲う
<h1>MP3の再生</h1> <audio src="test.mp3" controls></audio>
随机应变 ABCD: Always Be Coding and … : хороший
MPEGは「音声、映像関連の規格」
MP3は「音声データを扱うときの規格のひとつ」
MIMEタイプは「ファイルの種類を表す情報」
mp3ファイルはaudioタグで囲う
<h1>MP3の再生</h1> <audio src="test.mp3" controls></audio>
10個リクエストを送ります。
重複してレスポンスが返ってくるので、array_uniqueで重複を削除します。
<?php require 'vendor/autoload.php'; $session = new SpotifyWebAPI\Session( 'id', 'secret', 'http://192.168.33.10:8000/callback/' ); $api = new SpotifyWebAPI\SpotifyWebAPI(); $count = 10; if (isset($_GET['code'])) { $session->requestAccessToken($_GET['code']); $api->setAccessToken($session->getAccessToken()); $tracks = $api->search('浜崎あゆみ', 'track', array( 'limit' => $count )); // print_r('<pre>'); // var_dump($tracks); // print_r('</pre>'); for($i=0; $i<$count; $i++){ $track_id[] = $tracks->tracks->items[$i]->album->id; } // print_r($track_id); } else { $options = [ 'scope' => [ 'user-read-email', ], ]; header('Location: ' . $session->getAuthorizeUrl($options)); die(); } $track_id = array_unique($track_id); foreach($track_id as $value){ echo "<iframe src=\"https://embed.spotify.com/?uri=spotify:album:".$value."\" width=\"300\" height=\"380\" frameborder=\"0\" allowtransparency=\"true\"></iframe>"; } ?>
あ、これは結構いい。昔の曲が聞ける。
LUNA SEA行ってみよう。 mothersはかっこよかった。
一曲全部じゃないのが惜しいが。
spotify api
$api->searchでtrackが返ってきます。
<?php require 'vendor/autoload.php'; $session = new SpotifyWebAPI\Session( 'id', 'secret', 'http://192.168.33.10:8000/callback/' ); $api = new SpotifyWebAPI\SpotifyWebAPI(); if (isset($_GET['code'])) { $session->requestAccessToken($_GET['code']); $api->setAccessToken($session->getAccessToken()); $tracks = $api->search('浜崎あゆみ', 'track', array( 'limit' => 1 )); $track_id = $tracks->tracks->items[0]->album->id; print_r($track_id); } else { $options = [ 'scope' => [ 'user-read-email', ], ]; header('Location: ' . $session->getAuthorizeUrl($options)); die(); } // print_r('<pre>'); // var_dump($tracks); // print_r('</pre>'); ?> <h1>spotify</h1> <iframe src="https://embed.spotify.com/?uri=spotify:album:<?php echo $track_id; ?>" width="300" height="380" frameborder="0" allowtransparency="true"></iframe>
まあまあいいんだけど、全部サビ前からサビの30秒位なんだよな。
1曲全部聞けないと、物足りない感が尋常ではない。
あ、iframeこんな感じです。うーん、違うな。やっぱりイントロから聞けないと絶対ダメでしょ。
index.php
$session = new SpotifyWebAPI\Session( 'client id', 'client secret', 'http://192.168.33.10:8000/callback' );
spotify
invalid URIのレスポンスが返ってくるため、stackoverflowを見ていたら、
stackoverflow
https://stackoverflow.com/questions/32956443/invalid-redirect-uri-on-spotify-auth
app.js:
var redirect_uri = ‘http://localhost:8888/callback’;
Spotify > My application:
http://localhost:8888/callback/
それでもエラーで
なんでだろうと思っていたら、
myappとlocalで、callback urlは完全一致(バックスラッシュ)にしないといけないようです。
http://192.168.33.10:8000/callback/
http://192.168.33.10:8000/callback/
泣きたくなってきた。
まず、一つ目のテーブルを作くってデータを入れます。
create table cake.base( id int unsigned auto_increment primary key, code int, name varchar(255) ); insert into base(code, name) values ('3689', 'イグニス'), ('4579', 'ラクオリア創薬'), ('3825', 'リミックスポイント');
二つ目のテーブルを作って、こちらにもデータを挿入。
create table cake.data( id int unsigned auto_increment primary key, code int, price int, time datetime default null ); insert into cake.data(code, price, time) values ('3689', '3240', now()), ('3689', '3245', now()), ('3689', '3250', now()), ('3689', '3245', now());
INNER JOINでカラムを指定して結合する
SELECT base.code, base.name, data.price, data.time FROM base INNER JOIN data ON base.code = data.code;
OUTER JOIN
SELECT base.code, base.name, data.price, data.time FROM base LEFT OUTER JOIN data ON base.code = data.code;
dataが入っていないラクオリア創薬、リミックスポイントもselectされます。
更にテーブルを連結する場合も、joinでok
create table cake.market(
id int unsigned auto_increment primary key,
code int,
market varchar(255)
);
insert into market(code, market) values
(‘3689’, ‘マザーズ’),
(‘4579’, ‘ジャスダック’),
(‘3825’, ‘東証二部’);
SELECT base.code, base.name, data.price, data.time, market.market FROM base JOIN market ON base.code = market.code JOIN data ON base.code = data.code;
// making migration [vagrant@localhost myblog]$ bin/cake bake migration_snapshot Initial [vagrant@localhost myblog]$ bin/cake migrations status using migration paths - /home/vagrant/fw/myblog/config/Migrations using seed paths - /home/vagrant/fw/myblog/config/Seeds using environment default Status Migration ID Migration Name ----------------------------------------- up 20180306042845 Initial [vagrant@localhost myblog]$ bin/cake bake migration CreateComments post_id:integer body:string created modified Creating file /home/vagrant/fw/myblog/config/Migrations/20180306043056_CreateComments.php Wrote `/home/vagrant/fw/myblog/config/Migrations/20180306043056_CreateComments.php [vagrant@localhost myblog]$ bin/cake migrations migrate `
mysqlで確認
mysql> use cake Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> show tables; +----------------+ | Tables_in_cake | +----------------+ | comments | | phinxlog | | posts | +----------------+ 3 rows in set (0.00 sec)
すげー
commentController
<?php namespace App\Controller; class CommentsController extends AppController { public function add() { $this->viewBuilder()->layout('my_layout'); $comment = $this->Comments->newEntity(); if($this->request->is('post')){ $comment = $this->Comments->patchEntity($comment, $this->request->data); if($this->Comments->save($comment)){ $this->Flash->success('Comment Add Success!'); return $this->redirect(['controller'=>'Posts','action'=>'view', $comment->post_id]); }else { $this->Flash->success('Error'); } } $this->set('post', $comment); } public function delete($id = null) { $this->viewBuilder()->layout('my_layout'); $this->request->allowMethod(['post', 'delete']); $comment = $this->Comments->get($id); if($this->Comments->delete($comment)){ $this->Flash->success('Comment Delete Success!'); }else { $this->Flash->success('Error'); } return $this->redirect(['controller'=>'Posts','action'=>'view', $comment->post_id]); } } ?>
controllerでgetして、$this->Posts->save
public function edit($id = null) { $this->viewBuilder()->layout('my_layout'); $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->success('Error'); } } $this->set('post', $post); }
deleteは $this->Posts->deleteになる
public function edit($id = null) { $this->viewBuilder()->layout('my_layout'); $this->request->allowMethod(['post', 'delete']); $post = $this->Posts->get($id); if($this->Posts->delete($post)){ $this->Flash->success('Delete Success!'); }else { $this->Flash->success('Error'); } return $this->redirect(['action'=>'index']); }
<?= $this->Form->create($post); ?> <?= $this->Form->input('title'); ?> <?= $this->Form->input('body', ['rows'=> '3']); ?> <?= $this->Form->button('Add'); ?> <?= $this->Form->end(); ?>
なるほど、だんだんテンションが下がってきた。
DBへのinsertをcontrollerで書きます。
public function add() { $this->viewBuilder()->layout('my_layout'); $post = $this->Posts->newEntity(); if($this->request->is('post')){ $post = $this->Posts->patchEntity($post, $this->request->data); $this->Posts->save($post); return $this->redirect(['action'=>'index']); } $this->set('post', $post); }
validatorはmodelに書きます。
<?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; } }
controllerでvalidationの設定
public function add() { $this->viewBuilder()->layout('my_layout'); $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 { // error } } $this->set('post', $post); }
index.ctp
Htmlヘルパーを使う場合
Html->linkとする テーブルのカラムを指定し、コントローラーとアクションを作成。
うーん、慣れるまで時間がかかりそう。
<?php foreach($posts as $post):?> <li><?= $this->Html->link($post->title, ['controller'=>'Posts', 'action'=>'view']); ?></li> <?php endforeach; ?>
ブラウザで確認。反映されてますね。
urlヘルパーを使う場合
<a href="<?= $this->Url->build(['action'=>'view', $post->id]); ?>"> <?= h($post->title); ?></a>
Htmlヘルパーの方がコード量が少なく楽そうに見えます。
共通ヘッダーをつくります。
app/src/Template/Element/my_header.ctp
<header>My Blog</header>
作ったelementをレイアウトファイルに書き込みます。
app/src/Template/Layout/my_layout.ctp
<!DOCTYPE html> <html> <head> <?= $this->Html->charset() ?> <title> <?= $this->fetch('title') ?> </title> <?= $this->Html->css('styles.css') ?> </head> <body> <?= $this->element('my_header') ?> <section class="container"> <?= $this->fetch('content') ?> </section> </body> </html>
サーバーを再起動します。
bin/cake server -H 192.168.33.10 -p 8000
ブラウザ読み込みます。なるほど、エレメントはパーツですね。
PostController.phpはAppControllerのclassをextendしているので、AppControllerのクラスに記載してもOK
$this->viewBuilder()->layout(‘my_layout’);