20211125のPHPに関する記事は5件です。

11月25日の学習

本日はテックアカデミーの最初のメンタリングがありました。 その中でQiitaというサービスをメンターさんから教えてもらい、始めました。 現在はレッスン9のチャプター2まで進んでいます。 これから毎日学習報告をさせていただければと思います。 気づいたことや感じたことを逐一書いていきます。初心者ですが、よろしくお願いします。 本日の進捗 テックアカデミー レッスン8の課題に取り組みクリア My SQLの学習に入る。 今日はレッスン8の課題に取り組みましたが、nl2brの関数に手こずったり、h3タグをtableに入れてしまうというミスがありました。もう一度bootstrapのカリキュラムを見直ししたりしないといけないなと感じました。 これからひとまず25分のポモドーロ・テクニックで集中力を切らさないように学習していきたいです。 明日からMySQLの学習に入ります。また新しいことですが、一生懸命頑張りたいと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WordPressで記事のタグ名を取得するショートコードを作成

WordPressで記事のタグ名を取得するショートコードを作成しました。 目的 WordPressで全記事に共通して表示されるキャッチコピーやマイクロコピー、固定の文言をより具体化したいと考えたため。 例) Pythonの解説記事、PHPの解説記事、Javaの解説記事といった風に言語ごとに記事のタグが設定されているサイト構造の場合。 [タグ名(PHPなど)]に関して分からないことがありましたらお問い合わせフォームへ。 [タグ名(PHPなど)]で困ったらこちらのプログラミングスクールがおすすめです。 といた風に表記内容を具体化できる。 作成方法 1. タグ名を取得するPHPファイルをテーマ内に作成 まずはタグ名を取得するためのPHPファイルをWordPressテーマ内に作成します。 get_tag_name.php <?php //タグが設定されていないときに表示させたい文言 $ctaTagName = "不明"; //WordPressのタグを取得 $tags = get_the_tags(); //タグを取得できた場合の処理 if ($tags) { foreach($tags as $tag) { $ctaTagName = $tag->name; } } echo $ctaTagName; ?> *タグ名は1つしか取得できません。 2. functions.phpでショートコードを作成する functions.phpにショートコードを作成するためのPHPコードを書きます。 functions.php function tag_echo_php( $atts ){ ob_start(); get_template_part('get_tag_name'); return ob_get_clean(); } add_shortcode( 'TAG_NAME', 'tag_echo_php' ); これによって[TAG_NAME]というショートコードを書くことでget_tag_name.phpが呼び出されるtag_echo_php関数が読み込まれます。 3. ショートコードで確認 あとはタグが設定されている適当な投稿画面で[TAG_NAME]というショートコードを書いてタグを呼び出してみましょう。 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ポーリングによる状態チェックを軽量化した話

はじめに 注・最初っからそうしとけよ、という話です。 研修で使うようなゲームっぽいプロダクト(ゲームマスター:プレーヤー=1:n)で、双方が行った操作(データ変更)をお互いにある程度リアルタイムで検知するために、ポーリングを用いて定期的にチェックすることで実現していました。 ポーリングを用いたのは下記の理由によります。 push型が理想だがミドルウェア構成をシンプルにしたかった 仕組みも簡単だし確実 DBの問い合わせも軽そうなので負荷もそれほどではないだろう(甘かった) 現実に全力で殴られる さていざ実戦投入してみると、数十クライアント程度でCPUがパンパンになって、ロードアベレージが100近くまで行きました。 DBを外に出したり、ポーリング間隔をあけたりしましたが、劇的な効果は得られませんでした。 (php-fpmがアイドリングでもなぜかCPUを食いっぱなしになるという現象もあったのでそれも一因かもしれません。これはstraceで真面目に調べようと思ったら突如再現しなくなりました。) 反攻に出る これは根本的に対策せねばなるまいということで、どうするか検討しました。 ポーリングで返しているデータは、ゲームの状態を入れたjsonで、アクセスが来るたびにDBからデータを取ってきてPHPでデータを加工して返していました。 実はこのプロダクトのゲーム状態の変化はせいぜい分速ひと桁程度です。 そしてゲーム状態に変化がなければ当然jsonデータにも変化はなく、アクセスが来るたびにDBにアクセスして作る必要はありません。 ですので変化が起きるタイミングでスタティックなjsonファイルに書き出して、ポーリングはそのファイルにアクセスさせることにしました。これならポーリングのアクセスはnginxの階層のみで動くので、軽くなるはずです。 余談 jsonファイルのreadとwriteがバッティングするとまずそうなので、書き込み方法は下記のようにしています。 完璧ではないかも知れませんが、少なくとも同じファイルに読み書きが同時に起こることはないので概ね大丈夫ではないかと思います。 tmpファイルにjsonデータを書き出す 現jsonファイルを別の名前にrenameする tmpファイルを正規の名前にrenameする さらなる反攻 スタティックなファイルにしてすっきり軽くなりましたが、今度は状態に変化がなくても毎回同じものが転送されるのが無駄に感じます。 ですので更新チェックを入れて、前回のアクセスと変化がない場合は304(Not Modified)を返させてbodyの転送を節約するようにしました。 これは、前回アクセス時のレスポンスのEtagヘッダの値をリクエストのIf-None-Matchヘッダの値として付けることで実現しました。 まとめ ポーリングが来た時に毎回DBにアクセスしていたら大したアクセス量じゃないのに重すぎた 状態が変化する頻度が低いのでファイルに書き出すことにした さらに更新チェックを入れて無駄なデータ転送を減らした
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MVCモデルのViewにDTOを導入するとどうなるか

