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

外部ファイル関連(出力、読込、追記)

●外部ファイルへの書き込み file_put_contents('パス/出力ファイル名', '出力内容')を用いる。 例) <?php $success = file_put_contents('data/output.txt', 'ファイルを出力しました'); if ($success !== false) { echo 'ファイルの出力が完了しました'; } else { echo 'ファイルの出力に失敗しました'; } ※dataディレクトリにoutput.txtを作成 ※output.txtには、ファイルを出力しました、と記入 ※if文で完了or失敗をチェック ●外部ファイルの読込、追記 ・外部ファイルの読込 file_get_contents('外部ファイルへのパス')を用いる。 ・既に存在している外部ファイルへの追記 file_put_contents('パス/追記ファイル名', '出力内容')を用いる。 例) <?php // ファイルの読込 $output = file_get_contents('data/output.txt'); // ファイルへの追記 $output = $output . "<br>追記です"; file_put_contents('data/output.txt', $output);
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHP 配列の要素をランダムに並び替える関数 shuffle

概要 既存の配列を渡すと配列内部の要素をランダムに並び替えてくれる関数shuffle()についてまとめる。 紹介 下記の様に実行する。 $array = ['りんご', 'いちご', 'バナナ']; shuffle($array); 下記の様に配列の内部要素をランダムに並び替える。 var_dump($array); // 筆者が実行したときは['バナナ', 'いちご', 'りんご']に並び替えされた 当該関数に引数として渡す配列そのものの要素を入れ替える(難しい言い方をすると「参照渡し」でもともとの配列に影響を与える)ので注意する。 成功したらtrue、失敗したらfalseを返す。 参考文献 https://www.php.net/manual/ja/function.shuffle.php
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel ブラウザからログイン済みのユーザーが実行できるAPIの作成と確認

