<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>プログラミング | バスにっき</title>
	<atom:link href="https://takabus.com/category/program/feed/" rel="self" type="application/rss+xml" />
	<link>https://takabus.com</link>
	<description>バスに関するニュース・マメ知識を紹介しています</description>
	<lastBuildDate>Tue, 14 Oct 2025 12:13:44 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.4.3</generator>

<image>
	<url>https://takabus.com/wp-content/uploads/2022/08/cropped-takabusサイトロゴスクエア余白なし-1-32x32.png</url>
	<title>プログラミング | バスにっき</title>
	<link>https://takabus.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Strapiでさくっとバックエンドをつくってみた</title>
		<link>https://takabus.com/strapi/</link>
					<comments>https://takabus.com/strapi/#respond</comments>
		
		<dc:creator><![CDATA[takabus]]></dc:creator>
		<pubDate>Thu, 16 Sep 2021 13:14:31 +0000</pubDate>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[Strapi]]></category>
		<guid isPermaLink="false">https://takabus.com/?p=5131</guid>

					<description><![CDATA[ヘッドレスCMSのStrapiをつかって、お手軽にバックエンドをつくってみました。インストールからコンテンツ作成まで、一通りの流れを紹介しておきます。]]></description>
										<content:encoded><![CDATA[
<p>ヘッドレスCMSのStrapiをつかって、お手軽にバックエンドをつくってみました。</p>




<a rel="noopener" href="https://strapi.io/" title="Strapi - Open source Node.js Headless CMS 🚀" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img decoding="async" src="https://delicate-dawn-ac25646e6d.media.strapiapp.com/HP_meta_b32f546a40.png" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="90" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">Strapi - Open source Node.js Headless CMS 🚀</div><div class="blogcard-snippet external-blogcard-snippet">Strapi is the next-gen headless CMS, open-source, JavaScript/TypeScript, enabling content-rich experiences to be created...</div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img decoding="async" src="https://www.google.com/s2/favicons?domain=https://strapi.io/" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">strapi.io</div></div></div></div></a>



<div class="wp-block-cocoon-blocks-tab-box-1 blank-box bb-tab bb-check block-box has-border-color has-amber-border-color">
<p><span class="bold-red"><span class="marker-under">Strapiで制作したサイト「バスずかん」を公開しています。</span></span></p>




<a href="https://takabus.com/buszukan/" title="バスずかん" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img decoding="async" src="https://takabus.com/buszukan/ogp.jpg" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="90" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">バスずかん</div><div class="blogcard-snippet external-blogcard-snippet">バスの写真をたくさん掲載！バスずかんでは仙台を中心としたバスの写真を掲載しています。バスにっきとあわせてごらんください。</div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://takabus.com/buszukan/" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">takabus.com</div></div></div></div></a>



<p>フロントエンドには<strong><span class="has-inline-color has-green-color">Nuxt.js</span></strong>を採用し、静的サイトジェネレーター（SSG）モードで完全静的サイトとして公開しています。ぜひご覧ください！</p>
</div>



<h2 class="wp-block-heading">strapiとは？</h2>



<p>StrapiはヘッドレスCMSのひとつです。</p>



<p>ヘッドレスCMSとは、フロントエンドを持たないCMS（コンテンツ管理システム）のことです。WordPressと同じように管理UIも有していますが、HTMLを返す代わりにJSONでデータを返してくれます。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="576" src="https://takabus.com/wp-content/uploads/2021/09/Fnキーで明るさ調整を可能にするドライバ-1-1024x576.png" alt="" class="wp-image-5175" srcset="https://takabus.com/wp-content/uploads/2021/09/Fnキーで明るさ調整を可能にするドライバ-1-1024x576.png 1024w, https://takabus.com/wp-content/uploads/2021/09/Fnキーで明るさ調整を可能にするドライバ-1-300x169.png 300w, https://takabus.com/wp-content/uploads/2021/09/Fnキーで明るさ調整を可能にするドライバ-1-768x432.png 768w, https://takabus.com/wp-content/uploads/2021/09/Fnキーで明るさ調整を可能にするドライバ-1-1536x864.png 1536w, https://takabus.com/wp-content/uploads/2021/09/Fnキーで明るさ調整を可能にするドライバ-1-120x68.png 120w, https://takabus.com/wp-content/uploads/2021/09/Fnキーで明るさ調整を可能にするドライバ-1-160x90.png 160w, https://takabus.com/wp-content/uploads/2021/09/Fnキーで明るさ調整を可能にするドライバ-1-320x180.png 320w, https://takabus.com/wp-content/uploads/2021/09/Fnキーで明るさ調整を可能にするドライバ-1.png 1920w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>WordPressとは異なり、別途フロントエンドも用意しなければなりませんが、その分柔軟性が増すというメリットがあります。</p>



<p>また、最近では、Nuxt.jsやReactなど、優秀なフロントエンドフレームワークがたくさん開発されています。これらのフレームワークを使うと、非常に効率よく開発をすすめることができます。昨今のWeb業界では、フロントエンドとバックエンドを分けて開発することが主流となっており、バックエンドをかんたんに開発する手法としてヘッドレスCMSが注目されているのです。</p>



<h2 class="wp-block-heading">npmでインストール！</h2>



<p>インストールはnpmで行うことができます。</p>



<pre class="wp-block-code"><code>npx create-strapi-app my-project --quickstart</code></pre>



<p>インストール完了後、管理者アカウントの作成ページが表示されるので、指示に従ってパスワードを設定します。</p>



<figure class="wp-block-image"><img decoding="async" src="https://strapi.io/documentation/assets/img/qsg-starters-part1-01-register.3f64017d.png" alt=""/></figure>



<p>メールアドレスのチェックは行われないので、メールアドレスと氏名については適当でOKです。</p>



<p>とくにトラブルなく構築することができました！</p>



<h2 class="wp-block-heading">コンテンツタイプを作成する</h2>



<p><span class="marker-animation">まずはコンテンツタイプを作成しましょう。</span></p>



<p><strong><span class="bold-red">コンテンツタイプ</span></strong>とは、データベースでいうところのテーブルにあたるものです。どんなフィールド（カラム）を用意するのか、あらかじめ設定しておきます。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="514" height="402" src="https://takabus.com/wp-content/uploads/2021/09/image-7.png" alt="" class="wp-image-5132" srcset="https://takabus.com/wp-content/uploads/2021/09/image-7.png 514w, https://takabus.com/wp-content/uploads/2021/09/image-7-300x235.png 300w" sizes="(max-width: 514px) 100vw, 514px" /></figure>



<p><strong>DIsplay name</strong>にコンテンツの名前を入力します。データベースでいうところのテーブル名に該当するものです。ブログサイトであれば、postsなどを指定することになりますね。APIにアクセスする場合もこの名前を使用します。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="933" height="351" src="https://takabus.com/wp-content/uploads/2021/09/image-8.png" alt="" class="wp-image-5133" srcset="https://takabus.com/wp-content/uploads/2021/09/image-8.png 933w, https://takabus.com/wp-content/uploads/2021/09/image-8-300x113.png 300w, https://takabus.com/wp-content/uploads/2021/09/image-8-768x289.png 768w" sizes="(max-width: 933px) 100vw, 933px" /></figure>



<p>つづけて、<span class="marker-animation">フィールドの追加</span>を行います。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="956" height="652" src="https://takabus.com/wp-content/uploads/2021/09/image-9.png" alt="" class="wp-image-5134" srcset="https://takabus.com/wp-content/uploads/2021/09/image-9.png 956w, https://takabus.com/wp-content/uploads/2021/09/image-9-300x205.png 300w, https://takabus.com/wp-content/uploads/2021/09/image-9-768x524.png 768w" sizes="(max-width: 956px) 100vw, 956px" /></figure>



<p>いろんなタイプを指定できるようになっています。</p>



<p><span class="marker-animation">タイトルなど短めの文字列であればText、ブログ本文などエディタを使って編集したい場合はRich Textを選択します。</span></p>



<p>Relationをつかうと、ほかのコンテンツタイプ（モデル）を参照することもできます。</p>



<p>いくつか作成してみます。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="913" height="469" src="https://takabus.com/wp-content/uploads/2021/09/image-10.png" alt="" class="wp-image-5136" srcset="https://takabus.com/wp-content/uploads/2021/09/image-10.png 913w, https://takabus.com/wp-content/uploads/2021/09/image-10-300x154.png 300w, https://takabus.com/wp-content/uploads/2021/09/image-10-768x395.png 768w" sizes="(max-width: 913px) 100vw, 913px" /></figure>



<p>３つほどフィールドを作成してみました。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1001" height="640" src="https://takabus.com/wp-content/uploads/2021/09/image-12.png" alt="" class="wp-image-5138" srcset="https://takabus.com/wp-content/uploads/2021/09/image-12.png 1001w, https://takabus.com/wp-content/uploads/2021/09/image-12-300x192.png 300w, https://takabus.com/wp-content/uploads/2021/09/image-12-768x491.png 768w" sizes="(max-width: 1001px) 100vw, 1001px" /></figure>



<p>最後に忘れずに保存します。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="419" height="261" src="https://takabus.com/wp-content/uploads/2021/09/image-13.png" alt="" class="wp-image-5139" srcset="https://takabus.com/wp-content/uploads/2021/09/image-13.png 419w, https://takabus.com/wp-content/uploads/2021/09/image-13-300x187.png 300w" sizes="(max-width: 419px) 100vw, 419px" /></figure>



<p>Saveをクリックすると、strapiがリスタートし、コンテンツタイプが作成されます。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1001" height="640" src="https://takabus.com/wp-content/uploads/2021/09/image-14.png" alt="" class="wp-image-5140" srcset="https://takabus.com/wp-content/uploads/2021/09/image-14.png 1001w, https://takabus.com/wp-content/uploads/2021/09/image-14-300x192.png 300w, https://takabus.com/wp-content/uploads/2021/09/image-14-768x491.png 768w" sizes="(max-width: 1001px) 100vw, 1001px" /></figure>



<p>無事作成できたようです。</p>



<p>なお、これらの設定はstrapiのディレクトリにあるapiディレクトリにJSONファイルとして保存されています。jsonファイルを直接編集しても設定することができます。</p>



<h2 class="wp-block-heading">コンテンツを作成する</h2>



<p><strong><span class="marker-animation">それでは</span><span class="marker-animation">、</span><span class="marker-animation">コンテンツを作成してみます。</span></strong></p>



<p>Strapiではコンテンツの作成もGUIで行うことができます。WordPressのように手軽に利用できますし、開発者側としても自前で管理UIを作成しなくて良いので、大変便利です。</p>



<p>コンテンツのページに飛び、追加ボタンをクリックします。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="742" height="304" src="https://takabus.com/wp-content/uploads/2021/09/image-15.png" alt="" class="wp-image-5141" srcset="https://takabus.com/wp-content/uploads/2021/09/image-15.png 742w, https://takabus.com/wp-content/uploads/2021/09/image-15-300x123.png 300w" sizes="(max-width: 742px) 100vw, 742px" /></figure>



<p>すると、コンテンツ作成ページに移ります。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="645" src="https://takabus.com/wp-content/uploads/2021/09/image-16-1024x645.png" alt="" class="wp-image-5142" srcset="https://takabus.com/wp-content/uploads/2021/09/image-16-1024x645.png 1024w, https://takabus.com/wp-content/uploads/2021/09/image-16-300x189.png 300w, https://takabus.com/wp-content/uploads/2021/09/image-16-768x484.png 768w, https://takabus.com/wp-content/uploads/2021/09/image-16.png 1358w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>Rich Textフィールドについては、エディタを使用することができます。WordPressのようなデザインで、かんたんに操作できますね。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="643" src="https://takabus.com/wp-content/uploads/2021/09/image-18-1024x643.png" alt="" class="wp-image-5144" srcset="https://takabus.com/wp-content/uploads/2021/09/image-18-1024x643.png 1024w, https://takabus.com/wp-content/uploads/2021/09/image-18-300x188.png 300w, https://takabus.com/wp-content/uploads/2021/09/image-18-768x482.png 768w, https://takabus.com/wp-content/uploads/2021/09/image-18.png 1125w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>Mediaタイプのフィールドについては、ファイルアップローダーを利用することができます。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="645" src="https://takabus.com/wp-content/uploads/2021/09/image-17-1024x645.png" alt="" class="wp-image-5143" srcset="https://takabus.com/wp-content/uploads/2021/09/image-17-1024x645.png 1024w, https://takabus.com/wp-content/uploads/2021/09/image-17-300x189.png 300w, https://takabus.com/wp-content/uploads/2021/09/image-17-768x484.png 768w, https://takabus.com/wp-content/uploads/2021/09/image-17.png 1358w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>画像ファイルがアップロードされた場合は、自動的にリサイズ版も作成されます。ブログサイトなどでは、記事一覧ページのサムネイルなどのため、小さい画像も必要な場合がありますが、Strapiを使えばそれらの生成も自動的に行なってくれます。EXIFなどのメタデータも自動的に削除してくれるようです。</p>



<p>最後に<span class="bold-red">保存</span>をクリックします。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="266" height="143" src="https://takabus.com/wp-content/uploads/2021/09/image-19.png" alt="" class="wp-image-5145"/></figure>



<p>これで下書き保存されました。</p>



<p>となりにあるPublishをクリックすると、公開になります。Publishもクリックしましょう。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="229" height="77" src="https://takabus.com/wp-content/uploads/2021/09/image-25.png" alt="" class="wp-image-5151"/></figure>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://takabus.com/wp-content/themes/cocoon-master/images/man.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p>保存するだけでは公開はされません。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1023" height="630" src="https://takabus.com/wp-content/uploads/2021/09/image-26.png" alt="" class="wp-image-5152" srcset="https://takabus.com/wp-content/uploads/2021/09/image-26.png 1023w, https://takabus.com/wp-content/uploads/2021/09/image-26-300x185.png 300w, https://takabus.com/wp-content/uploads/2021/09/image-26-768x473.png 768w" sizes="(max-width: 1023px) 100vw, 1023px" /></figure>



<p>Publishをクリックし、このあと行うアクセス権の設定を済ますと、APIから取得できるようになります。</p>
</div></div>



<p>これでコンテンツが作成され、公開されました。</p>



<p>コンテンツの名前は適当に「asdfs」としてしまいましたが、このまま行くことにしましょう(^^;)本当はPostsとかにするべきでしたね。</p>



<h2 class="wp-block-heading">アクセス権を設定する</h2>



<p>ここまででデータを作成することはできています。</p>



<p>しかし、<span class="marker-animation">まだAPIから取得することはできません。</span>APIからデータを取得するには、<span class="bold-red">アクセス許可を設定しておく必要があります。</span></p>



<p>ログイン無しでAPIへアクセスする場合は、Publicロールが適用されます。Publicロールにアクセス許可を設定します。</p>



<p><strong>「設定」＞「ロールと権限」</strong>をクリックします。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="643" src="https://takabus.com/wp-content/uploads/2021/09/image-20-1024x643.png" alt="" class="wp-image-5146" srcset="https://takabus.com/wp-content/uploads/2021/09/image-20-1024x643.png 1024w, https://takabus.com/wp-content/uploads/2021/09/image-20-300x188.png 300w, https://takabus.com/wp-content/uploads/2021/09/image-20-768x482.png 768w, https://takabus.com/wp-content/uploads/2021/09/image-20.png 1125w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>Publicの<strong>編集マーク</strong>をクリック。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="509" height="201" src="https://takabus.com/wp-content/uploads/2021/09/image-21.png" alt="" class="wp-image-5147" srcset="https://takabus.com/wp-content/uploads/2021/09/image-21.png 509w, https://takabus.com/wp-content/uploads/2021/09/image-21-300x118.png 300w" sizes="(max-width: 509px) 100vw, 509px" /></figure>



<p>すると、権限の設定ページが表示されます。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="603" src="https://takabus.com/wp-content/uploads/2021/09/image-22-1024x603.png" alt="" class="wp-image-5148" srcset="https://takabus.com/wp-content/uploads/2021/09/image-22-1024x603.png 1024w, https://takabus.com/wp-content/uploads/2021/09/image-22-300x177.png 300w, https://takabus.com/wp-content/uploads/2021/09/image-22-768x452.png 768w, https://takabus.com/wp-content/uploads/2021/09/image-22.png 1117w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>「権限」パネルに権限のリストがありますので、</p>



<ul><li><strong>count</strong></li><li><strong>find</strong></li><li><strong>findone</strong></li></ul>



<p>を許可しておきましょう。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="633" height="337" src="https://takabus.com/wp-content/uploads/2021/09/image-23.png" alt="" class="wp-image-5149" srcset="https://takabus.com/wp-content/uploads/2021/09/image-23.png 633w, https://takabus.com/wp-content/uploads/2021/09/image-23-300x160.png 300w" sizes="(max-width: 633px) 100vw, 633px" /></figure>



<p>選択できる権限については、以下のようになっています。</p>



<ul><li><strong>count<br></strong>/モデルの複数形(postsなど)/countにアクセスすると、件数を取得できます。</li><li><strong>findone</strong><br>/モデルの複数形(postsなど)/idにアクセスすると、IDを指定してコンテンツを取得できます。</li><li><strong>find</strong><br>/モデルの複数形(postsなど)で全件取得できます。</li><li><strong>create</strong>・<strong>delete</strong>・<strong>update</strong><br>コンテンツの作成・削除・アップロードを許可します。</li></ul>



<p>通常は<span class="bold-red">count,findone,find</span>の３つを有効にしておけばいいでしょう。</p>



<p>終わったら保存をクリックします。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="216" height="64" src="https://takabus.com/wp-content/uploads/2021/09/image-24.png" alt="" class="wp-image-5150"/></figure>



<h2 class="wp-block-heading">APIで投稿を取得してみる</h2>



<p>それではstrapiのAPIをつかって、投稿を取得してみましょう。</p>



<p>コンテンツを取得するには、GETメソッドで次のようにアクセスします。</p>



<pre class="wp-block-code"><code>http:&#47;&#47;127.0.0.1:ポート番号/asdfses</code></pre>



<p>ホスト名につづいて、取得したいモデルの複数形をつづけます。現在はモデル名をasdfsにしていたので、その複数形のasdfsesを指定すれば、コンテンツを取得できます。名前がPostなら、postsで取得できます。</p>



<p>ポート番号はstrapi起動時のシェルに表示されています。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="654" height="316" src="https://takabus.com/wp-content/uploads/2021/09/image-29.png" alt="" class="wp-image-5156" srcset="https://takabus.com/wp-content/uploads/2021/09/image-29.png 654w, https://takabus.com/wp-content/uploads/2021/09/image-29-300x145.png 300w" sizes="(max-width: 654px) 100vw, 654px" /></figure>



<p>Postmanを使って、APIへリクエストを投げてみましょう。Postmanがない方はブラウザで直接アクセスしてもかまいません。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1023" height="807" src="https://takabus.com/wp-content/uploads/2021/09/image-27.png" alt="" class="wp-image-5153" srcset="https://takabus.com/wp-content/uploads/2021/09/image-27.png 1023w, https://takabus.com/wp-content/uploads/2021/09/image-27-300x237.png 300w, https://takabus.com/wp-content/uploads/2021/09/image-27-768x606.png 768w" sizes="(max-width: 1023px) 100vw, 1023px" /></figure>



<p>取得できました！</p>



<p>JSON全体は次のようになっていました。</p>



<pre class="wp-block-code"><code>&#91;
    {
        "id": 1,
        "hoge": "タイトル",
        "blog": "本文です。",
        "published_at": "2021-09-11T11:50:07.320Z",
        "created_at": "2021-09-11T11:37:15.896Z",
        "updated_at": "2021-09-11T11:50:07.353Z",
        "picture": &#91;
            {
                "id": 2,
                "name": "SAMPLE-sm.jpg",
                "alternativeText": "",
                "caption": "",
                "width": 1024,
                "height": 683,
                "formats": {
                    "thumbnail": {
                        "name": "thumbnail_SAMPLE-sm.jpg",
                        "hash": "thumbnail_SAMPLE_sm_a409713b7d",
                        "ext": ".jpg",
                        "mime": "image/jpeg",
                        "width": 234,
                        "height": 156,
                        "size": 9.59,
                        "path": null,
                        "url": "/uploads/thumbnail_SAMPLE_sm_a409713b7d.jpg"
                    },
                    "large": {
                        "name": "large_SAMPLE-sm.jpg",
                        "hash": "large_SAMPLE_sm_a409713b7d",
                        "ext": ".jpg",
                        "mime": "image/jpeg",
                        "width": 1000,
                        "height": 667,
                        "size": 129.31,
                        "path": null,
                        "url": "/uploads/large_SAMPLE_sm_a409713b7d.jpg"
                    },
                    "medium": {
                        "name": "medium_SAMPLE-sm.jpg",
                        "hash": "medium_SAMPLE_sm_a409713b7d",
                        "ext": ".jpg",
                        "mime": "image/jpeg",
                        "width": 750,
                        "height": 500,
                        "size": 78.26,
                        "path": null,
                        "url": "/uploads/medium_SAMPLE_sm_a409713b7d.jpg"
                    },
                    "small": {
                        "name": "small_SAMPLE-sm.jpg",
                        "hash": "small_SAMPLE_sm_a409713b7d",
                        "ext": ".jpg",
                        "mime": "image/jpeg",
                        "width": 500,
                        "height": 333,
                        "size": 36.48,
                        "path": null,
                        "url": "/uploads/small_SAMPLE_sm_a409713b7d.jpg"
                    }
                },
                "hash": "SAMPLE_sm_a409713b7d",
                "ext": ".jpg",
                "mime": "image/jpeg",
                "size": 131.9,
                "url": "/uploads/SAMPLE_sm_a409713b7d.jpg",
                "previewUrl": null,
                "provider": "local",
                "provider_metadata": null,
                "created_at": "2021-09-11T11:35:09.055Z",
                "updated_at": "2021-09-11T11:35:09.079Z"
            }
        ]
    }
]</code></pre>