はじめに 株式会社じげんのアレクセイです プロパンガス会社の情報・見積もり比較サービス エネピの開発を担当しています。 今回は、Viewでの作業を楽にするためにDTOの導入について書いていきます。 コントローラーで取得したモデルをそのままViewへ渡すことが多いと思いますが、Viewでモデルのリレーションを呼び出したり、モデルのプロパティによって分岐処理を入れたりします。分岐が複雑になり、同じ分岐が増え、だんだんViewのソースが読みづらくなっていきます。ビズネスロジックが変わったら何箇所を直さないといけないことになります。定期的にこういう依頼が来るとViewでの作業が大変です。そしてリファクタリングの時にモデルのリレーションやプロパティをなくすか変更する場合はエラーが起こりやすくなります。 始める前に この記事のソースコードは実際に使われているものではないので、以下の画像をHTMLページとしてメージしています。 DTOとは? 【Data Transfer Object】オブジェクト指向プログラミングでよく用いられる典型的なオブジェクトの設計パターン(デザインパターン)の一つで、関連するデータを一つにまとめ、データの格納・読み出しのためのメソッドを定義したオブジェクトのことです。異なるプログラム間やコンピュータ間でひとまとまりのデータを受け渡す際に用いられます。 引用:https://e-words.jp/w/DTO.html DTOを導入する前のView view.html @if ($book->author) @if ($book->author->firstName && $book->author->lastName) <p>{{ $book->author->firstName }} {{ $book->author->lastName }}</p> @else <p>Unknown Author</p> @endif <p>{{ $book->author->registeredDate->format('Y-m-d') }}</p> @endif <p>Price: {{ $book->price ? number_format().'円' : 'Sold out' }}</p> <a href="/buy-me">{{ session('ab.test') ? 'Buy now' : 'Buy' }}</a> @if ($book->images) @foreach ($book->images as $image) <div><img src="{{ $image->url }}"></div> @endforeach @elseif <div><img src="no-image.jpg"></div> @endif DTOオブジェクトを用意する dto.php class BookShowDto extends AbstractDto { /** * @var bool */ public $showAuthorSection; /** * @var string */ public $authorFullName; /** * @var mixed|string|null */ public $authorRegisteredDate; /** * @var array */ public $bookImages = []; /** * @var string */ public $bookPrice; /** * @var string */ public $buyButtonText = 'Buy'; // or HTML } DTOオブジェクトのプロパティを設定する logic.php $dto = new BookShowDto; if ($book->author) { $dto->showAuthorSection = true; $dto->authorFullName = $book->author->firstName.$book->author->lastName; if (!$dto->authorFullName) { $dto->authorFullName = 'Unknown Author'; } $dto->authorRegisteredDate = $book->author->registeredDate->format('Y-m-d'); } $dto->bookPrice ? $book->price ? number_format().'円' : 'Sold out'; @foreach ($book->images as $image) { $dto->bookImages[] = $image->url; } // Default image empty($dto->bookImages) and $dto->bookImages[] = '/images/no-image.jpg'; // AB testing session('ab.test') and $dto->buyButtonText = 'Buy now'; DTOを導入する後のView view.html @if ($dto->showAuthorSection) <p>{{ $dto->authorFullName }}</p> <p>{{ $dto->authorRegisteredDate }}</p> @endif <p>Price: {{ $dto->bookPrice }}</p> <a href="/buy-me">{{ $dto->buyButtonText }}</a> @foreach ($dto->bookImages as $url) <div><img src="{{ $url }}"></div> @endforeach まとめ 単純なページであればメリットをあまり感じませんが、リレーションが多い、大量な分岐が入っているページならViewとビジネスロジックの間にDTOを置けば作業が楽になるかと思います。実際のプロジェクトに導入したら以下のメリットを感じました。 ① Viewが読みやすい。 ② 多くの分岐が1箇所にまとまっている、HTMLと混ざっていないので、HTMLだけでなくphpのロジックも読みやすい。 ③ DTOのデフォルト値を設定できるので、リファクタリングの際に値の設定を忘れたり、リレーションが変わる際にもエラーが起きない。 ④ ビジネスロジックが重かったらDTOをそのまま簡単にキャッシュに乗せられる。 ⑤ ボタンや文言などのABテストの実装がやりやすい。 みなさんも是非試してみてください。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