概要 Laravelのアプリケーションにてブラウザからログインしているユーザーが実行できるAPIを作成する方法をまとめる。 ご注意 本知見は同じチームで働くエンジニアさんにご教授いただいた内容です。 筆者がかなり詰まっていたときにお力添えいただきました!改めてお礼申し上げます! 今回、詰まりそうな作業を極力少なくするためにAPIで実行されるルーティングをweb.phpに記載します。 本来、APIのルーティングはapi.phpに記載することが望ましいです。 今回web.phpで定義している処理はあくまで「ROOT GET OK」の文字列を返すだけのものですが、応用すればいろいろな処理が可能です。 作成 Laravelの新規アプリケーションを作成する。 下記の方法でLaravel Breezeを用いた認証処理を作成する。 https://readouble.com/laravel/9.x/ja/starter-kits.html DBにテーブル作成、.envの記載とアプリケーションの起動、composer install、などを行い、ブラウザから「Register」ページにアクセスして任意のユーザーを登録する。 登録したユーザーでブラウザからログインできる事を確認する。 下記の記載をweb.phpに記載する。 web.php Route::get('/get_test', function(){ return 'ROOT GET OK'; })->middleware('auth'); 体験 用意するもの PostmanやThunder Clientなどのリクエストを送るツール VScode Thunder Client の導入方法 リクエストを送るツールで下記のようなリクエストを作成 項目 情報  備考  リクエスト名 get_test 皆さんの任意のものでOK HTTPメソッド GET リクエスト送信URL 任意のホスト名/get_test dockerの方はhttp://localhost:ポート番号/get_testphp artisan serveでローカルサーバー立てている方はhttp://127.0.0.1/get_testとかになるはずです。php artisan serveの方のURLが若干自信無いので間違えているかも。。すみません ヘッダー情報 空 一回authミドルウエアが実行されているか知りたいのでまずは空で Auth情報 特に入力しない ヘッダー情報が空(未認証)でどんな挙動をするか確認 /get_testに対してGETのリクエストを投げてみる。 web.phpにAPIのルーティングを記載しちゃっているためおそらくログイン画面のhtmlが返される。 これはブラウザ側で認証していないと開けないURL領域に未認証状態でアクセスした場合と同じ挙動。ブラウザで見ているかリクエストを送るツールで返されたhtmlのコードを見ているかの差。 認証をパスした状態で「ROOT GET OK」の文字が返って来てほしいので次の方法で確かめてみる。 ブラウザでログイン、ヘッダーにCookieを追加してどんな挙動をするか確認 作成での中で行った作業と同じ様にブラウザからログインを行う。 ログインした画面(おそらくダッシュボード画面)にてChromeの開発者ツールを起動する。 「Network」タブをクリックする。 一度画面をリロードする。 「Name」の部分に「login」や「home」などがあると思うのでクリックする。 「Request Headers」の「Cookie」を全選択してコピーする。(Cookie:の部分も含めてすべてコピーする。) リクエストを送るツールの当該のリクエストのヘッダーにコピーしたCookieをそのまま貼り付ける。 Thunder Clientの場合 リクエストの詳細の「Headers」をクリックする。 「Raw」のチェックボックスにチェックをつける。 コピーした内容を貼り付け。 ちなみに筆者のThunder Clientはhttp://localhost:8000を変数「host」に割り当てている。 Postmanの場合(今回は未検証、昔に試した方法を思い出して記載しているので若干違うかも、すみません。) リクエストの詳細の「Cookies」をクリックする。 任意のドメイン名(おそらく)を入力して「Add」をクリックする。 「Add Cookie」をクリックする。 コピーした内容を貼り付けて「Save」をクリックする。 /get_testに向けてリクエストを送信する。 ブラウザから認証を突破したCookieをそのままヘッダーに入れてリクエストを投げているので、認証を突破し、「ROOT GET OK」の値が帰ってきた。 上記を実施しても「ROOT GET OK」の値が帰ってこない場合 作成での中で行った作業と同じ様にブラウザからログインを行う。 ログインした画面(おそらくダッシュボード画面)にてChromeの開発者ツールを起動する。 「Network」タブをクリックする。 一度画面をリロードする。 「Name」の部分に「login」や「home」などがあると思うのでクリックする。 「Request Headers」に記載されている内容をキーと値すべて範囲選択してコピーする。 リクエストを送るツールの当該のリクエストのヘッダーにコピーしたRequestHeadersをそのまま貼り付ける。 Thunder Clientの場合 リクエストの詳細の「Headers」をクリックする。 「Raw」のチェックボックスにチェックをつける。 コピーした内容を貼り付け。 ポイント Cookieの値はすべてまるまるリクエストで投げてあげること。 XSRF-TOKENのセッションIDだけとかを「Cookie」の名前で送信してもだめ! とにかくログインしたあとの画面のリクエストヘッダーのCookieの「Cookie:」も全て含めてコピーしてリクエストを送るツールで送ってあげないと認証されているとアプリ側が認識してくれない。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Symfonyプロジェクトをherokuにデプロイする。