<p>きちんとデータが取得できていますね。</p>



<p>mediaフィールド（今回はpictureという名前にしました）を確認すると、ちゃんとリサイズ版も生成されていることがわかります。</p>



<p>表示されているURLをAPIにリクエストすると、ファイルも取得することができます。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="751" height="530" src="https://takabus.com/wp-content/uploads/2021/09/image-30.png" alt="" class="wp-image-5157" srcset="https://takabus.com/wp-content/uploads/2021/09/image-30.png 751w, https://takabus.com/wp-content/uploads/2021/09/image-30-300x212.png 300w" sizes="(max-width: 751px) 100vw, 751px" /></figure>



<p>なかなか便利ですね！Laravelで実装するなら、ファイルの保存やリサイズのロジックまで組まなければならないわけですが、それらをすべて割愛することができます。かなりの負担軽減です！</p>



<p>あとはVue.jsやNuxt.js、ReactなどのフロントエンドからAPIを利用してやれば、あっというまにサイトを作成することができます。</p>



<h2 class="wp-block-heading">npmコマンドで操作できる</h2>



<p>strapiはnpmコマンドからほとんどの操作を行うことができます。</p>



<p>起動するには、コンソール（WindowsならPowerShell）でstrapiのディレクトリを開き、</p>



<pre class="wp-block-code"><code>npm run strapi dev</code></pre>