いろいろな言語でAPIコールするよ!

導入 webAPIの叩き方を各言語でまとめました。 後で見返す用です。 2021年11月23日時点:Postリクエスト送信 json リクエストのサンプルパラメータ sample_endpoint = "http://localhost:8888/sample" sample_parameter = { "title": "トマトスープ", "making_time": "15分", "serves": "5人", "ingredients": "玉ねぎ, トマト, スパイス, 水", "cost": "450" } Curl curl --location --request POST 'http://localhost:8888/recipes' \ --header 'Content-Type: application/json' \ --data-raw '{ "title": "トマトスープ", "making_time": "15分", "serves": "5人", "ingredients": "玉ねぎ, トマト, スパイス, 水", "cost": "450" }' Go package main import ( "fmt" "strings" "net/http" "io/ioutil" ) func main() { url := "http://localhost:8888/recipes" method := "POST" payload := strings.NewReader(`{ "title": "トマトスープ", "making_time": "15分", "serves": "5人", "ingredients": "玉ねぎ, トマト, スパイス, 水", "cost": "450" }`) client := &http.Client { } req, err := http.NewRequest(method, url, payload) if err != nil { fmt.Println(err) return } req.Header.Add("Content-Type", "application/json") res, err := client.Do(req) if err != nil { fmt.Println(err) return } defer res.Body.Close() body, err := ioutil.ReadAll(res.Body) if err != nil { fmt.Println(err) return } fmt.Println(string(body)) } php <?php require_once 'HTTP/Request2.php'; $request = new HTTP_Request2(); $request->setUrl('http://localhost:8888/recipes'); $request->setMethod(HTTP_Request2::METHOD_POST); $request->setConfig(array( 'follow_redirects' => TRUE )); $request->setHeader(array( 'Content-Type' => 'application/json' )); $request->setBody('{\n "title": "トマトスープ",\n "making_time": "15分",\n "serves": "5人",\n "ingredients": "玉ねぎ, トマト, スパイス, 水",\n "cost": "450"\n}'); try { $response = $request->send(); if ($response->getStatus() == 200) { echo $response->getBody(); } else { echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' . $response->getReasonPhrase(); } } catch(HTTP_Request2_Exception $e) { echo 'Error: ' . $e->getMessage(); } python import requests import json url = "http://localhost:8888/recipes" payload = json.dumps({ "title": "トマトスープ", "making_time": "15分", "serves": "5人", "ingredients": "玉ねぎ, トマト, スパイス, 水", "cost": "450" }) headers = { 'Content-Type': 'application/json' } response = requests.request("POST", url, headers=headers, data=payload) print(response.text) これから getパラメータの記述方法なども追記していく
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む