20220114のPHPに関する記事は8件です。

baserCMSのページネーション(ページャー)のカスタマイズ

baserCMS公式の、ページネーションのドキュメントが少ないので、私が把握していることをまとめます。 基本的な使い方 baserCMSでは「ブログ」のアーカイブページでページネーションが使用できます。 pagination関数が提供されています。 <?php $this->BcBaser->pagination(); ?> 引数と出力内容 pagination関数には「出力するHTML」を変更する第1引数$nameがあり、テーマ側で何もしていなければ(後述)、受け付ける引数は3種類です。 CSSのみでカスタマイズするのであれば、ordered_listで良いかと思います。 default(または引数なし) <?php $this->BcBaser->pagination('default'); ?> <div class="pagination"> <div class="pagination-result">結果: 00~00 件 / 総件数: 99 件</div> <div class="pagination-numbers"> <span><a href="/pathToBlog/index/page:1" rel="first">|&lt;</a></span>  <span class="prev"><a href="/pathToBlog/index/page:2" rel="prev">&lt;&lt;</a></span>  <span><a href="/pathToBlog/index/page:1">1</a></span> | <span><a href="/pathToBlog/index/page:2">2</a></span> | <span class="current">3</span> | <span><a href="/pathToBlog/index/page:4">4</a></span> | <span><a href="/pathToBlog/index/page:5">5</a></span> | <span><a href="/pathToBlog/index/page:6">6</a></span> | <span><a href="/pathToBlog/index/page:7">7</a></span> | <span><a href="/pathToBlog/index/page:8">8</a></span> | <span><a href="/pathToBlog/index/page:9">9</a></span>  <span class="next"><a href="/pathToBlog/index/page:4" rel="next">&gt;&gt;</a></span>  <span><a href="/pathToBlog/index/page:10" rel="last">&gt;|</a></span> </div> </div> simple <?php $this->BcBaser->pagination('simple'); ?> <div class="pagination"> <span class="prev"><a href="/pathToBlog/index/page:2" rel="prev">&lt; 前へ</a></span> <span> <span class="number"><a href="/pathToBlog/index/page:1">1</a></span> <span class="number"><a href="/pathToBlog/index/page:2">2</a></span> <span class="current number">3</span> <span class="number"><a href="/pathToBlog/index/page:4">4</a></span> <span class="number"><a href="/pathToBlog/index/page:5">5</a></span> <span class="number"><a href="/pathToBlog/index/page:6">6</a></span> <span class="number"><a href="/pathToBlog/index/page:7">7</a></span> <span class="number"><a href="/pathToBlog/index/page:8">8</a></span> <span class="number"><a href="/pathToBlog/index/page:9">9</a></span> </span> <span class="next"><a href="/pathToBlog/index/page:4" rel="next">次へ &gt;</a></span> </div> ordered_list <?php $this->BcBaser->pagination('ordered_list'); ?> <nav class="c-pagination" aria-label=""> <div class="c-pagination__prev"> <a href="/pathToBlog/index/page:2" class="prev" rel="prev">prev</a> </div> <div class="c-pagination__next"> <a href="/pathToBlog/index/page:4" class="next" rel="next">next</a> </div> <ol class="c-pagination__numbers"> <li class="c-pagination__number"><a href="/pathToBlog/index/page:1">1</a></li> <li class="c-pagination__number"><a href="/pathToBlog/index/page:2">2</a></li> <li class="current c-pagination__number"><a aria-current="page">3</a></li> <li class="c-pagination__number"><a href="/pathToBlog/index/page:4">4</a></li> <li class="c-pagination__number"><a href="/pathToBlog/index/page:5">5</a></li> <li class="c-pagination__number"><a href="/pathToBlog/index/page:6">6</a></li> <li class="c-pagination__number"><a href="/pathToBlog/index/page:7">7</a></li> <li class="c-pagination__number"><a href="/pathToBlog/index/page:8">8</a></li> <li class="c-pagination__number"><a href="/pathToBlog/index/page:9">9</a></li> </ol> </nav> ページネーションのテンプレートの場所 それぞれのページネーションの処理は、baserCMSのコアパッケージ内の、以下のパスにあるテンプレートを参照しています。 /lib/Baser/View/Elements/paginations/default.php /lib/Baser/View/Elements/paginations/ordered_list.php /lib/Baser/View/Elements/paginations/simple.php baserCMSはコアテンプレートを、管理画面からブラウザで見ることもできます。 /admin/theme_files/view/core/Elements/paginations/default.php /admin/theme_files/view/core/Elements/paginations/ordered_list.php /admin/theme_files/view/core/Elements/paginations/simple.php HTMLを細かくカスタマイズする コーディングされた静的HTMLをテーマ化したい場合は、以下の通り作業します。 独自の引数を渡す pagination関数の引数を、上記とは違う値にします。ここではpagerにしました。 <?php $this->BcBaser->pagination('pager'); ?> コアテンプレートを複製 前項のどれかのテンプレートをコピーし、自作のテーマ(ここではmyBaserTheme)の以下のパスに設置します。 /theme/myBaserTheme/Elements/paginations/pager.php 引数をなしにして、テンプレートを以下のパスに設置しても同じ結果となります。この場合はbaserCMSのdefaultテンプレートを上書きします。 /theme/myBaserTheme/Elements/paginations/default.php テンプレートをカスタマイズ テンプレートのHTMLを修正します。細かいページネーションの定義はPaginatorクラスを使用します。 PaginatorはCakePHPを継承しています。よほどがっつりしたカスタマイズでない限り不要と思いますが、細かい引数や処理を知りたい場合は、baserCMSのコアパッケージの以下のパスから参照できます。 /lib/Cake/View/Helper/PaginatorHelper.php TIPS よくありそうな細かいカスタマイズを書いておきます。 現在ページのマークアップをa要素にする baserCMS = CakePHPではページネーションの現在ページはspanでマークアップされますが、最近のCSSフレームワークはクラス付きのa要素であることが多いです。 a要素にする場合は、Paginatorのnumbersクラスメソッド(関数)の、tagオプションを空にしてspanを削除しつつ、currentTagオプションを指定します。以下のように書いておけばまず大丈夫です。 <?php echo $this->Paginator->numbers([ 'tag' => false, 'separator' => '', 'currentTag' => 'a href="' . $this->BcBaser->getHere() . '" class="is-current"', 'modulus' => $modules, ]); ?> 前後リンクがない場合に何も表示しない Paginatorの、hasPrev・hasNextクラスメソッドで判定できます。 <?php if( $this->Paginator->hasPrev() ) : ?> <?php echo $this->Paginator->prev('< 前のページ', ['class' => 'prev']) ?> <?php endif; ?> 前後リンクにアイコンフォントを使う デフォルトでは、prev・nextクラスメソッドはラベルがエスケープされてしまうので、以下のように引数escapeを渡します。 <?php echo $this->Paginator->next( '次のページ<i class="fas fa-chevron-right"></i>', [ 'class' => 'next', 'escape' => false, ] ); ?> 変数の値を渡す ページネーションに現在のブログIDなどの変数の値を渡す場合は、以下のように第2引数を配列で指定します。この場合は変数hogeの値としてhugaが渡ります。 <?php $this->BcBaser->pagination( 'default', [ 'hoge' => 'huga' ] ); ?> 以上です。 baserCMSはCakePHPをベースに開発されているためか、公式のドキュメントが少ないです。もうちょっと充実させてほしいですが、よくわからないときはとりあえずCakeのコアやCookBook、有志のチートシートを読むと解決できるかもしれません。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MarinDBのdelimiter