<p>を実行すればOKです。</p>



<p>Shiftを押しながら、strapiのフォルダを右クリックし、「PowerShellで開く」をクリックし、さきほどのコマンドを入力します。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="446" height="295" src="https://takabus.com/wp-content/uploads/2021/09/image-31.png" alt="" class="wp-image-5158" srcset="https://takabus.com/wp-content/uploads/2021/09/image-31.png 446w, https://takabus.com/wp-content/uploads/2021/09/image-31-300x198.png 300w" sizes="(max-width: 446px) 100vw, 446px" /></figure>



<p>起動が完了すると、管理ページとAPIのURLがシェルに表示されます。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="653" height="314" src="https://takabus.com/wp-content/uploads/2021/09/image-28.png" alt="" class="wp-image-5155" srcset="https://takabus.com/wp-content/uploads/2021/09/image-28.png 653w, https://takabus.com/wp-content/uploads/2021/09/image-28-300x144.png 300w" sizes="(max-width: 653px) 100vw, 653px" /></figure>



<p>シェルでCtrl＋Cを押せば、終了することができます。</p>



<p>本番環境では<code>npm run strapi</code>と入力し、実行します。この場合は、プラグインのインストールや重要な設定の変更などはできなくなります。</p>



<h2 class="wp-block-heading">予想以上にかんたん！UIは要改良！</h2>



<p>昨今流行りの<span class="bold-red">HeadlessCMS</span>。</p>



<p>今回はじめて使ってみましたが、予想以上にかんたんで驚きました。</p>



<p>当記事ではWebUIを使用した方法を紹介しましたが、<span class="bold-red"><span class="marker-under">ソースコードを書き換えて、機能拡張を行うこともできます。</span></span></p>



<p>ソースはMVCモデルに基づいた設計になっているため、カスタマイズ性も良好です。WordPres開発だと独自の関数をたくさん覚えなければなりませんが、Strapiではそういったこともなく、独自のルーティングやコントローラーをかんたんに追加することができます。</p>



<p><span class="bold-blue"><span class="marker-under-blue">デメリットを挙げるとすると、UIの弱さでしょうか。</span></span>せっかくコンテンツページにチェックボックスがあるのに、一括編集に対応していなかったり、リレーションフィールドのサジェスト機能が不安定だったりと、まだまだ改善の余地はあるのかなあと思います。エディタも基本的なタグしか対応していないうえ、リアルタイムプレビューにも対応していないため、WordPressに比べると使い勝手はよくありませんでした。</p>



<p>とはいえ、静的Webサイトにニュースリリースを追加したい場合や、基本のプロジェクトにちょっとした投稿機能を追加したいようなニーズであれば、Strapiで十分そうです。</p>