モチベーション The Fast Track - 基礎から最速で学ぶ Symfony 入門でSymfonyの勉強中、作業内容をデプロイする説がありました。 その際、Platform.shにデプロイするとありましたが、情報量が少ない上に、私の勉強不足により上手く行うことが出来ませんでした。 ですので、比較的情報も多く、日本語ドキュメントが豊富なHerokuにデプロイすることにしました。 環境 Symfony6系 "php": ">=8.0.2" 行ったこと まずプロジェクトを作成します。 symfony new guestbook --version=6.0 --php=8.1 --webapp --cloud (本文ではオプションに--dockerがついていますが、元バージョンでは元から組み込まれている?ので必要ありませんでした。) 続いてターミナル上でenv=prodにします。 $ heroku config:set APP_ENV=prod Procfileを作成し $echo web: $(composer config bin-dir)/heroku-php-apache2 public/ > Procfile $composer require symfony/apache-pack git pushしてherokuにdelpoyされたら、ブラウザで確認してみます。 env=prodでは、welcomeページはないので404になります。 適当にコントローラーを作成し $ php bin/console make:controller HogeController 作成した/hogeにアクセスしてみると、、、多分見れないですよね。500エラーが出ます。 ログは {"message":"Uncaught PHP Exception Twig\\Error\\RuntimeError: \"An exception has been thrown during the rendering of a template (\"Could not find the entrypoints file from Webpack: the file \"/app/public/build/entrypoints.json\" does not exist.\").\" at /tmp/build_0efa956e/templates/base.html.twig line 9","context":{"exception":{"class":"Twig\\Error\\RuntimeError","message":"An exception has been thrown during the rendering of a template (\"Could not find the entrypoints file from Webpack: the file \"/app/public/build/entrypoints.json\" does not exist.\").","code":0,"file":"/tmp/build_0efa956e/templates/base.html.twig:9","previous":{"class":"InvalidArgumentException","message":"Could not find the entrypoints file from Webpack: the file \"/app/public/build/entrypoints.json\" does not exist.","code":0,"file":"/app/vendor/symfony/webpack-encore-bundle/src/Asset/EntrypointLookup.php:124"}}},"level":500,"level_name":"CRITICAL","channel":"request","datetime":"2022-03-23T08:59:44.310978+00:00","extra":{}} 解決策を載せておくと webpack_encore.yamlを少し修正する必要があるようですね。 strict_mode: false もう一度デプロイすると 出来ました?? 下のリンクから見れます? https://desolate-spire-14306.herokuapp.com/hoge 最後に。 この記事がSymfonyを学ぶ方の一助になれば幸いです。 参考 Heroku での Symfony 4 および 5 アプリのデプロイ
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【PHP】タグ機能②