delimiterについて この記事は主の備忘録用の物です。 投稿初期のものなので、諸々許してください。 目的 MariaDBで、;を実行コマンドとして機能させないように、delimiterをつかおうと思ったのですが、すこし手こずりましたので、その解決方法の共有です。 エラーの内容 ''' MariaDB [test_db]> delimiter// -> ; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'delimiter//' at line 1 ''' 解決方法 解決方法はいたってSimpleでした。 delimiterを大文字で使う たったこれだけです。 以上でした。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【備忘録】Instagram Graph APIを使用してWEBページに正方形の画像を埋め込む

Instagram Graph APIを使用してInstagramの画像をwebページに埋め込む際に、少し手間取ったので備忘録として。 実現したいこと Instagram Graph APIを利用してInstagramから取得した画像をwebページに埋め込み、正方形のグリッド状に配置したい。 実装 Instagramのプロアカウント作成からwebページへの埋め込みまではこちらを参考に行った。 実装後に起きた問題 画像が表示されない。 画像をクリックしても投稿に飛ばない。 取得された画像サイズが正方形ではないのでレイアウトが崩れる。 原因 画像が表示されない。 phpファイル内のGraph APIのバージョンが最新ではなかった。 目的のInstagramアカウントの投稿数が、Graph APIで取得する数(javascriptファイルのphoto_lengthの値)より少なかった。 javascriptファイル内のphpファイル指定がうまく動作しなかった。 画像をクリックしても投稿に飛ばない。 投稿へのリンクの値であるpermalinkを取得していなかった。 取得された画像サイズが正方形ではないのでレイアウトが崩れる。 対策を後述。 修正点 画像が表示されない。 phpファイルの$instagram_api_url内のGraph APIのバージョンを最新のものに書き換える。 「取得する画像の数 ≦ 目的のアカウントの投稿の数」にする。 javascriptファイル内のphpファイル指定を相対パスから絶対パスに変更。 画像をクリックしても投稿に飛ばない。 phpファイルの$query内の、media{値(省略)}の値の部分にpermalinkを追加。 javascriptファイルのphotos +=内の、<li>と<img>の間に「<a href="' + gallery_data[i].permalink + '" target="_blank">」を追加(閉じタグも忘れずに) 取得された画像サイズが正方形ではないのでレイアウトが崩れる。 こちらのサイトを参考に<li>タグを正方形にして、中に入れる画像をobject-fit: cover;で拡大表示。 まとめ 以上で、webサイト内にInstagramの画像をレスポンシブな正方形で配置することができた。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Wordpressのmeta_queryを使って、指定値がmeta_valueに保存された配列に含まれるものを抽出したい