<p>今後の開発に乞うご期待です！</p>
]]></content:encoded>
					
					<wfw:commentRss>https://takabus.com/strapi/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【Laravel】外部キーで引っかかったらここをチェック！</title>
		<link>https://takabus.com/post-5010/</link>
					<comments>https://takabus.com/post-5010/#respond</comments>
		
		<dc:creator><![CDATA[takabus]]></dc:creator>
		<pubDate>Mon, 06 Sep 2021 06:22:05 +0000</pubDate>
				<category><![CDATA[Laravel]]></category>
		<guid isPermaLink="false">https://takabus.com/?p=5010</guid>

					<description><![CDATA[Laravelのマイグレーションが外部キー制約で引っかかる場合があります。こういったときのチェックポイントをまとめておきます。マイグレーションの順番は意外な盲点!!]]></description>
										<content:encoded><![CDATA[
<p>Laravelのマイグレーションが外部キー制約で引っかかる場合があります。こういったときのチェックポイントをまとめておきます。<span class="marker-animation"><span class="bold-red">マイグレーションの順番は意外な盲点なので、</span></span><span class="marker-animation"><span class="bold-red">忘れず</span></span><span class="marker-animation"><span class="bold-red">に</span></span><span class="marker-animation"><span class="bold-red">チェックしておきましょう！</span></span></p>



<h2 class="wp-block-heading">カラム名はあってる？</h2>



<p>最初にマイグレーションのカラム名をチェックです。</p>



<pre class="wp-block-code"><code>// 外部参照するテーブル
Schema::create('items', function (Blueprint $table) {
    $table-&gt;bigIncrements('id');
    $table-&gt;unsignedBigInteger('master_id')-&gt;comment("マスターのID")-&gt;nullable();
    $table-&gt;foreign('<span class="bold-red">master_id</span>')-&gt;references('<span class="bold-red">id</span>')-&gt;on('<span class="bold-red">masters</span>');
});


// 外部参照先（参照を受けるほうの）テーブルのスキーマ
Schema::create('masters', function (Blueprint $table) {
    $table-&gt;bigIncrements('id');
    $table-&gt;string('name')-&gt;comment("名前")-&gt;nullable();
});</code></pre>



<p>テーブル名、カラム名が正しいか確認してください。</p>



<div class="wp-block-cocoon-blocks-icon-box information-box common-icon-box block-box">
<p>モデルについては、マイグレーションとは無関係です。</p>
</div>



<h2 class="wp-block-heading">型はunsignedBigIntegerにする</h2>



<p>IDを外部参照するときは、データ型を<span class="bold-red">unsignedBigInteger</span>にします。</p>



<pre class="wp-block-code"><code>$table-&gt;bigIncrements('id');
//を参照するなら、
$table-&gt;<span class="bold-red">unsignedBigInteger</span>('master_id')
//とする</code></pre>



<p>通常、テーブルのIDカラムはbigIncrementsで自動採番としますが、bigIncrementsを参照したい場合は、unsignedBigIntegerで参照する必要があります。</p>



<h2 class="wp-block-heading">マイグレーションの順番に注意！</h2>



<p>盲点です。<span class="bold-red"><span class="marker-animation">マイグレーションの順番に注意</span></span>です。</p>



<p>マイグレーションはファイル名昇順で実行されるので、<span class="bold-red">参照を受けるテーブルを先に作って置く必要があります。</span></p>



<p>たとえば、以下のようなマイグレーションファイルがあったとします。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="629" height="84" src="https://takabus.com/wp-content/uploads/2021/09/image.png" alt="" class="wp-image-5011" srcset="https://takabus.com/wp-content/uploads/2021/09/image.png 629w, https://takabus.com/wp-content/uploads/2021/09/image-300x40.png 300w" sizes="(max-width: 629px) 100vw, 629px" /></figure>



<p>この場合、question_setsテーブルからquestion_listsテーブルに参照が向けられていると、マイグレーションはうまくいきません。</p>



<p>create_question_sets_tableが実行される時点では、question_listsテーブルは存在しないためです。必ず参照先のテーブルから作成されるように、マイグレーションファイルの名前を変更しておく必要があります。</p>



<p>また、1つのマイグレーションファイルで複数テーブルを作成する場合も要注意です。</p>



<pre class="wp-block-code"><code>// 外部参照するテーブルをつくる
Schema::create('items', function (Blueprint $table) {
    $table-&gt;bigIncrements('id');
    $table-&gt;unsignedBigInteger('master_id')-&gt;comment("マスターのID")-&gt;nullable();
    $table-&gt;foreign('master_id')-&gt;references('id')-&gt;on('masters');
});

// →mastersテーブルがまだつくられていないので、失敗する

Schema::create('masters', function (Blueprint $table) {
    $table-&gt;bigIncrements('id');
    $table-&gt;string('name')-&gt;comment("名前")-&gt;nullable();
});</code></pre>



<p>テーブルAからテーブルBを参照するなら、テーブルBのマイグレーションが先に実行されるようにします。</p>



<pre class="wp-block-code"><code>// 外部参照先（参照を受けるほうの）テーブル
Schema::create('masters', function (Blueprint $table) {
    $table-&gt;bigIncrements('id');
    $table-&gt;string('name')-&gt;comment("名前")-&gt;nullable();
});

// 外部参照するテーブル
Schema::create('items', function (Blueprint $table) {
    $table-&gt;bigIncrements('id');
    $table-&gt;unsignedBigInteger('master_id')-&gt;comment("マスターのID")-&gt;nullable();
    $table-&gt;foreign('master_id')-&gt;references('id')-&gt;on('masters');
});

// →mastersテーブルがつくられているので、成功する</code></pre>



<h2 class="wp-block-heading">まとめ</h2>



<p>個人的によくひっかかると思われるポイントは以上の3点です。</p>



<p>とくにマイグレーションの順番は忘れがちなポイントですので、外部キー制約でエラーとなった場合は、確認してみることをおすすめします。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://takabus.com/post-5010/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【C++】MFCの実行ファイルのアイコンを変更するには？</title>
		<link>https://takabus.com/mfc-icon/</link>
					<comments>https://takabus.com/mfc-icon/#respond</comments>
		
		<dc:creator><![CDATA[takabus]]></dc:creator>
		<pubDate>Wed, 12 May 2021 01:30:03 +0000</pubDate>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Visual C++]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[アイコン]]></category>
		<guid isPermaLink="false">https://takabus.com/?p=4147</guid>

					<description><![CDATA[MFCやVisual C++のアプリケーションアイコンを変更する方法を紹介します。アイコンが変更されない場合の対処法も紹介しています。]]></description>
										<content:encoded><![CDATA[
<p>　Visual C++でアプリケーションを開発したとき、<strong><span class="marker-animation">タスクバーに表示されるアイコンを変更したい場合があります。</span></strong></p>



<p>　しかし、C#と異なり、VisualC++ではプロジェクトのプロパティからかんたんに変更することはできません。ヘッダーファイルなどの編集が必要になります。</p>



<p>　当記事では、MFCアプリケーションやVisual C++のアプリケーションアイコン（実行ファイルのアイコン）を任意のアイコンに変更する方法を紹介します。</p>



<div class="wp-block-cocoon-blocks-icon-box common-icon-box block-box information-box">
<p>アイコンを変更しても、表示が変化しないときの対処法も紹介しています。</p>
</div>



<h2 class="wp-block-heading">MFCアプリケーションのアイコンはどう決められている？</h2>



<p>　C#やVBといった.NETでは、Visual Studioでプロジェクトのプロパティを開くと、GUIから使用するアイコンを設定できます。対して、MFCなどのVisual Cではこういったことができません。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="645" src="https://takabus.com/wp-content/uploads/2021/04/image-44.png" alt="" class="wp-image-4148" srcset="https://takabus.com/wp-content/uploads/2021/04/image-44.png 1024w, https://takabus.com/wp-content/uploads/2021/04/image-44-300x189.png 300w, https://takabus.com/wp-content/uploads/2021/04/image-44-768x484.png 768w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">C#やVBでは、Visual Studioからアイコンを設定できるが、MFCではできない。</figcaption></figure>



<p>　ではどのように変更するかというと、<span class="bold"><span class="marker-animation">アイコンリソースのIDを変更します。</span></span></p>



<p>　各リソースには、ヘッダファイルにより定義されるIDが割り当てられています。そして、最小のIDが設定されたアイコンが、実行ファイルのアイコンとして使用されるようになっています。よって、<strong><span class="bold-red">実行ファイルのアイコンに使用したいアイコンリソースのIDを、アイコンリソースのなかで最も小さな値に変更してやることで、任意のアイコンをexeファイルに表示させることができます。 </span></strong></p>



<div class="wp-block-cocoon-blocks-tab-box-1 blank-box bb-tab bb-tips block-box has-border-color has-amber-border-color">
<p><strong><span class="marker">アイコンはどのように保存されているの？</span></strong></p>



<p>そもそもアプリケーションの実行ファイルなどのアイコンは、どのようにして表示されているのでしょうか。</p>



<p>exe形式は一般に実行ファイルとして知られていますが、もう一つ重要な側面として、アーカイブ形式であることが挙げられます。アーカイブとは、複数のファイルを一つのファイルに集約することをいいますが、exeファイルもこのアーカイブ形式の一つで、<strong>アイコンはexeファイルの中にアーカイブされて格納されています。</strong>エクスプローラーで表示されるときに、アーカイブされているアイコンが表示されるという仕組みです。</p>



<p>Lhaplusなどのソフトウェアを用いると、次の画像のようにアーカイブされたファイルを取り出すことができます。</p>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="681" height="538" src="https://takabus.com/wp-content/uploads/2021/04/image-45.png" alt="" class="wp-image-4149" srcset="https://takabus.com/wp-content/uploads/2021/04/image-45.png 681w, https://takabus.com/wp-content/uploads/2021/04/image-45-300x237.png 300w" sizes="(max-width: 681px) 100vw, 681px" /><figcaption class="wp-element-caption">Lhaplusを使って、ビルド済みのexeを強制的に解凍してみたときのようす。解凍先のフォルダにたくさんのアイコンが含まれていることがわかります。</figcaption></figure>
</div>



<h2 class="wp-block-heading">MFCアプリケーションのアイコンを変更するには？</h2>



<p>それでは、具体的なやり方を紹介します。</p>



<h3 class="wp-block-heading">【手順1】アイコンファイルをリソースに追加する</h3>



<p>リソースビューから既存のアイコンファイルをインポートします。</p>



<p>[ソリューションエクスプローラー]から、<strong>アプリケーションのリソースファイルをダブルクリック</strong>します。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="297" height="324" src="https://takabus.com/wp-content/uploads/2021/04/image-46.png" alt="" class="wp-image-4150" srcset="https://takabus.com/wp-content/uploads/2021/04/image-46.png 297w, https://takabus.com/wp-content/uploads/2021/04/image-46-275x300.png 275w" sizes="(max-width: 297px) 100vw, 297px" /></figure>



<p>すると、[リソースビュー]が立ち上がるので、<strong>「Icon」を右クリック</strong>し、<strong>「リソースの追加」</strong>をクリックします。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="508" height="400" src="https://takabus.com/wp-content/uploads/2021/04/image-47.png" alt="" class="wp-image-4151" srcset="https://takabus.com/wp-content/uploads/2021/04/image-47.png 508w, https://takabus.com/wp-content/uploads/2021/04/image-47-300x236.png 300w" sizes="(max-width: 508px) 100vw, 508px" /></figure>



<p>[リソースの追加]ダイアログが開くので、<strong>「インポート」</strong>をクリック。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="409" height="302" src="https://takabus.com/wp-content/uploads/2021/04/image-48.png" alt="" class="wp-image-4152" srcset="https://takabus.com/wp-content/uploads/2021/04/image-48.png 409w, https://takabus.com/wp-content/uploads/2021/04/image-48-300x222.png 300w" sizes="(max-width: 409px) 100vw, 409px" /></figure>



<p>出てきたダイアログから、作成しておいたアイコンファイル（.ico）を選択します。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="669" height="473" src="https://takabus.com/wp-content/uploads/2021/04/image-49.png" alt="" class="wp-image-4153" srcset="https://takabus.com/wp-content/uploads/2021/04/image-49.png 669w, https://takabus.com/wp-content/uploads/2021/04/image-49-300x212.png 300w" sizes="(max-width: 669px) 100vw, 669px" /></figure>



<p>すると、こんな感じでアイコンファイルがリソースに追加されます。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="938" height="728" src="https://takabus.com/wp-content/uploads/2021/04/image-50.png" alt="" class="wp-image-4154" srcset="https://takabus.com/wp-content/uploads/2021/04/image-50.png 938w, https://takabus.com/wp-content/uploads/2021/04/image-50-300x233.png 300w, https://takabus.com/wp-content/uploads/2021/04/image-50-768x596.png 768w" sizes="(max-width: 938px) 100vw, 938px" /><figcaption class="wp-element-caption">Visual Studioでは[リソースビュー]を使うと、exeに含まれているリソースを確認することができます。アイコンファイルの場合は、ダブルクリックでエディタを開くことも可能です。</figcaption></figure>



<h3 class="wp-block-heading">【手順2】Resource.hを開く</h3>



<p>[ヘッダーファイル]フォルダから、Resource.hを開きます。</p>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="296" height="322" src="https://takabus.com/wp-content/uploads/2021/04/image-51.png" alt="" class="wp-image-4155" srcset="https://takabus.com/wp-content/uploads/2021/04/image-51.png 296w, https://takabus.com/wp-content/uploads/2021/04/image-51-276x300.png 276w" sizes="(max-width: 296px) 100vw, 296px" /></figure>



<h3 class="wp-block-heading">【手順3】アイコンにしたいリソースのIDを最小に変更する</h3>



<p>Resource.hを開いたら、ICONファイルのIDが定義されている箇所を探します。</p>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="938" height="728" src="https://takabus.com/wp-content/uploads/2021/04/image-53.png" alt="" class="wp-image-4157" srcset="https://takabus.com/wp-content/uploads/2021/04/image-53.png 938w, https://takabus.com/wp-content/uploads/2021/04/image-53-300x233.png 300w, https://takabus.com/wp-content/uploads/2021/04/image-53-768x596.png 768w" sizes="(max-width: 938px) 100vw, 938px" /></figure>



<p>オレンジで囲った部分がアイコンリソースのIDとなります。例として、<strong>「IDI_ICON2」</strong>を実行ファイルのアイコンにしてみましょう。</p>



<p>IDI_ICON2のIDをアイコンリソースのうち最小のIDに設定します。</p>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="587" height="352" src="https://takabus.com/wp-content/uploads/2021/04/image-55.png" alt="" class="wp-image-4159" srcset="https://takabus.com/wp-content/uploads/2021/04/image-55.png 587w, https://takabus.com/wp-content/uploads/2021/04/image-55-300x180.png 300w" sizes="(max-width: 587px) 100vw, 587px" /></figure>



<p>ここでは125を割り当ててみました。ほかのアイコンよりも小さい値にすれば、なんでもOKです。</p>



<p>これでビルドします。</p>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="558" height="468" src="https://takabus.com/wp-content/uploads/2021/04/image-57.png" alt="" class="wp-image-4161" srcset="https://takabus.com/wp-content/uploads/2021/04/image-57.png 558w, https://takabus.com/wp-content/uploads/2021/04/image-57-300x252.png 300w" sizes="(max-width: 558px) 100vw, 558px" /></figure>



<p>ちゃんと変わってますね。</p>



<h2 class="wp-block-heading">アイコンがうまく変わらないときは？</h2>



<p>　今回の方法を試しても、アイコンが変化しなかったという方もいるかもしれません。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-5 sbs-flat sbp-l sbis-cb cf block-box cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://takabus.com/wp-content/themes/cocoon-master/images/ojisan.png" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon has-text-color has-background has-watery-red-color has-white-background-color">
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="403" height="106" src="https://takabus.com/wp-content/uploads/2021/04/image-60.png" alt="ビルドし直したはずなのに、アイコンが変更されない…" class="wp-image-4243" srcset="https://takabus.com/wp-content/uploads/2021/04/image-60.png 403w, https://takabus.com/wp-content/uploads/2021/04/image-60-300x79.png 300w" sizes="(max-width: 403px) 100vw, 403px" /></figure>
</div></div>



<p>　<span class="marker-under">それはおそらく<strong><span class="marker-animation">エクスプローラーのキャッシュが原因です。</span></strong></span></p>



<p>　Windowsエクスプローラーは、アプリケーションのアイコンをキャッシュする機能を持っています。キャッシュが働いていると、正常にアイコンを変更できていても、表示に反映されない場合があります。</p>



<p>　<strong><span class="red">実行ファイルを別のフォルダに移すと、キャッシュがクリアされて、アイコンが再読み込みされます。</span></strong>アイコンが変わらない場合は、<strong><span class="marker-animation"><span class="marker-under">実行ファイル（.exe）を別フォルダに移動させてみましょう。</span></span></strong>この状態でアプリケーションを起動してみて、正しくアイコンが変更されているか確認してみてください。</p>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="601" height="259" src="https://takabus.com/wp-content/uploads/2021/04/image-61.png" alt="" class="wp-image-4244" srcset="https://takabus.com/wp-content/uploads/2021/04/image-61.png 601w, https://takabus.com/wp-content/uploads/2021/04/image-61-300x129.png 300w" sizes="(max-width: 601px) 100vw, 601px" /><figcaption class="wp-element-caption">場所を移動すると、アイコンのキャッシュがクリアされ、変更が適用されているか確認できます。</figcaption></figure>



<p>　注意してほしいのは、この現象は<span class="bold-red">F5キーを押しても解決しません。</span>また、アプリケーションを起動しなおした場合でも、以前のアイコンが表示されてしまいます。必ず別の場所に移動させてから、アイコンを確認するようにしてください。</p>



<h2 class="wp-block-heading">まとめ</h2>



<p>VIsualC++のアイコンを変更する方法について紹介しました。</p>



<p>意外につまづくのは、「うまくいかないときは？」で取り上げたキャッシュの問題かも知れませんね。ちゃんとやったはずなのに、アイコンが変わらないときは、キャッシュのせいではないかと疑ってみることをおすすめします。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://takabus.com/mfc-icon/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【C++】POSTでデータを送信するには？WinINetを使ってPOSTする方法</title>
		<link>https://takabus.com/cpp-wininet/</link>
					<comments>https://takabus.com/cpp-wininet/#respond</comments>
		
		<dc:creator><![CDATA[takabus]]></dc:creator>
		<pubDate>Thu, 25 Mar 2021 01:04:26 +0000</pubDate>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[WinINet]]></category>
		<category><![CDATA[Win32]]></category>
		<category><![CDATA[POST]]></category>
		<category><![CDATA[GET]]></category>
		<guid isPermaLink="false">https://nikki.takabus.com/?p=3958</guid>

					<description><![CDATA[C++（Win32）でPOSTしたいときの方法を紹介します。Win32ではWinINetを使用すると、比較的かんたんにPOSTすることができます。当記事ではWinINetを使用したPOSTの方法をサンプルコードとあわせて紹介していきます。]]></description>
										<content:encoded><![CDATA[
<p>　C++（Win32）でPOSTしたいときの方法を紹介します。Win32ではWinINetを使用すると、比較的かんたんにPOSTすることができます。当記事では、WinINetを使用したPOSTの方法をサンプルコードとあわせて紹介していきます。</p>



<h2 class="wp-block-heading">サンプルコード</h2>



<p>さっそくサンプルコードを公開します。</p>



<p>URL「http://192.168.1.4/test/test.php」に、次のデータをPOSTする例です。</p>



<ul><li><span class="marker-animation">キー「a」値「1234」</span></li><li><span class="marker-animation">キー「b」値「5678」</span></li></ul>



<pre class="wp-block-code"><code>// ConsoleApplication1.cpp : このファイルには 'main' 関数が含まれています。プログラム実行の開始と終了がそこで行われます。
//

#include &lt;iostream&gt;//std::coutなど使うのに必要
#include &lt;tchar.h&gt;//_Tを使うのに必要
#include &lt;windows.h&gt;//wininet.hを使うのに必要
#include &lt;wininet.h&gt;//HTTP通信に必要

//追加の依存ファイルにwininet.libを設定
#pragma comment (lib, "wininet.lib")


int main()
{
	// インターネット接続のハンドルを作成
	HINTERNET hInternet = InternetOpen(
		NULL, //User-Agentに設定したい文字列を指定する
		INTERNET_OPEN_TYPE_PRECONFIG,//接続方法（直接接続・プロキシ使用）を指定する
		NULL,//プロキシサーバーのアドレスを指定する
		NULL,//プロキシサーバー使用時、プロキシを経由させないで直接接続するアドレスを指定する
		0//オプション
	);

	// インターネット接続を確立して、コネクトハンドルを得る
	HINTERNET hConnect = InternetConnect(
		hInternet,
		_T("192.168.1.4"),//サーバーアドレス
		INTERNET_DEFAULT_HTTP_PORT,//ポート番号を指定する
		NULL,//認証ユーザー名を指定する
		NULL,//認証パスワードを指定する
		INTERNET_SERVICE_HTTP,//サービスタイプ(HTTP・FTP)を指定する
		0,//FTP接続時、パッシブモードにするかどうか指定する
		0
	);

	// リクエストを開いて、リクエストハンドルを得る
	HINTERNET hRequest = HttpOpenRequest(
		hConnect,
		_T("POST"),//POSTにする
		_T("/test/test.php"), //ホスト名以下
		_T("HTTP/1.1"),//HTTPプロトコルバージョン
		NULL, NULL, INTERNET_FLAG_RELOAD, 0);

	// ヘッダーを設定する
	wchar_t header&#91;] = L"Content-Type: application/x-www-form-urlencoded; charset=utf-8";//コンテンツタイプをFORMに指定

	//送信データを指定する
	char data&#91;] = "a=1234&amp;b=5678";

	// リクエストを送信する
	BOOL r = HttpSendRequest(
		hRequest,//リクエストハンドルを指定する
		header, //ヘッダーを指定する
		wcslen(header), //ヘッダーのサイズを求めて指定する
		(LPVOID)(data),//送信コンテンツを指定する
		strlen(data) //送信コンテンツのサイズを求めて指定する
	);

	// エラーがあれば表示する
	std::cout &lt;&lt; GetLastError() &lt;&lt; std::endl;

        // ハンドルを閉じる
	InternetCloseHandle(hInternet);
}</code></pre>



<p>実行すると、サーバーに次のようなデータが届きます。</p>



<pre class="wp-block-code"><code>2020-12-10 12:15:08 Array //リクエストヘッダー
(
    &#91;Content-Type] =&gt; application/x-www-form-urlencoded
    &#91;Host] =&gt; 192.168.1.4
    &#91;Content-Length] =&gt; 13
    &#91;Cache-Control] =&gt; no-cache
)

2020-12-10 12:15:08 Array //POSTデータ
(
    &#91;a] =&gt; 1234
    &#91;b] =&gt; 5678
)</code></pre>



<p>きちんとPOSTできていますね。</p>



<p>▼PHPでリクエストヘッダとPOSTされたデータを書き出す方法は、次のページで紹介しています。</p>



<div class="wp-block-cocoon-blocks-blogcard blogcard-type bct-together">

<a href="https://takabus.com/201214-dump-post-data-php/" title="【PHP】POST・GETされたデータとヘッダーをロギングする方法" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="160" height="90" src="https://takabus.com/wp-content/uploads/2021/03/image-160x90.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://takabus.com/wp-content/uploads/2021/03/image-160x90.png 160w, https://takabus.com/wp-content/uploads/2021/03/image-120x68.png 120w, https://takabus.com/wp-content/uploads/2021/03/image-320x180.png 320w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">【PHP】POST・GETされたデータとヘッダーをロギングする方法</div><div class="blogcard-snippet internal-blogcard-snippet">デバッグするときに、POST・GETで送信したデータやリクエストヘッダーを確認したいときがあります。こういったデータをテキストファイルに書き出すPHPコードを掲載しておきます。かんたんにクライアントからのリクエストを把握できるようになるので、とても便利ですよ～</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://takabus.com" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">takabus.com</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2021.01.10</div></div></div></div></a>
<p></p>
</div>



<h2 class="wp-block-heading">解説</h2>



<p>　C#（.NET）なら、WebRequestを使ってかんたんにPOSTできますが、<strong><span class="marker-animation">C++ではWinINetを使用します。</span></strong></p>



<p>　WinINetのほかにWinHTTPというAPIもありますが、通常は使用する必要はありません。WinHTTPのWebクライアントとしての機能は、WinINetに内包されています。よって、クライアントとしてPOSTするだけなら、基本的にWinINetを使用すればOKです。逆に、HTTPサーバーを構築するときは、WinHTTPを使用する必要があります。</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="559" height="336" src="https://takabus.com/wp-content/uploads/2021/03/image-4.png" alt="" class="wp-image-3962" srcset="https://takabus.com/wp-content/uploads/2021/03/image-4.png 559w, https://takabus.com/wp-content/uploads/2021/03/image-4-300x180.png 300w" sizes="(max-width: 559px) 100vw, 559px" /></figure></div>



<p>　次のページにWinINetとWinHTTPの機能比較表が掲載されていますが、利用可能な機能もWinINetのほうが多いです。WinINetなら、HTTPのみならず、FTPも使用することができます。</p>




<a rel="noopener" href="https://docs.microsoft.com/en-us/windows/win32/wininet/wininet-vs-winhttp" title="WinINet vs. WinHTTP - Win32 apps" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img loading="lazy" decoding="async" src="https://learn.microsoft.com/en-us/media/open-graph-image.png" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="90" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">WinINet vs. WinHTTP - Win32 apps</div><div class="blogcard-snippet external-blogcard-snippet">Learn how to choose between WinInet and WinHTTP. Read a comparison of features, and review related topics.</div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://learn.microsoft.com/en-us/windows/win32/wininet/wininet-vs-winhttp" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">learn.microsoft.com</div></div></div></div></a>



<h3 class="wp-block-heading">処理の流れ</h3>



<p>　まず、全体の流れを整理します。</p>



<div class="wp-block-cocoon-blocks-blank-box-1 blank-box block-box has-border-color has-amber-border-color">
<ol><li><strong>InternetOpen・・・初期化</strong></li><li><strong>InternetConnect・・・セッション開始</strong></li><li><strong>HttpOpenRequest・・・リクエスト作成</strong></li><li><strong>HttpSendRequest・・・データの送信</strong></li></ol>
</div>



<p>　最初に<strong>InternetOpen関数</strong>を実行します。</p>



<pre class="wp-block-code"><code>void InternetOpenW(
  LPCWSTR lpszAgent,
  DWORD   dwAccessType,
  LPCWSTR lpszProxy,
  LPCWSTR lpszProxyBypass,
  DWORD   dwFlags
);</code></pre>



<p>　InternetOpen関数を実行することで、WinINetが初期化されます。初期化が完了すると、ハンドルが返されます。以降、ここで得られたハンドルを使用して、処理を行っていきます。</p>



<div class="wp-block-cocoon-blocks-tab-box-1 blank-box bb-tab bb-tips block-box has-border-color has-yellow-border-color">
<p><span class="badge">ギモン</span><strong> <span class="marker-animation">void型なのにHANDLEが返るってどういうこと？</span></strong></p>



<p>C++のvoid型というのは、「型指定なしのポインタ（void*型）」のことを指しています。</p>



<p>HANDLE型も、実体は型指定なしのポインタ（すなわちvoid*型）です。よって、HANDLEを返す関数の返り値はvoid型であるといえます。</p>



<p>C#に慣れていると、「void型＝返り値なし」という認識になりがちですが、C++では何も返さないとは限らないので、注意が必要です。</p>
</div>



<div class="wp-block-cocoon-blocks-tab-box-1 blank-box bb-tab bb-comment block-box has-border-color has-pink-border-color">
<p>Unicode対応版としてビルドした場合、InternetOpen関数をはじめ、ほとんどの関数はワイド文字対応版の関数（末尾に「W」がついている関数）に置き換えられます。（既定ではUnicode対応版としてビルドされます。）よって、<strong><span data-ma_color="#fac0ff" class="marker-animation">InternetOpen関数とInternetOpenW関数は同じものとして考えてもらってかまいません。</span></strong></p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="840" height="564" src="https://takabus.com/wp-content/uploads/2021/03/image-2.png" alt="" class="wp-image-3960" srcset="https://takabus.com/wp-content/uploads/2021/03/image-2.png 840w, https://takabus.com/wp-content/uploads/2021/03/image-2-300x201.png 300w, https://takabus.com/wp-content/uploads/2021/03/image-2-768x516.png 768w, https://takabus.com/wp-content/uploads/2021/03/image-2-272x182.png 272w" sizes="(max-width: 840px) 100vw, 840px" /><figcaption>既定では、ワイド文字対応版の関数が使用されるようになっています。</figcaption></figure>
</div>



<p>　次に<strong><span class="marker-animation">InternetConnect関数</span></strong>を実行します。</p>



<pre class="wp-block-code"><code>void InternetConnectW(
  HINTERNET     hInternet,
  LPCWSTR       lpszServerName,
  INTERNET_PORT nServerPort,
  LPCWSTR       lpszUserName,
  LPCWSTR       lpszPassword,
  DWORD         dwService,
  DWORD         dwFlags,
  DWORD_PTR     dwContext
);</code></pre>



<p>　これにより、サーバーに接続が行われ、セッションが開始されます。</p>



<p>　あとは、HTTPOpenRequest関数とHTTPSendRequest関数により、データをPOSTします。</p>



<pre class="wp-block-code"><code>// リクエストを開いて、リクエストハンドルを得る
HINTERNET hRequest = HttpOpenRequest(
	hConnect,
	_T("POST"),//POSTにする
	_T("/test/test.php"), //ホスト名以下
	_T("HTTP/1.1"),//HTTPプロトコルバージョン
	NULL, NULL, INTERNET_FLAG_RELOAD, 0);

// ヘッダーを設定する
wchar_t header&#91;] = L"Content-Type: application/x-www-form-urlencoded";//コンテンツタイプをFORMに指定

//送信データを指定する
char data&#91;] = "a=1234&amp;b=5678";

// リクエストを送信する
BOOL r = HttpSendRequest(
	hRequest,//リクエストハンドルを指定する
	header, //ヘッダーを指定する
	wcslen(header), //ヘッダーのサイズを求めて指定する
	(LPVOID)(data),//送信コンテンツを指定する
	strlen(data) //送信コンテンツのサイズを求めて指定する
);</code></pre>



<p>　POSTでデータを送信する際には、何らかのMIMEタイプにデータをエンコードする必要があります。jsonなどをはじめ、使用できるMIMEタイプは多岐にわたりますが、今回はformタグを送信する際に使用される「application/x-www-form-urlencoded」を採用します。この場合、送信データは「キー＝値」のペアを&amp;で区切る形でエンコードされますので、送信データもそれに従って定義しておきます。</p>



<pre class="wp-block-code"><code>//送信データを指定する
char data&#91;] = "a=1234&amp;b=5678";</code></pre>




<a rel="noopener" href="https://developer.mozilla.org/ja/docs/Web/HTTP/Methods/POST" title="POST &#12522;&#12463;&#12456;&#12473;&#12488;&#12513;&#12477;&#12483;&#12489; - HTTP | MDN" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img loading="lazy" decoding="async" src="https://s.wordpress.com/mshots/v1/https%3A%2F%2Fdeveloper.mozilla.org%2Fja%2Fdocs%2FWeb%2FHTTP%2FMethods%2FPOST?w=160&#038;h=90" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="90" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">POST &#12522;&#12463;&#12456;&#12473;&#12488;&#12513;&#12477;&#12483;&#12489; - HTTP | MDN</div><div class="blogcard-snippet external-blogcard-snippet">POST は HTTP のメソッドで、サーバーにデータを送信します。リクエストの本体の型は Content-Type ヘッダーで示されます。</div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://developer.mozilla.org/ja/docs/Web/HTTP/Methods/POST" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">developer.mozilla.org</div></div></div></div></a>



<p>　リクエストヘッダーのContent-typeにも、「application/x-www-form-urlencoded」を指定しておきます。これでサーバーは受け取ったデータを適切にパースしてくれるようになります。</p>



<pre class="wp-block-code"><code>// ヘッダーを設定する
wchar_t header&#91;] = L"Content-Type: application/x-www-form-urlencoded";//コンテンツタイプをFORMに指定</code></pre>



<p>　リクエストの送信が完了したら、ハンドルを破棄しましょう。</p>



<pre class="wp-block-code"><code>//ハンドルを閉じる(hRequestなどは同時に閉じられるのでClose不要)
InternetCloseHandle(hInternet);</code></pre>



<p>　当プログラムでは、複数のハンドルが使用されていますが、hInternetハンドルだけ閉じれば十分です。二次的に生成されているhRequestなどのハンドルは、自動的に同時に閉じられます。</p>



<p>　POSTによる送信については以上です。エラーはGetLastError関数で取得できますので、うまくいかないときは追加してみてください。</p>



<h2 class="wp-block-heading">レスポンスを取得するには？</h2>



<p>　POSTした後、サーバーからのレスポンスを取得したいケースもあるでしょう。サーバーからのレスポンスは、<strong>hRequestハンドル</strong>にFileとして格納されています。</p>



<p>　<a href="https://docs.microsoft.com/en-us/windows/win32/api/wininet/nf-wininet-internetreadfile">InternetReadFile関数</a>を使用すると、格納されているレスポンスデータを読み出すことができます。</p>



<h3 class="wp-block-heading">サンプルコード</h3>



<p><code>InternetCloseHandle(hInternet);</code>の前に、次のコードを追加してください。</p>



<pre class="wp-block-code"><code>
//レスポンス取得・表示

char buf&#91;1024] = { 0 };//バッファ
DWORD size = 1024;//1回あたり読み出すサイズ
BOOL bResult;
DWORD lpdwReadLength;

for (;;) {

	//レスポンスを取得する
	bResult = InternetReadFile(hRequest, buf, sizeof(buf), &amp;lpdwReadLength);

	//読み出しサイズ0以下のとき、ループを抜ける
	if (lpdwReadLength &lt;= 0) {
		break;
	}

	//バッファを出力する
	printf("%s", buf);
	//std::cout &lt;&lt; buf;
}

// エラーがあれば表示する
std::cout &lt;&lt; GetLastError() &lt;&lt; std::endl;

//ハンドルを閉じる(hRequestなどは同時に閉じられるのでClose不要)
InternetCloseHandle(hInternet);</code></pre>



<p>これを追加して実行すると、コンソールにレスポンスが出力されます。</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="595" height="374" src="https://takabus.com/wp-content/uploads/2021/03/image-6.png" alt="" class="wp-image-3964" srcset="https://takabus.com/wp-content/uploads/2021/03/image-6.png 595w, https://takabus.com/wp-content/uploads/2021/03/image-6-300x189.png 300w" sizes="(max-width: 595px) 100vw, 595px" /><figcaption>レスポンスを表示。最後の0はGetLastErrorによるもの。</figcaption></figure></div>



<h3 class="wp-block-heading">解説</h3>



<p>　<a href="https://docs.microsoft.com/en-us/windows/win32/api/wininet/nf-wininet-internetreadfile">InternetReadFile関数</a>は、hRequestハンドルの中に格納されているレスポンスボディを読み出します。</p>



<pre class="wp-block-code"><code>BOOLAPI InternetReadFile(
  HINTERNET hFile,
  LPVOID    lpBuffer,
  DWORD     dwNumberOfBytesToRead,
  LPDWORD   lpdwNumberOfBytesRead
);</code></pre>



<p>　第3引数に、1回あたり読み出すバイト数を指定します。読み出されたデータ（文字配列）は、第2引数に出力されます。第2引数に文字型配列（char[]）を指定することで、指定したバイト数だけ、サーバーからのレスポンスを文字列として取り出せるという仕組みです。これをforでループさせて、レスポンス全体を取得します。</p>



<p>　使用する変数は、最初に定義してあります。</p>



<pre class="wp-block-code"><code>char buf&#91;1024] = { 0 };//バッファ
DWORD size = 1024;//1回あたり読み出すサイズ
BOOL bResult;
DWORD lpdwReadLength;</code></pre>



<div class="wp-block-cocoon-blocks-tab-box-1 blank-box bb-tab bb-check block-box has-border-color has-lime-border-color">
<p><strong><span class="marker-under">NULL終端</span></strong></p>



<p>Cでの文字列は、必ずNULLで終わっていなければならないというルールがあります。これを<strong>NULL終端</strong>といいます。</p>



<p>今回、バッファとして使用する配列（buf）は、変数定義の時点でゼロクリアしておきました。<code>buf[1024]={0}</code>とは、次のコードを実行しているのとほぼ同義です。</p>



<pre class="wp-block-code"><code>for (int i = 0; i &lt; 1024; i++) {
	buf&#91;i] = '\0';
}</code></pre>



<p>これをせずに、ただの空配列としてbufを定義してしまうと、bufがレスポンスデータで埋めつくされない場合に問題が出ます。末尾の要素が不定となってしまい、以下のような実行結果になってしまいます。</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="653" height="512" src="https://takabus.com/wp-content/uploads/2021/04/image-39.png" alt="" class="wp-image-4129" srcset="https://takabus.com/wp-content/uploads/2021/04/image-39.png 653w, https://takabus.com/wp-content/uploads/2021/04/image-39-300x235.png 300w" sizes="(max-width: 653px) 100vw, 653px" /><figcaption>NULL終端させないと、末尾におかしなデータが。。。</figcaption></figure></div>



<p>NULL終端に関わる部分は、脆弱性の元となることもあります。次のページに詳しい解説がなされていますので、興味があれば参照してみてください。</p>




<a rel="noopener" href="https://codezine.jp/article/detail/4644" title="文字列はNULL終端させる　――C/C++セキュアコーディング入門（3）" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img loading="lazy" decoding="async" src="https://codezine.jp/static/common/images/czlogo4fb_ogp.png" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="90" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">文字列はNULL終端させる　――C/C++セキュアコーディング入門（3）</div><div class="blogcard-snippet external-blogcard-snippet">文字列操作に関するプログラミングエラーはいくつかありますが、今回は基本的であるが間違いを犯しやすい文字列のNULL終端エラーについて解説します。</div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=http://codezine.jp/article/detail/4644" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">codezine.jp</div></div></div></div></a>
</div>



<h2 class="wp-block-heading">ステータスコードを取得するには？</h2>



<p>　ステータスコードなど、各種情報を取得したいときには<strong>HttpQueryInfo関数</strong>を使用します。</p>



<p><strong>例）ステータスコードを取得する</strong></p>



<pre class="wp-block-code"><code>
//ステータスコード取得
DWORD buf2 = { 0 };
DWORD buf2len = sizeof(buf2);

HttpQueryInfoW(hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &amp;buf2, &amp;buf2len, 0);

printf("%d", buf2);
</code></pre>



<p>　実行すると、ステータスコードが表示されます。</p>



<pre class="wp-block-code"><code>404</code></pre>



<p>　ステータスコード以外にも、HttpQueryInfo関数を使用すると、ヘッダーに含まれる様々な情報を取得することができます。第2引数にパラメーターを指定することで、取得するデータを切り替えることができます。指定できるパラメータは、次のページにまとめられています。</p>




<a rel="noopener" href="https://docs.microsoft.com/en-us/windows/win32/wininet/query-info-flags" title="Query Info Flags (Wininet.h) - Win32 apps" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img loading="lazy" decoding="async" src="https://learn.microsoft.com/en-us/media/open-graph-image.png" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="90" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">Query Info Flags (Wininet.h) - Win32 apps</div><div class="blogcard-snippet external-blogcard-snippet">The following lists contain the attributes and modifiers used by HttpQueryInfo and QueryInfo.</div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://learn.microsoft.com/en-us/windows/win32/wininet/query-info-flags" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">learn.microsoft.com</div></div></div></div></a>



<h2 class="wp-block-heading">日本語のデータを送るには？</h2>



<p>　基本的にこのままでOKです。data変数に日本語を追加してもらえれば、日本語も送れるはずです。</p>



<pre class="wp-block-preformatted">char data[] = "a=1234&amp;b=5678&amp;あ=あいうえお";</pre>



<p>　実際にやってみたところ、日本語も送信することができました。</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="406" height="198" src="https://takabus.com/wp-content/uploads/2021/03/image-1.png" alt="" class="wp-image-3959" srcset="https://takabus.com/wp-content/uploads/2021/03/image-1.png 406w, https://takabus.com/wp-content/uploads/2021/03/image-1-300x146.png 300w" sizes="(max-width: 406px) 100vw, 406px" /><figcaption>日本語も送信できました。取得方法は<a href="https://takabus.com/201214-dump-post-data-php/" data-type="post" data-id="3944">こちら</a></figcaption></figure></div>



<div class="wp-block-cocoon-blocks-icon-box information-box common-icon-box block-box">
<p>ただし、環境によっては、文字コードの変換などが必要となる可能性があります。 </p>
</div>



<h2 class="wp-block-heading">WinINetのオプションを活用する</h2>



<p>　WinINetには、さまざまなオプションが用意されています。オプションを設定するには<strong>InernetSetOption関数</strong>を使用します。タイムアウト時間を変更したり、接続失敗時に自動的にリトライするようにしたりすることができるようになります。</p>



<pre class="wp-block-preformatted">BOOL InernetSetOption(
     IN HINTERNET hInternet OPTIONAL,
     IN DWORD Option,
     IN LPVOID Buf,
     IN DWORD BufSize);</pre>



<p>第1引数には、hInternetハンドルを指定します。InternetOpen関数で返されるハンドルです。</p>



<h3 class="wp-block-heading">タイムアウト時間を変更する</h3>



<p>　Optionに<strong>”INTERNET_OPTION_CONNECT_TIMEOUT”</strong>を指定すると、タイムアウト時間を任意に設定することができます。</p>



<pre class="wp-block-preformatted">InternetSetOption(hInternet, INTERNET_OPTION_CONNECT_TIMEOUT, &amp;dwtimeoutMs, sizeof(timeoutMs));</pre>



<p>　第3引数にタイムアウトまでの時間をミリ秒単位で指定します。指定時間内にサーバーとの接続が確立できないと、エラー12002（ERROR_INTERNET_TIMEOUT）が発生します。</p>



<h3 class="wp-block-heading">接続できないときに自動で再試行するようにする</h3>



<p>　<strong>INTERNET_OPTION_CONNECT_RETRIES</strong>オプションを設定すると、接続失敗時に自動再試行させることもできます。</p>



<pre class="wp-block-preformatted">InternetSetOption(hInternet, INTERNET_OPTION_CONNECT_RETRIES , &amp;dwRetryTimes, sizeof(dwRetryTimes));</pre>



<p>　自動再試行する回数や間隔を任意の値に設定することができます。</p>



<p>　ほかにも様々なオプションが用意されています。MSDNに指定できるパラメーターが掲載されていますので、ご参照ください。</p>




<a rel="noopener" href="https://docs.microsoft.com/en-us/windows/win32/wininet/option-flags" title="Option Flags (Wininet.h) - Win32 apps" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img loading="lazy" decoding="async" src="https://learn.microsoft.com/en-us/media/open-graph-image.png" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="90" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">Option Flags (Wininet.h) - Win32 apps</div><div class="blogcard-snippet external-blogcard-snippet">The following option flags are used with the InternetQueryOption and InternetSetOption functions. All valid option flags...</div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://learn.microsoft.com/en-us/windows/win32/wininet/option-flags" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">learn.microsoft.com</div></div></div></div></a>



<p></p>



<h2 class="wp-block-heading">まとめ</h2>



<p>　.NET Frameworkの活用が当たり前になっている世の中で、「今頃C++？？」という印象を受ける方もいるかもしれません。</p>



<p>　しかし、実際動かしてみると、<strong><span class="marker-animation">C#とは比較にならないくらい、爆速で動作します。</span></strong>一瞬で処理が完了するので、とにかく速く動作させたいというニーズには、今でもぴったりな選択肢といえるでしょう。</p>



<p>　それに、メモリを初期化したりなど、C#では味わえない<strong><span class="marker-animation">”コンピューターをコントロールしている感覚”</span></strong>がまた新鮮です。きっちり理解していないと動作させられないので、勉強になります。ふだんHTTPClientを使用されている方も、たまにはC++で遊んでみてはいかがでしょうか。</p>



<div class="wp-block-cocoon-blocks-blogcard blogcard-type bct-reference-link">
<p>　WinINetに関しては、Microsoft Docsに詳細が掲載されています。あわせて参照することをおすすめします。</p>

<a rel="noopener" href="https://docs.microsoft.com/en-us/windows/win32/wininet/http-sessions" title="HTTP Sessions - Win32 apps" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img loading="lazy" decoding="async" src="https://learn.microsoft.com/en-us/media/open-graph-image.png" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="90" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">HTTP Sessions - Win32 apps</div><div class="blogcard-snippet external-blogcard-snippet">Resources on the WWW are accessed by using http.</div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://learn.microsoft.com/en-us/windows/win32/wininet/http-sessions" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">learn.microsoft.com</div></div></div></div></a>
</div>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://takabus.com/cpp-wininet/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【PHP】POST・GETされたデータとヘッダーをロギングする方法</title>
		<link>https://takabus.com/201214-dump-post-data-php/</link>
					<comments>https://takabus.com/201214-dump-post-data-php/#respond</comments>
		
		<dc:creator><![CDATA[takabus]]></dc:creator>
		<pubDate>Sun, 10 Jan 2021 02:10:00 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<guid isPermaLink="false">https://cssv.mydns.jp/wp/?p=3944</guid>

					<description><![CDATA[　デバッグするときに、POST・GETで送信したデータやリクエストヘッダーを確認したいときがあります。テキストファイルに書き出しておけると便利でしょう。 　こういうときに使えるコードを載せておきます。 サンプルコード 　 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>　デバッグするときに、POST・GETで送信したデータやリクエストヘッダーを確認したいときがあります。テキストファイルに書き出しておけると便利でしょう。</p>



<p>　こういうときに使えるコードを載せておきます。</p>



<h2 class="wp-block-heading">サンプルコード</h2>



<p>　phpファイルを作成し、以下のコードをコピー・アンド・ペーストします。Webサーバーにアップロードすれば完了です。</p>



<pre class="wp-block-code php"><code>&lt;?php
// ログ保存ファイル名
define("TXTFILE", "log.txt");
// ファイルを追記モードでオープン
$fh = fopen(TXTFILE, "a+");
//ヘッダーをすべて取得して、配列として取得
$str = print_r(getallheaders(), true);//print_r関数は、第2引数んいtrueを指定すると、内容を返すことができる
// ファイルに追記する
fputs($fh,  date("Y-m-d H:i:s") . ' ' . $str . "\n");
// WEBページにも表示しておく
echo ($str);
// POSTされたデータをすべて取得して、配列として取得
$str = print_r($_POST, true);
// ファイルに追記する
fputs($fh,  date("Y-m-d H:i:s") . ' ' . $str . "\n");
// GETされたデータをすべて取得して、配列として取得
$str = print_r($_GET, true);
// ファイルに追記する
fputs($fh,  date("Y-m-d H:i:s") . ' ' . $str . "\n");
// WEBページにも表示しておく
echo ($str);
// ファイルを閉じる
fclose($fh);
// var_dump(file_get_contents(TXTFILE));
?&gt;</code></pre>



<p>あとはそのphpにPOSTしてみると、こんな感じで、POSTされたデータとRequestヘッダーがテキストファイルに記録されます。</p>



<pre class="wp-block-code"><code>2020-12-10 12:44:24 Array
(
    &#91;Content-Type] =&gt; application/x-www-form-urlencoded
    &#91;Host] =&gt; 192.168.1.4
    &#91;Content-Length] =&gt; 13
    &#91;Cache-Control] =&gt; no-cache
)

2020-12-10 12:44:24 Array
(
    &#91;a] =&gt; 1234
    &#91;b] =&gt; 5678
)
2020-12-10 12:44:24 Array
(
)</code></pre>



<p>　ログを出力するテキストファイルは、phpを配置したディレクトリに作成されます。GETでもヘッダーは記録されますので、ブラウザでアクセスするだけでもログが追加されていきます。</p>



<p>　もちろん、ログファイルが作成されるディレクトリは、Webサーバーから書き込めるように、書き込み権限を設定しておく必要がありますので、お忘れなく。</p>



<pre class="wp-block-code"><code># chmod -R 777 test //全ユーザーからの全権限（書き込み含む）を許可</code></pre>
]]></content:encoded>
					
					<wfw:commentRss>https://takabus.com/201214-dump-post-data-php/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