下記投稿の続きで、タグ機能に文字かタグの数で改行するように制御を追加します。 タグか文字の数で改行 form.php function inputChange() { : spans = skill.getElementsByTagName("span"), skills = new Array(); for (i = 0; i < spans.length; i++) { skills[i] = spans[i].textContent; } skills = skills.join(''); if (3 <= spans.length || 9 <= skills.length) { // 改行処理 } : タグ数と文字数を取得して、条件に合えば改行するようにします。 今回はタグ数が3つ以上または、文字数が9文字以上で設定します。 それでは、改行処理を実装していきます。 条件が一致したときに、div要素を作成して改行するようにします。 例えば上記のようなタグの場合は、 このようにdiv要素をタグの間に入れて改行させます。 form.php : div_element = document.createElement("div"); span_element.setAttribute("id", "child-span" + i + ""); : if (3 <= spans.length || 9 <= skills.length) {   i--; if (document.getElementById('child-span' + i + '') !== null) { parentDiv.appendChild(div_element, document.getElementById('child-span' + i + '')); } i++; } i++; span要素に変数iが入ったIDを追加し、1個前のタグ('child-span' + i + ''からi-1したもの)があれば、div要素を追加します。 しかし、現在のままだと2回目の改行を行うときに、タグ数と文字数が前の状態のため何を入力しても改行してしまいます。 なので、改行があった際の処理を追加します。 form.php <body> : <input type="text" id="sample" /> <div id="skill"> </div> <input type="hidden" name="skill_count" id="skill_count"> //追加 : </body> : skill_count = document.getElementById('skill_count').val; : if (0 < document.getElementById('skill_count').val) { i--; skills = new Array(); // 改行した列で再度文字数取得 for (k = 0; k < skill_count; k++) { skills[k] = spans[i].textContent; i--; } spans = ''; skills = skills.join(''); // skill_countの値で改行後のタグ数を決める switch (skill_count) { case 2: i += 1; spans = '@@'; break; case 3: i += 2; spans = '@@@'; break; case 4: i += 3; spans = '@@@@'; break; case 5: i += 4; spans = '@@@@@'; break; default: } i++; document.getElementById('skill_count').val += 1; } if (3 <= spans.length || 9 <= skills.length) {  : document.getElementById('skill_count').val = 1; } 改行を判定する値はブラウザ側(ID属性:skill_count)で持ちます。 skill_countが改行後のタグ数になっているため、こちらで改行後のタグ情報を取得します。 switch文でskill_countの値からspansに@を代入して、 タグ数を決めています。 こちらの処理を追加すると、2回目以降の改行もタグ数と文字数をカウントするようになります。 また、最終行タグのバツ印をクリックした際にdocument.getElementById('skill_count').valの値もデクリメントする必要があるので、最終行をクリックしたかの判定が必要になります。 from.php // タグのバツ印がクリックされた場合 $(document).on('click', '.far.fa-times-circle', function() { var k = 0, skills = new Array(), skill = document.getElementById("skill"), spans = skill.getElementsByTagName("span"), span = $(this).parents(".skill_tag")[0].textContent; switch (document.getElementById('skill_count').val) { case 1: var spans_count = spans.length - 1; break; case 2: var spans_count = spans.length - 2; break; case 3: var spans_count = spans.length - 3; break; default: } for (i = spans_count; i < spans.length; i++) { skills[k] = spans[i].textContent; k++; } $(this).parents(".skill_tag").remove(); skills = skills.join(''); if (skills.indexOf(span) != -1) { document.getElementById('skill_count').val -= 1; } }); spans_countに総タグ数から最終行のタグ数を引いた値を代入して、 その値からskillsに最終行のタグの文字を入れます。 spanにバツ印をクリックしたタグの文字を代入し、 skillsの中にspanの値があれば、document.getElementById('skill_count').valをデクリメントします。 最後にすでに入力されているものについては、タグ追加しないようにします。 function inputChange() { : // 既に入力済みのものはタグ追加しない if (skills.indexOf(fome_x_name) != -1) { return false; } :
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelでニコニコ動画 『スナップショット検索API v2』を利用してみた

はじめに Laravelを学び始めたばかりの筆者が、自身のアプリにニコニコ動画のコンテンツ検索機能を実装した際のメモです。Qiitaの記事は初めて書きました。何かミスを含んでいる可能性は十分ありますので、あらかじめご了承ください。 『スナップショット検索API v2』について ニコニコ動画のコンテンツを検索/取得できる公式APIです。 使い方は公式ドキュメントにわかりやすく説明してありますので、大半の方はこの記事で無く公式ドキュメントを読んだ方が速いと思います。 ControllerでcURLを使って情報を取得 Controller内で必要なパラメータを指定しcURLでGETを行います。今回は、ユーザから検索対象文字の"q"と何ページ目を取得するかを示す"page"を受け取り、APIのパラメータを指定する際に用いています。 MyPageController.php <?php namespace App\Http\Controllers; use Illuminate\Http\Request; class MyPageController extends Controller { public function search(Request $request){ $query = $request->get('q'); $page = $request->get('page'); $App_name = '#アプリ名を記述'; $url = 'https://api.search.nicovideo.jp/api/v2/snapshot/video/contents/search?q='.urlencode($query).'&targets=title,description,tags&fields=contentId,title,userId,thumbnailUrl&filters[tags][0]=VOCALOID&filters[tags][1]=UTAU&filters[tags][2]=CeViO&filters[tags][3]=VOICELOID&_sort=-viewCounter&_offset='.strval(($page-1)*20).'&_limit=20&_context='.$App_name; $curl = curl_init($url); //cURLセッションを初期化 curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET'); //GETで取得 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);//サーバー証明書の検証を行わない curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);//戻り値を文字列で $curl_response = curl_exec($curl);//実行 curl_close($curl); //APIからのレスポンスを配列に変換し、検索結果をviewへ渡す。 $result = json_decode($curl_response, true); $response = response()->view('search', ['result' => $result]); return $response; } } 各種パラメータについて 下記のAPIエンドポイントに対して、必要なクエリパラメータを付与します。 APIエンドポイント https://api.search.nicovideo.jp/api/v2/snapshot/video/contents/search 最低限必要なパラメータ パラメータ名 型 説明 q string 検索キーワード targets string 検索対象のフィールド。キーワード検索の場合はtitle,description,tags。タグ検索の場合はtagsExact。 _sort string ソート順の指定。今回は再生数降順で-viewCounterとしてます。 _context string 利用者のサービス名・アプリケーション名。 その他のパラメータ パラメータ名 型 説明 fields string 取得したいコンテンツ情報。contentId,title,description,tagsなど様々な情報を指定できる。今回取得したのは contentId, title, userId, thumbnailUrlである。 filters string 検索結果を絞るための条件を指定できます。先ほどの例では、filters[tags][0]=VOCALOIDとして、VOCALOIDタグの動画に絞っています。 jsonFilter string 複雑なフィルター条件を指定する際に使用します _offset integer コンテンツの取得オフセットです。先ほどの例では、1ページあたりのコンテンツ数を20とし、pageで指定されたページ位置に該当するコンテンツを取得するため、_offsetをstrval(($page-1)*20)としています。 _limit integer 返ってくるコンテンツの最大数を指定。先ほどの例では20としています。 例えば、page=1, query=初音ミク とした場合のレスポンスは以下の通りです。 json {"data":[{"contentId":"sm1097445","title":"【初音ミク】みくみくにしてあげる♪【してやんよ】","userId":70391,"thumbnailUrl":"https://nicovideo.cdn.nimg.jp/thumbnails/1097445/1097445"},{"contentId":"sm15630734","title":"『初音ミク』千本桜『オリジナル曲PV』","userId":449061,"thumbnailUrl":"https://nicovideo.cdn.nimg.jp/thumbnails/15630734/15630734.34480305"},{"contentId":"sm1715919","title":"初音ミク が オリジナル曲を歌ってくれたよ「メルト」","userId":317063,"thumbnailUrl":"https://nicovideo.cdn.nimg.jp/thumbnails/1715919/1715919"},{"contentId":"sm11809611","title":"【オリジナル曲PV】マト リョシカ【初音ミク・GUMI】","userId":380847,"thumbnailUrl":"https://nicovideo.cdn.nimg.jp/thumbnails/11809611/11809611"},{"contentId":"sm10759623","title":"初音ミク・巡音ルカ オリジナル曲 「ワールズエンド・ダンスホール」","userId":11912389,"thumbnailUrl":"https://nicovideo.cdn.nimg.jp/thumbnails/10759623/10759623"},{"contentId":"sm27965309","title":"DECO*27 - ゴーストルール feat. 初音ミク","userId":811012,"thumbnailUrl":"https://nicovideo.cdn.nimg.jp/thumbnails/27965309/27965309"},{"contentId":"sm2937784","title":"初音ミクオリジナル曲 「初音ミクの消失(LONG VERSION)」","userId":1091989,"thumbnailUrl":"https://nicovideo.cdn.nimg.jp/thumbnails/2937784/2937784"},{"contentId":"sm31606995","title":"ハチ MV「砂の惑星 feat.初音ミク」","userId":380847,"thumbnailUrl":"https://nicovideo.cdn.nimg.jp/thumbnails/31606995/31606995"},{"contentId":"sm3504435","title":"初音ミク が オリジナル曲を歌ってくれたよ「ワールドイズマイン」","userId":317063,"thumbnailUrl":"https://nicovideo.cdn.nimg.jp/thumbnails/3504435/3504435"},{"contentId":"sm19133907","title":"【初音ミク&GUMI】脳漿炸裂ガール【オリジナル】","userId":2591026,"thumbnailUrl":"https://nicovideo.cdn.nimg.jp/thumbnails/19133907/19133907"},{"contentId":"sm9714351","title":"初音ミク オリジナル曲 「ローリンガール」","userId":11912389,"thumbnailUrl":"https://nicovideo.cdn.nimg.jp/thumbnails/9714351/9714351"},{"contentId":"sm8082467","title":"初音ミク オリジナル曲 「裏表ラバーズ」","userId":11912389,"thumbnailUrl":"https://nicovideo.cdn.nimg.jp/thumbnails/8082467/8082467"},{"contentId":"sm6666016","title":"「ロミオとシンデレラ」 オリジナル曲 vo.初音ミク","userId":655340,"thumbnailUrl":"https://nicovideo.cdn.nimg.jp/thumbnails/6666016/6666016.67600511"},{"contentId":"sm31791630","title":"wowaka『アンノウン・マザーグース』feat. 初音ミク","userId":11912389,"thumbnailUrl":"https://nicovideo.cdn.nimg.jp/thumbnails/31791630/31791630"},{"contentId":"sm22960446","title":"【初音ミク】 ウミユリ海底譚 【オリジナル曲】","userId":26225387,"thumbnailUrl":"https://nicovideo.cdn.nimg.jp/thumbnails/22960446/22960446"},{"contentId":"sm15751190","title":"【初音ミク】カゲロウデ イズ【オリジナルPV】","userId":15872264,"thumbnailUrl":"https://nicovideo.cdn.nimg.jp/thumbnails/15751190/15751190"},{"contentId":"sm28576299","title":"エイリアンエイリアン / 初音ミク","userId":49716308,"thumbnailUrl":"https://nicovideo.cdn.nimg.jp/thumbnails/28576299/28576299.67529574"},{"contentId":"sm30177801","title":"ダンスロボットダンス / 初音ミク","userId":49716308,"thumbnailUrl":"https://nicovideo.cdn.nimg.jp/thumbnails/30177801/30177801.97461989"},{"contentId":"sm3645817","title":"初音ミクがオリジナルを歌ってくれたよ「ブラック★ロックシューター」","userId":317063,"thumbnailUrl":"https://nicovideo.cdn.nimg.jp/thumbnails/3645817/3645817"},{"contentId":"sm31685272","title":"DECO*27 - ヒバナ feat. 初音ミク","userId":811012,"thumbnailUrl":"https://nicovideo.cdn.nimg.jp/thumbnails/31685272/31685272"}],"meta":{"id":"f04f124a-049a-4fb7-b712-7b64c57a3ad4","totalCount":267280,"status":200}} これをjson_decodeで配列に変換後、blade内でresult["data"]に対してforeachします。 search.blade.php //・・・ @foreach($result["data"] as $content) <div> <h3>{{ $content['title'] }}</h3> <img src="{{ $content['thumbnailUrl'] }}"> <a href="https://nico.ms/{{ $content['contentId'] }}">動画URL</a> <p>{{ $content['userId'] }}</p> </div> @endforeach //・・・ imgタグでthumbnailUrlからサムネイル画像を取り出したり、contentIdから動画のURLを生成したりできます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】初期設定について

この記事に書いてあること Laravelプロジェクトを立ち上げた直後の初期設定について、最低限必要なものを紹介します。 プロジェクトに応じて、他にも必要があれば設定してください。 タイムゾーン、言語設定 タイムゾーンと言語設定を日本にします。 config/app.phpを以下のように変更。 config/app.php // 'timezone' => 'UTC', 'timezone' => 'Asia/Tokyo', //中略 // 'locale' => 'en', 'locale' => 'ja', デバッグバー クエリ実行ログ、ルーティング、ビュー、セッション等の様々な情報をデバッグバーとして出力してくれます。 githubはこちら 以下のコマンドでインストール。 vagrantにssh接続して、仮想環境上で実行します。 composer require barryvdh/laravel-debugbar デバッグバーは本番環境で表示するべきではないので、リリース時は.envで必ずオフにすること .env APP_NAME=Laravel APP_ENV=local APP_KEY=base64:ygBp5fppgXX+myRzs27tgQfBxRYd6db2/PJnPTJtpa0= APP_DEBUG=false //ここをfalseに変更 APP_URL=http://localhost また.envの変更が改善されない場合はキャッシュの可能性もあるので、下記コマンドでキャッシュクリアを試してみてください。 php artisan cache:clear php artisan config:clear データベース設定 データベースの設定は.envで行います。 下記の箇所を環境に合わせて変更してください。 homesteadで環境構築した場合のユーザーネームとパスワードのデフォルトはhomestead / secretです。 .env DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=study-app DB_USERNAME=homestead DB_PASSWORD=secret データベースに接続できるか確認します。 Laravelにはコマンドラインからデータベースのバージョン管理ができるマイグレーションという仕組みが備わっているので、それを利用してみます。 vagrant sshでログインしている仮想環境上で下記を実行 php artisan migrate データベースに自動でテーブルが作られているはず。 phpMyAdminで確認しましょう。 これで必要最低限の準備ができました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【初心者向け】ポケモンでオブジェクト指向をふわっと学ぶ

はじめに オブジェクト指向とは何か。 プログラミングを学んでいく上で欠かせないものらしいとわかっていながら、ずっと後回しにしていた方や何回学んでも忘れてしまう方(自分)に向けてアウトプットを兼ねて、馴染みのあるポケモンを例に自分なりにまとめてみました! できるだけわかりやすい言葉でまとめているのでかる〜い気持ちで読んでくれたら嬉しいです! もくじ ・オブジェクト指向の理解が困難なワケ… ・オブジェクト指向誕生のきっかけ ・オブジェクト指向とは ・オブジェクト指向で出てくる用語 ・ポケモンでオブジェクト指向を考えてみる ・さいごに オブジェクト指向の理解が困難なワケ… これにはプログラミング初学者ならではの理由があると思いました。 ・オブジェクト指向自体が考え方や概念であるため。 ・書籍や記事での解説が実用的な例を使った解説ではないため。 オブジェクト指向はルールがあって、それに従って書けば動く何かだ!と言うシンプルなものではなく、「概念」「考え方」であるために難しく感じてしまいます。「愛とは何か。」それを考えるのも難しいですよね。。 そして、未経験の人にとってはオブジェクト指向を知らなくてもポートフォリオなどは難なく開発できてしまうために、概念を知ったとしても使うことのメリットは感じづらいことも挙げられるかと思います。 前提として、オブジェクト指向はさまざまな機能を盛り込み、後々修正箇所が多岐に渡るような大規模な開発において力を発揮します。 また、書籍や記事で見る多くの説明は、そのページ内では理解できても、実際の開発現場の使い方が全くイメージできないなようなものが多いなと感じました。 オブジェクト指向誕生のきっかけ 新たな発明には必ず背景があり、より良いものを生み出そうとする理由があります。オブジェクト指向の理解もまた、背景を知ることで深まると感じました。簡単に誕生のきっかけをまとめてみました。 時代と共にコンピューターの性能が向上し、開発規模が大きくなる。するとソースコードが膨大になり、複雑化することによってバグが多くなるという問題が生まれました。 ・修正したい箇所は一つなのに、他のコードも修正する必要があった ・一つのプログラムの追加や修正が他のプログラムに影響を与えてしまい、バグが発生。 ・少しの機能を変更したいだけなのに修正しなければならない箇所が多い。 ・冗長なコードで読みづらく、新規アサインメンバーが解読できない。 以上のように修正が面倒なことや影響範囲が大きいと言った理由から大規模システムを作るのは難しかったみたいです。 このままでは、ソフトウェア需要に対して供給が追いつかない!! 時間が足りない、、、人手も足りない、、、なんとか解消しなければ、、、 そこで!!! システム開発の複雑化を解消するために作られたのがオブジェクト指向 なわけです! オブジェクト指向とは それではオブジェクト指向とは何か、どのような概念・考え方なのか。 いかに効率よく、わかりやすく、開発ができるか そのために機能を共通化し、コードの重複を減らし、再利用性を高める これを突き詰めた考え方がオブジェクト指向です。 しかし、これでは良くわかりません。概念を知っただけじゃその考え方が実際にどのように使われているのか想像もつきません。それがどれほど重要なのかもさっぱりです。。 そこで、以下の用語を使ってポケモンを例にオブジェクト指向をわかりやすく説明しようと思います!! オブジェクト指向で出てくる用語 ・?クラス……設計図 ・?インスタンス……実体/オブジェクト(モノ) ・?プロパティ……属性/性質 ・?メソッド……機能/処理 ・?継承……クラスからプロパティやメソッドを引き継ぐ ・オーバーライド……上書き ポケモンでオブジェクト指向を考えてみる ポケモンが持つプロパティ(属性)は 「体の色」「大きさ」「形」と考えます。 メソッド(処理)は 「鳴き声を発する」「技を繰り出す」だと考えます。 どれもポケモン一匹ずつがそれぞれ持つものであり、異なるものです。 ポケモン図鑑に登録されているポケモンは全部で何種類でしょうか? wikiによると、全部で908種類いるみたいです。。ポケモンすご。。 それではあなたがポケモン開発部隊だったとします。 ーーーーオブジェクト指向じゃない場合ーーーー このポケモンたちそれぞれ"1匹"に対して、 プロパティとして色、形、大きさをセットして、、、 さらに鳴き声を発する機能をつけて、、、 さらにこんな鳴き声にセットして、、、 技を繰り出す機能つけて、、、 こんな技を使えるようにセットして、、、完了っと!!! さっ!この工程であと907種類作るぞぉーー!!!(狂気 想像しただけで涙が出ます。ここは地獄でしょうか。あぁ、アニメがみたい。ゲームがしたい。実家の味噌汁を啜りたい。。。 それではオブジェクト指向の場合どのようになるのか。 ーーーーオブジェクト指向の場合ーーーー 全ポケモンが共通しているプロパティ(色、形、大きさ)・メソッド(鳴き声を発する、技を出す)を変更を仮定して予め記述したポケモンクラス(ポケモンの設計図)を最初に作成する。 そのポケモンクラスを継承し、クラスにセットされた共通のプロパティとメソッドをその1匹独自のものに上書きしていく(オーバーライドする)だけ。 例えば、「ピカチュウ」というインスタンスを作ろうとした時、 元々ポケモンクラスから与えられた「色」プロパティに対して「黄色」を、 「形」プロパティに対して「ねずみ」を、 「大きさ」プロパティに対して「40cm」を、 「鳴き声を発する」メソッドに対して「ピッピカチュ〜♪」を、 「技を繰り出す」メソッドに対して「10まんボルト」をはめ込みます。 このようにしてクラスから与えられた情報に対して独自の見た目や技をはめ込むようにして唯一のポケモン(インスタンス/実体)を作れることができ、全てを0から書く必要がなくなります。 つまり、予めクラスに書いておいた、「技を繰り出すメソッドの定義や鳴き声をはめ込むための定義」等は改めて書く必要はありません。どんな技かを繰り出すのかをセットするだけです。 修正箇所が見つかった場合も同様の考え方ができます。 一匹のポケモン(インスタンス)に修正箇所が見つかった場合、独立したそのポケモンのプロパティやメソッドを修正すれば良いだけで、その他のポケモン(別のインスタンス)に修正を加える必要はありません。 つまり、修正ポイントを見つけやすく、修正による他のコードへの影響も少なく、修正箇所も自然と少なくなります。 さいごに 以上で、「オブジェクト指向とは何か、どういう概念なのか。」で述べた いかに効率よく、わかりやすく、開発ができるか 機能を共通化することによって、コードの重複を減らし、再利用性を高めている ということを突き詰めた考え方である。 と説明したのが少しは腑に落ちるのではないかと思います。 私自身まだまだ理解が乏しい駆け出しの身なので、間違えている箇所等ありましたらご指摘いただけると幸いです! 最後まで読んでいただきありがとうございました!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む