WP_Queryのmeta_queryでin_array()的なことをしたくて探してたら Stack Exchangeで見つけたので紹介します。 単純に以下のように書く場合 $args = [ 'meta_query' => [ [ 'key' => 'hoge', 'value' => $id, 'compare' => 'IN' ] ] ]; $query = new WP_Query($args); 「DBに保存されている値が配列$idに含まれる場合」 という意図と逆の意味合いになってしまいます。 「$idがDBに保存されている配列に含まれる場合」という場合、 シリアライズ保存されたデータからLIKEを使って文字列で抽出するしかないそうです。 ただ$idが数字の場合、単に文字列化しても誤抽出が起こりやすいので、 こちらもシリアライズして前後の記号も含めLIKE抽出します。 $args = [ 'meta_query' => [ [ 'key' => 'hoge', 'value' => serialize(strval($id)), 'compare' => 'LIKE' ] ] ]; $query = new WP_Query($args); 参考: https://wordpress.stackexchange.com/questions/55354/how-can-i-create-a-meta-query-with-an-array-as-meta-field/308393#308393
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

1つのカスタム投稿に複数のタクソノミーを設定する

●スラッグ 「レッスン」 → lesson 「ギター」 → lesson_guitar 「ベース」 → lesson_bass 「ドラム」 → lesson_drum functions.php //カスタム投稿タイプ追加 register_post_type( 'lesson', //カスタム投稿のスラッグ array( 'label' => 'レッスン検索', //管理画面に表示される名前 'hierarchical' => true, 'has_archive' => true, 'public' => true, 'menu_position' => 5, 'supports' => array('title','editor'), 'exclude_from_search' => false, )); //カスタムタクソノミー追加 add_action( 'init', 'add_custom_taxonomy_event', 0 ); function add_custom_taxonomy_event() { register_taxonomy( 'lesson_guitar', //カスタムタクソノミーのスラッグ 'lesson', //上のカスタム投稿タイプ追加で指定したスラッグ array( 'hierarchical' => true, 'update_count_callback' => '_update_post_term_count', 'label' => 'ギター', //管理画面に表示される名前 'public' => true, 'show_ui' => true, )); } add_action( 'init', 'add_custom_taxonomy_event02', 0 ); function add_custom_taxonomy_event02() { register_taxonomy( 'lesson_bass', //カスタムタクソノミーのスラッグ 'lesson', //上のカスタム投稿タイプ追加で指定したスラッグ array( 'hierarchical' => true, 'update_count_callback' => '_update_post_term_count', 'label' => 'ベース', //管理画面に表示される名前 'public' => true, 'show_ui' => true, )); } add_action( 'init', 'add_custom_taxonomy_event03', 0 ); function add_custom_taxonomy_event03() { register_taxonomy( 'lesson_drum', //カスタムタクソノミーのスラッグ 'lesson', //上のカスタム投稿タイプ追加で指定したスラッグ array( 'hierarchical' => true, 'update_count_callback' => '_update_post_term_count', 'label' => 'ドラム', //管理画面に表示される名前 'public' => true, 'show_ui' => true, )); } ●管理画面の表示 何やらスマートな書き方じゃない気がしますが… とりあえず機能はしてます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHP(とちょっとLaravel)の細々とした覚書

foreachで値を直接いじくりたいとき foreach ($data_array as &$data) { $data['中身']['値'] = true; } 繰り返し処理のあとの$data_arrayを変更された状態にしたい場合は、値の変数に&をつける。 値から配列のキーを取りたいとき array_search(値, 配列); 定数クラス内の配列('定数が表すもの'=>定数)からマジックナンバーを取り出したい時によく使ってます。 array_search($const, CONST_CLASS::CONST_LIST); 配列から任意の値を削除して、別の配列を作りたいとき こちらを参照しました。PHPで配列から特定の要素を削除する array_values(array_diff(配列, 第一引数から削除する値の配列); 配列同士を比較するarray_diffの戻り値(値だけ消えてキーはそのまま)をarray_valuesで整える。 リクエストで変更するカラムの配列を受け取り、その中から変更レコードのものを除外した配列を作ってwhereInに渡す、みたいな処理で使ってます。 一定期間の中でランダムな日付を作りたい時 こちらを参照しました。特定の2つの日付の間から、ランダムに1日を取得 HogeFactory.php $start = Carbon::create('2021', '1', '1'); $end = Carbon::create('2021', '12', '31'); $min = strtotime($start); $max = strtotime($end); $date = rand($min, $max); return [ 'なんらかの日付' => date('Y-m-d', $date), ]; Factoryでテストデータの日付を適当に作る際、この方法で1年の内どこかしらの日付を取ってくるようにしました。 空のコレクションはifでfalseにはならない なぜなら配列ではなく、Collectionクラスのインスタンスだから… 中身があろうとなかろうと… 中身の有無で処理を変えたいときは($collection->isEmpty())で真偽値を返してもらうとよい。 定数は定数クラスを作るのが楽 こちらを参照しました。Laravelで定数を使うときにConfigを使う腰抜けはもう死んだ configに定数.phpを作って配列をリターンするやり方はどうも不便でなりません。 デメリットは参考記事にも書いてありますし、個人的にはVSCodeで表示したとき一面まっかっかになってしまうのが見づらくてしょうがないです。 クラスで管理するメリットとしては、個人的にはテストコードで簡単に使えるという点に尽きると思います。 前職では定数はconfigで定義し、テストコード内の定数はすべてマジックナンバーで書いてましたので、変更がある度に地獄でした。 「0」だの「301(なんらかの独自ステータスコード)」だの、検索かけて書き換えようにもテストがデグらないか不安で不安で…見てるうちになんの数字だかわかんなくなってくるし。 というわけで定数クラス推しです。 PHP8.1ではfinal public const修飾子をつけることで、クラス定数を上書きさせないことが可能になりました。安心ですね。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

(仮)Laravel Snappyにて、cssサイズが想定通りにする。(wkhtmltopdf側の設定をする。)

※私的備忘録のため、乱雑に記載しています。 【問題点】 Laravel Snappy にて、cssが想定通りに出力されない 【原因】 wkhtmltopdf にて、自動調整がdefaultでonになっている。 【解決方法】 snappyのsetOptionにて、以下のように設定すれば良い。 ->setOption('disable-smart-shrinking', true); ※wkhtmlでは、--disable-smart-shrinking true を追加してあげれば良い。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Cropper.jsで加工した画像をAjaxでLaravelに送り保存する。

この記事では、Cropper.jsを利用し画像を加工したあとに、加工した画像をAjaxを通してLaravelに渡し、その画像を保存する方法を紹介します。 Cropper.jsは、ライブプレビューとカスタムアスペクト比をサポートしており、JavaScript / jQueryプラグインを画像のトリミングに利用するのに便利です。 事前準備 1. フォルダの作成 ファイルを保存する先のフォルダを作成します。 今回、コントローラで指定するフォルダは「storage/app/public/upload」です。 ファイルをアップロードして画像を切り取って保存を押すと、このフォルダに保存されます。 バックエンド側 2. ルーティング 次に下記のルーティングを設定してください。 routes/web.php Route::get('image-cropper','ImageCropperController@index'); Route::post('image-cropper/upload','ImageCropperController@upload'); 3. コントローラ 次に下記のようなコントローラを作成します。 app/Http/Controller/ImageCropperController.php <?php namespace App\Http\Controllers; use Illuminate\Http\Request; class ImageCropperController extends Controller { public function index() { return view('cropper'); } public function upload(Request $request) { $folderPath = storage_path('app/public/upload/'); // 保存先のパス $image_parts = explode(";base64,", $request->image); $image_type_aux = explode("image/", $image_parts[0]); // ファイルの型を取り出す(今回は使わない) $image_type = $image_type_aux[1]; // ファイルの型を取り出す(今回は使わない) $image_base64 = base64_decode($image_parts[1]); // 画像データとして取り出す $file = $folderPath . uniqid() . '.png'; // 保存に使うファイル名 file_put_contents($file, $image_base64); // ファイルを保存 return response()->json(['success'=>'success']); // JSONでレスポンスを返す } } フロントエンド側 3. ビュー 最後にお待ちかねのビューを用意します。 ここにCropper.jsの処理も記述します。 resources/views/cropper.blade.php <!DOCTYPE html> <html> <head> <title>Laravel Crop Image Before Upload using Cropper JS - LaravelCode</title> <meta name="_token" content="{{ csrf_token() }}"> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" crossorigin="anonymous" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha256-WqU1JavFxSAMcLP2WIOI+GB2zWmShMI82mTpLDcqFUg=" crossorigin="anonymous"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.6/cropper.css" integrity="sha256-jKV9n9bkk/CTP8zbtEtnKaKf+ehRovOYeKoyfthwbC8=" crossorigin="anonymous" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.6/cropper.js" integrity="sha256-CgvH7sz3tHhkiVKh05kSUgG97YtzYNnWt6OXcmYzqHY=" crossorigin="anonymous"></script> </head> <style type="text/css"> img { display: block; max-width: 100%; } .preview { overflow: hidden; width: 160px; height: 160px; margin: 10px; border: 1px solid red; } .modal-lg{ max-width: 1000px !important; } </style> <body> <div class="container"> <h1>Cropper.JSで加工した画像をAjaxでLaravelに送信</h1> <input type="file" name="image" class="image"> </div> <div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> <div class="modal-dialog modal-lg" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <div class="img-container"> <div class="row"> <div class="col-md-8"> <img id="image" src="https://avatars0.githubusercontent.com/u/3456749"> </div> <div class="col-md-4"> <div class="preview"></div> </div> </div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">キャンセル</button> <button type="button" class="btn btn-primary" id="crop">保存</button> </div> </div> </div> </div> </div> </div> <script> var $modal = $('#modal'); var image = document.getElementById('image'); var cropper; $("body").on("change", ".image", function(e){ var files = e.target.files; var done = function (url) { image.src = url; $modal.modal('show'); }; var reader; var file; var url; if (files && files.length > 0) { file = files[0]; if (URL) { done(URL.createObjectURL(file)); } else if (FileReader) { reader = new FileReader(); reader.onload = function (e) { done(reader.result); }; reader.readAsDataURL(file); } } }); $modal.on('shown.bs.modal', function () { cropper = new Cropper(image, { aspectRatio: 1, viewMode: 3, preview: '.preview' }); }).on('hidden.bs.modal', function () { cropper.destroy(); cropper = null; }); $("#crop").click(function(){ canvas = cropper.getCroppedCanvas({ width: 160, height: 160, }); canvas.toBlob(function(blob) { url = URL.createObjectURL(blob); var reader = new FileReader(); reader.readAsDataURL(blob); reader.onloadend = function() { var base64data = reader.result; $.ajax({ type: "POST", dataType: "json", url: "image-cropper/upload", data: {'_token': $('meta[name="_token"]').attr('content'), 'image': base64data}, success: function(data){ $modal.modal('hide'); alert("success upload image"); } }); } }); }) </script> </body> </html> 最後に 以上の実装でAjaxを通してLaravelにCropper.jsで加工した画像を送れるはずです。 ぜひ試してみてください。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む