<?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>Webアプリ &#8211; ケケンタの独学ITブログ</title>
	<atom:link href="https://kekenta-it-blog.com/tag/web%E3%82%A2%E3%83%97%E3%83%AA/feed/" rel="self" type="application/rss+xml" />
	<link>https://kekenta-it-blog.com</link>
	<description>プログラミングやWeb制作の情報を発信</description>
	<lastBuildDate>Tue, 18 Mar 2025 01:59:09 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://kekenta-it-blog.com/wp-content/uploads/2023/07/cropped-KEKENTA-BLOG-32x32.png</url>
	<title>Webアプリ &#8211; ケケンタの独学ITブログ</title>
	<link>https://kekenta-it-blog.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>【PHP】掲示板アプリの作り方｜正しいセキュリティ対策</title>
		<link>https://kekenta-it-blog.com/php-board-app-secure/</link>
		
		<dc:creator><![CDATA[ケケンタ]]></dc:creator>
		<pubDate>Mon, 18 Mar 2024 08:13:49 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Webアプリ]]></category>
		<category><![CDATA[セキュリティ対策]]></category>
		<guid isPermaLink="false">https://kekenta-it-blog.com/?p=3549</guid>

					<description><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/eye-catch__php-board-app-secure__3549-1024x576.jpg" class="webfeedsFeaturedVisual" /></p>以前にこちらの記事で掲示板アプリの作成方法を解説しました。 記事内でもお伝えしているように、上の記事で解説している掲示板アプリではセキュリティ対策はしておらず、本番運用には不向きの状態です。 今回は、この掲示板アプリにセ [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/eye-catch__php-board-app-secure__3549-1024x576.jpg" class="webfeedsFeaturedVisual" /></p>
<p class="is-style-balloon_box2">以前にこちらの記事で<strong>掲示板アプリの作成方法</strong>を解説しました。</p>


<div class="swell-block-postLink">			<div class="p-blogCard -external" data-type="type3" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">ケケンタの独学ITブログ</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/eye-catch__board-app-php__2739.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/board-app-php/" target="_blank" rel="noopener noreferrer">掲示板アプリの作り方｜プログラミング初心者向け【PHP】 | ケケンタの独学ITブログ</a>
						<span class="p-blogCard__excerpt">初心者向けにPHPで掲示板アプリを作成する方法を解説しています。PHPの基礎学習後、初めてのWebアプリ開発におすすめの記事です。</span>					</div>
				</div>
			</div>
		</div>


<p>記事内でもお伝えしているように、上の記事で解説している掲示板アプリでは<strong><span class="marker-under"><span class="swl-marker mark_orange">セキュリティ対策はしておらず、本番運用には不向き</span></span></strong>の状態です。</p>



<p>今回は、この掲示板アプリに<strong>セキュリティ対策</strong>の処理を加え、それについて解説をしていきたいと思います。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>純粋な掲示板アプリの解説が読みたい場合、まずは<a href="https://kekenta-it-blog.com/board-app-php/">上記の記事</a>をご覧下さい！<br>その上で当記事の<strong>セキュリティ対策編</strong>をお読みいただくことでご自身でも安全なアプリケーション開発を行うポイントを学ぶことが可能です。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<div class="swell-block-capbox cap_box is-style-shadow"><div class="cap_box_ttl"><span><span data-icon="LsLightbulb" data-id="0" style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" aria-hidden="true" class="swl-inline-icon"> </span><strong>この記事で分かること</strong></span></div><div class="cap_box_content">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>XSS対策方法・攻撃内容</li>



<li>CSRF対策方法（トークンの利用）・攻撃内容</li>



<li>SQLインジェクション対策方法・攻撃内容</li>



<li>セッションハイジャック対策方法・攻撃内容</li>
</ul>
</div></div>



<p class="is-style-bg_stripe">なお、この記事のセキュリティ対策は以下の書籍を参考にしています。<br>（<strong>通称：徳丸本</strong>と呼ばれる「Webアプリ開発者必読」とまで言われている書籍です）<br><br><a href="https://www.amazon.co.jp/%E4%BD%93%E7%B3%BB%E7%9A%84%E3%81%AB%E5%AD%A6%E3%81%B6-%E5%AE%89%E5%85%A8%E3%81%AAWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-%E7%AC%AC2%E7%89%88-%E8%84%86%E5%BC%B1%E6%80%A7%E3%81%8C%E7%94%9F%E3%81%BE%E3%82%8C%E3%82%8B%E5%8E%9F%E7%90%86%E3%81%A8%E5%AF%BE%E7%AD%96%E3%81%AE%E5%AE%9F%E8%B7%B5-%E5%BE%B3%E4%B8%B8/dp/4797393165?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&amp;crid=1FQAOXKEGI9HT&amp;dib=eyJ2IjoiMSJ9.ksxMxdA4KTXnYLFgVxMFis4f3XHMUvarmNijcsU4Nmvl3Tud_nU0g7agEl3ercb-Os7uj_I-9w5xejzyw_JwMcs7FC4uVP9jc3sHC7c9ZuDT_gwuJFliueZNV3zuXq4731v-JAlEh4pR64KI-_puhFly0i_zkfDlsH2xTLQWoeNNIM9FkS584d43eeD8-mNtPjbtKK1lmvjecUb-VALfXImg-mACYpqlPWhTawzlYmnCmT85BL5k4gVzrtlErnyRPeFE4qCXwaN884rSGk9l6PGCfVcIoDQOg1lp8Ia-RWA.i4wIGc7KFczkxeNgrmVo03tuk6Fod-K6t-LEHGJtLtE&amp;dib_tag=se&amp;keywords=Web%E3%82%A2%E3%83%97%E3%83%AA+%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3&amp;qid=1718235109&amp;sprefix=web%E3%82%A2%E3%83%97%E3%83%AA+%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%2Caps%2C186&amp;sr=8-1&amp;linkCode=ll1&amp;tag=kekenta03amaz-22&amp;linkId=dc5df2a77d4a028f4519e6b2a07ffb84&amp;language=ja_JP&amp;ref_=as_li_ss_tl"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNNDQgMkgzMGMtMS4xIDAtMiAuOS0yIDJzLjkgMiAyIDJoOS4yTDI0IDIxLjJjLS44LjgtLjggMiAwIDIuOHMyIC44IDIuOCAwTDQyIDguOFYxOGMwIDEuMS45IDIgMiAyczItLjkgMi0yVjRjMC0xLjEtLjktMi0yLTJ6Ij48L3BhdGg+PHBhdGggZD0iTTQxIDI3Yy0xLjEgMC0yIC45LTIgMnYxMGMwIDEuMS0uOSAyLTIgMkg5Yy0xLjEgMC0yLS45LTItMlYxMWMwLTEuMS45LTIgMi0yaDEwYzEuMSAwIDItLjkgMi0ycy0uOS0yLTItMkg5Yy0zLjMgMC02IDIuNy02IDZ2MjhjMCAzLjMgMi43IDYgNiA2aDI4YzMuMyAwIDYtMi43IDYtNlYyOWMwLTEuMS0uOS0yLTItMnoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsExternalLink" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span>体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 脆弱性が生まれる原理と対策の実践</a><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMTEuNyAxLjQgNi44IDVjLS41LjQtLjggMS0uOCAxLjZ2MjguN2MwIC44LjUgMS41IDEuMiAxLjhsMjQgMTAuM2MxLjMuNiAyLjgtLjQgMi44LTEuOFYxOWMwLS44LS41LTEuNS0xLjItMS44TDEwLjIgNy41bDIuOS0yLjJjLjktLjYgMi0uOCAzLS40bDIwLjYgOC44Yy43LjMgMS4yIDEgMS4yIDEuOFY0Mi45YzAgLjkgMSAxLjMgMS43LjhsMS43LTEuNWMuNC0uNC43LS45LjctMS41VjEzYzAtLjgtLjUtMS41LTEuMi0xLjhMMTYuNy44Yy0xLjctLjctMy42LS41LTUgLjZ6Ij48L3BhdGg+PC9zdmc+)" data-icon="LsBook" data-id="47" aria-hidden="true" class="swl-inline-icon"> </span><br>徳丸 浩／著　SBクリエイティブ／出版│<a href="https://www.amazon.co.jp/%E4%BD%93%E7%B3%BB%E7%9A%84%E3%81%AB%E5%AD%A6%E3%81%B6-%E5%AE%89%E5%85%A8%E3%81%AAWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-%E7%AC%AC2%E7%89%88-%E8%84%86%E5%BC%B1%E6%80%A7%E3%81%8C%E7%94%9F%E3%81%BE%E3%82%8C%E3%82%8B%E5%8E%9F%E7%90%86%E3%81%A8%E5%AF%BE%E7%AD%96%E3%81%AE%E5%AE%9F%E8%B7%B5-%E5%BE%B3%E4%B8%B8/dp/4797393165?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&amp;crid=1FQAOXKEGI9HT&amp;dib=eyJ2IjoiMSJ9.ksxMxdA4KTXnYLFgVxMFis4f3XHMUvarmNijcsU4Nmvl3Tud_nU0g7agEl3ercb-Os7uj_I-9w5xejzyw_JwMcs7FC4uVP9jc3sHC7c9ZuDT_gwuJFliueZNV3zuXq4731v-JAlEh4pR64KI-_puhFly0i_zkfDlsH2xTLQWoeNNIM9FkS584d43eeD8-mNtPjbtKK1lmvjecUb-VALfXImg-mACYpqlPWhTawzlYmnCmT85BL5k4gVzrtlErnyRPeFE4qCXwaN884rSGk9l6PGCfVcIoDQOg1lp8Ia-RWA.i4wIGc7KFczkxeNgrmVo03tuk6Fod-K6t-LEHGJtLtE&amp;dib_tag=se&amp;keywords=Web%E3%82%A2%E3%83%97%E3%83%AA+%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3&amp;qid=1718235109&amp;sprefix=web%E3%82%A2%E3%83%97%E3%83%AA+%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%2Caps%2C186&amp;sr=8-1&amp;linkCode=ll1&amp;tag=kekenta03amaz-22&amp;linkId=dc5df2a77d4a028f4519e6b2a07ffb84&amp;language=ja_JP&amp;ref_=as_li_ss_tl">Amazon</a></p>


<div class="swell-block-postLink">			<a href="https://kekenta-it-blog.com/alone-php-study/" class="c-blogLink -internal" data-style="text">
				<!-- <i class="c-blogLink__icon icon-link" role="presentation"></i> -->
				<span class="c-blogLink__icon">
					<svg xmlns="http://www.w3.org/2000/svg" class="swl-svg-link __svg" width="1em" height="1em" viewBox="0 0 48 48" role="img" aria-hidden="true" focusable="false"><path d="M21.2 30.2c-.5 0-1-.2-1.4-.6l-.7-.7c-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l7.1-7.1c2.3-2.3 5.3-3.5 8.5-3.5s6.2 1.2 8.5 3.5c4.7 4.7 4.7 12.3 0 17l-3.5 3.5c-.8.8-2 .8-2.8 0-.8-.8-.8-2 0-2.8l3.5-3.5c3.1-3.1 3.1-8.2 0-11.3-1.5-1.5-3.5-2.3-5.7-2.3-2.1 0-4.2.8-5.7 2.3l-7.1 7.1c-1.5 1.5-2.3 3.5-2.3 5.7s.8 4.2 2.3 5.7l.7.7c.8.8.8 2 0 2.8-.4.3-.9.5-1.4.5z" /><path d="M13.4 46.6c-3.1 0-6.1-1.2-8.5-3.5-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l3.5-3.5c.8-.8 2-.8 2.8 0 .8.8.8 2 0 2.8l-3.5 3.5c-1.5 1.5-2.3 3.5-2.3 5.7 0 2.1.8 4.2 2.3 5.7 3.1 3.1 8.2 3.1 11.3 0l7.1-7.1c1.5-1.5 2.3-3.5 2.3-5.7 0-2.1-.8-4.2-2.3-5.7l-.7-.7c-.8-.8-.8-2 0-2.8.8-.8 2-.8 2.8 0l.7.7c2.3 2.3 3.5 5.3 3.5 8.5s-1.2 6.2-3.5 8.5l-7.1 7.1c-2.3 2.3-5.3 3.5-8.4 3.5z" /></svg>				</span>
				<span class="c-blogLink__text">PHPはこうして習得した！約１年間の勉強内容【プログラミング独学】</span>
			</a>
		</div>

<div class="swell-block-postLink">			<a href="https://kekenta-it-blog.com/php-deploy-xserver-for-zip/" class="c-blogLink -internal" data-style="text">
				<!-- <i class="c-blogLink__icon icon-link" role="presentation"></i> -->
				<span class="c-blogLink__icon">
					<svg xmlns="http://www.w3.org/2000/svg" class="swl-svg-link __svg" width="1em" height="1em" viewBox="0 0 48 48" role="img" aria-hidden="true" focusable="false"><path d="M21.2 30.2c-.5 0-1-.2-1.4-.6l-.7-.7c-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l7.1-7.1c2.3-2.3 5.3-3.5 8.5-3.5s6.2 1.2 8.5 3.5c4.7 4.7 4.7 12.3 0 17l-3.5 3.5c-.8.8-2 .8-2.8 0-.8-.8-.8-2 0-2.8l3.5-3.5c3.1-3.1 3.1-8.2 0-11.3-1.5-1.5-3.5-2.3-5.7-2.3-2.1 0-4.2.8-5.7 2.3l-7.1 7.1c-1.5 1.5-2.3 3.5-2.3 5.7s.8 4.2 2.3 5.7l.7.7c.8.8.8 2 0 2.8-.4.3-.9.5-1.4.5z" /><path d="M13.4 46.6c-3.1 0-6.1-1.2-8.5-3.5-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l3.5-3.5c.8-.8 2-.8 2.8 0 .8.8.8 2 0 2.8l-3.5 3.5c-1.5 1.5-2.3 3.5-2.3 5.7 0 2.1.8 4.2 2.3 5.7 3.1 3.1 8.2 3.1 11.3 0l7.1-7.1c1.5-1.5 2.3-3.5 2.3-5.7 0-2.1-.8-4.2-2.3-5.7l-.7-.7c-.8-.8-.8-2 0-2.8.8-.8 2-.8 2.8 0l.7.7c2.3 2.3 3.5 5.3 3.5 8.5s-1.2 6.2-3.5 8.5l-7.1 7.1c-2.3 2.3-5.3 3.5-8.4 3.5z" /></svg>				</span>
				<span class="c-blogLink__text">【PHP】エックスサーバーへデプロイする方法【初心者でも簡単！】</span>
			</a>
		</div>

<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">あわせて読みたい</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/03/eye-catch__school-php-and-wp__14099-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/school-php-and-wp/">PHPやWordPressを学ぶのにおすすめのプログラミングスクール【７選】</a>
						<span class="p-blogCard__excerpt">僕はこれまで独学でPHPを学習してきました。結論から言えば、それでもPHPを習得することはできました。 しかし、それに費やした累計学習期間は1年ほど。モチベーション&#8230;</span>					</div>
				</div>
			</div>
		</div>


<h2 class="wp-block-heading">掲示板アプリの全体コード</h2>



<p class="is-style-balloon_box2"><strong>元々の掲示板アプリのコード</strong></p>



<div class="swell-block-tab is-style-balloon has-border -border01" data-width-pc="auto" data-width-sp="auto"><ul class="c-tabList" role="tablist"><li class="c-tabList__item" role="presentation"><button role="tab" class="c-tabList__button" aria-selected="true" aria-controls="tab-a10a9a3a-0" data-onclick="tabControl">掲示板アプリ全体のコード</button></li><li class="c-tabList__item" role="presentation"><button role="tab" class="c-tabList__button" aria-selected="false" aria-controls="tab-a10a9a3a-1" data-onclick="tabControl">style.css</button></li></ul><div class="c-tabBody">
<div id="tab-a10a9a3a-0" class="c-tabBody__item" aria-hidden="false">
<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">board.php（掲示板トップ）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * 投稿者ID（20桁）を生成
 */
if (isset($_SESSION[&#39;cont_id&#39;])) {
    $cont_id = $_SESSION[&#39;cont_id&#39;];
} else {
    $_SESSION[&#39;cont_id&#39;] = 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90));
    $cont_id = $_SESSION[&#39;cont_id&#39;];
}
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;
/**
 * 投稿ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;post_btn&#39;])) {
    // 更新操作用の処理
    unset($_SESSION[&#39;id&#39;]);
    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }
    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }
    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;
    /**
     * 必要項目がすべて入力されてたら投稿処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                INSERT INTO
                    board_info (title, comment, contributor_id)
                VALUES
                    (:TITLE, :COMMENT, :CONTRIBUTOR_ID)
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:CONTRIBUTOR_ID&#39;, $cont_id, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿に成功したらセッション変数を破棄
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 投稿一覧取得処理
 */
try {
    /**
     * DB接続処理
     */
    $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
        PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
        PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
    ]);
    $sql = (&#39;
        SELECT * 
        FROM board_info 
        ORDER BY id DESC
    &#39;);
    $stmt = $pdo-&gt;prepare($sql);
    // SQL実行
    $stmt-&gt;execute();
    // 投稿情報を辞書形式ですべて取得
    $post_list = $stmt-&gt;fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    echo &#39;接続失敗&#39; . $e-&gt;getMessage();
    exit();
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;掲示板アプリ&lt;/h1&gt;
    &lt;!-- 投稿フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル（※最大30文字）&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容（※最大1000文字）&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;])) echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;button class=&quot;btn--mg-c&quot; type=&quot;submit&quot; name=&quot;post_btn&quot; value=&quot;post_btn&quot;&gt;投稿&lt;/button&gt;
        &lt;/form&gt;
    &lt;/section&gt;
    &lt;hr&gt;
    &lt;!-- 投稿一覧 --&gt;
    &lt;section class=&quot;post-list&quot;&gt;
        &lt;?php if (count($post_list) === 0) : ?&gt;
            &lt;!-- 投稿が無いときはメッセージを表示する --&gt;
            &lt;p class=&quot;no-post-msg&quot;&gt;現在、投稿はありません。&lt;/p&gt;
        &lt;?php else : ?&gt;
            &lt;ul&gt;
                &lt;!-- 投稿情報の出力 --&gt;
                &lt;?php foreach ($post_list as $post_item) : ?&gt;
                    &lt;li&gt;
                        &lt;form action=&quot;&quot; method=&quot;post&quot;&gt;
                            &lt;!-- 投稿ID --&gt;
                            &lt;span&gt;ID：&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;　&lt;/span&gt;
                            &lt;!-- 投稿タイトル --&gt;
                            &lt;span&gt;&lt;?php echo $post_item[&#39;title&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿者ID --&gt;
                            &lt;span&gt;／投稿者：&lt;?php echo $post_item[&#39;contributor_id&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿内容 --&gt;
                            &lt;p class=&quot;p-pre&quot;&gt;&lt;?php echo $post_item[&#39;comment&#39;]; ?&gt;&lt;/p&gt;
                            &lt;!-- 投稿日時 --&gt;
                            &lt;span class=&quot;post-datetime&quot;&gt;投稿日時：&lt;?php echo $post_item[&#39;created_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 過去に更新されていたら更新日時も表示 --&gt;
                            &lt;?php if ($post_item[&#39;created_at&#39;] &lt; $post_item[&#39;updated_at&#39;]) : ?&gt;
                                &lt;span class=&quot;post-datetime post-datetime__updated&quot;&gt;更新日時：&lt;?php echo $post_item[&#39;updated_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;?php endif; ?&gt;
                        &lt;/form&gt;
                        &lt;!-- 自分の投稿内容かつセッションが有効な間は編集・削除が可能 --&gt;
                        &lt;?php if ($post_item[&#39;contributor_id&#39;] === $cont_id) : ?&gt;
                            &lt;div class=&quot;btn-flex&quot;&gt;
                                &lt;form action=&quot;update-edit.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;update_btn&quot;&gt;編集&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                                &lt;form action=&quot;delete-confirm.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;delete_btn&quot;&gt;削除&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                            &lt;/div&gt;
                        &lt;?php endif; ?&gt;
                        &lt;?php if (isset($_SESSION[&#39;id&#39;]) && ($_SESSION[&#39;id&#39;] == $post_item[&#39;id&#39;])): ?&gt;
                            &lt;p class=&#39;updated-post&#39;&gt;更新しました&lt;/p&gt;
                        &lt;?php endif; ?&gt;
                    &lt;/li&gt;
                &lt;?php endforeach; ?&gt;
            &lt;/ul&gt;
        &lt;?php endif; ?&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>



<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">update-edit.php（編集画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;
/**
 * 編集ボタンで遷移してきたときの処理
 */
if (isset($_POST[&#39;update_btn&#39;])) {
    /**
     * 編集対象の投稿情報を取得
     */
    if (isset($_POST[&#39;post_id&#39;]) && $_POST[&#39;post_id&#39;] != &#39;&#39;) {
        // セッションに投稿IDを保持
        $_SESSION[&#39;id&#39;] = $_POST[&#39;post_id&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容取得処理
             */
            $sql = (&#39;
                SELECT id, title, comment
                FROM board_info 
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿情報の取得
            $post_info = $stmt-&gt;fetch();
            $_SESSION[&#39;title&#39;] = $post_info[&#39;title&#39;];
            $_SESSION[&#39;comment&#39;] = $post_info[&#39;comment&#39;];
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 更新ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;update_submit_btn&#39;])) {
    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }
    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }
    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;
    /**
     * 必要項目がすべて入力されてたら更新処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容更新処理
             */
            $sql = (&#39;
                UPDATE board_info 
                SET title = :TITLE, comment = :COMMENT
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();
            // 更新に成功したらセッション変数を破棄
            // unset($_SESSION[&#39;id&#39;]);  // ※投稿IDは敢えて破棄せず、掲示板ページでID判定をするために情報を保持する★
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
            // 掲示板ページへ戻る
            header(&#39;Location: board.php&#39;);
            exit();
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * キャンセルボタンが押下されたら
 * セッション情報を破棄して
 * 掲示板一覧画面へ戻る
 */
if (isset($_POST[&#39;cancel_btn&#39;])) {
    unset($_SESSION[&#39;id&#39;]);
    unset($_SESSION[&#39;title&#39;]);
    unset($_SESSION[&#39;comment&#39;]);
    header(&#39;Location: board.php&#39;);
    exit();
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;投稿編集画面&lt;/h1&gt;
    &lt;!-- 投稿編集フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;]))  echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;; ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;btn-flex&quot;&gt;
                &lt;button type=&quot;submit&quot; name=&quot;update_submit_btn&quot; value=&quot;update_submit_btn&quot;&gt;更新&lt;/button&gt;
                &lt;button type=&quot;submit&quot; name=&quot;cancel_btn&quot; value=&quot;cancel_btn&quot;&gt;キャンセル&lt;/button&gt;
            &lt;/div&gt;
        &lt;/form&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>



<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">delete-confirm.php（削除確認画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;
/**
 * 削除ボタンで遷移してきたときの処理
 */
if (isset($_POST[&#39;delete_btn&#39;])) {
    /**
     * 編集対象の投稿情報を取得
     */
    if (isset($_POST[&#39;post_id&#39;]) && $_POST[&#39;post_id&#39;] != &#39;&#39;) {
        // セッションに投稿IDを保持
        $_SESSION[&#39;id&#39;] = $_POST[&#39;post_id&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                SELECT id, title, comment
                FROM board_info 
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿情報の取得
            $post_info = $stmt-&gt;fetch();
            $_SESSION[&#39;title&#39;] = $post_info[&#39;title&#39;];
            $_SESSION[&#39;comment&#39;] = $post_info[&#39;comment&#39;];
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 削除ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;delete_submit_btn&#39;])) {
    try {
        /**
         * DB接続処理
         */
        $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
            PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
        ]);
        /**
         * 投稿内容削除処理
         */
        $sql = (&#39;
            DELETE FROM board_info 
            WHERE id = :ID
        &#39;);
        $stmt = $pdo-&gt;prepare($sql);
        // プレースホルダーに値をセット
        $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
        // SQL実行
        $stmt-&gt;execute();
        // 削除に成功したらセッション変数を破棄
        unset($_SESSION[&#39;id&#39;]);
        unset($_SESSION[&#39;title&#39;]);
        unset($_SESSION[&#39;comment&#39;]);
        // 削除成功画面へ遷移
        header(&#39;Location: delete-success.php&#39;);
        exit();
    } catch (PDOException $e) {
        echo &#39;接続失敗&#39; . $e-&gt;getMessage();
        exit();
    }
    // DBとの接続を切る
    $pdo = null;
    $stmt = null;
}
/**
 * キャンセルボタンが押下されたら
 * セッション情報を破棄して
 * 掲示板一覧画面へ戻る
 */
if (isset($_POST[&#39;cancel_btn&#39;])) {
    unset($_SESSION[&#39;id&#39;]);
    unset($_SESSION[&#39;title&#39;]);
    unset($_SESSION[&#39;comment&#39;]);
    header(&#39;Location: board.php&#39;);
    return;
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;削除確認&lt;/h1&gt;
    &lt;p class=&quot;delete-confirm-msg&quot;&gt;以下の投稿を削除します。&lt;/p&gt;
    &lt;!-- 削除確認画面 --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;p&gt;タイトル&lt;/p&gt;
                    &lt;p&gt;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&lt;/p&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;p&gt;投稿内容&lt;/p&gt;
                    &lt;p class=&quot;p-pre&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;]))  echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/p&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;btn-flex&quot;&gt;
                &lt;button type=&quot;submit&quot; name=&quot;delete_submit_btn&quot; value=&quot;delete_submit_btn&quot;&gt;削除&lt;/button&gt;
                &lt;button type=&quot;submit&quot; name=&quot;cancel_btn&quot; value=&quot;cancel_btn&quot;&gt;キャンセル&lt;/button&gt;
            &lt;/div&gt;
        &lt;/form&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>



<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">delete-success.php（削除成功画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * 掲示場TOPへ自動で遷移する処理★
 */
header(&#39;refresh: 3; url=board.php&#39;);
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;削除が完了しました。&lt;/h1&gt;
    &lt;p class=&quot;delete-success-msg&quot;&gt;3秒後に自動で掲示板TOPへ戻ります。&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>
</div>
</div>



<div id="tab-a10a9a3a-1" class="c-tabBody__item" aria-hidden="true">
<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">style.css（同じ見た目にしたい方用）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-css" data-lang="CSS"><code>body {
    margin: 0 auto;
    width: 700px;
    background-color: rgb(224, 224, 224);
}
hr {
    margin: 40px 0;
    border-color: rgb(137, 137, 137);
}
h1 {
    text-align: center;
}
li {
    list-style: none;
}
p {
    margin: 0;
}
p,
span {
    color: #333;
}
input,
textarea {
    padding: 10px;
    border: 1px solid gray;
    border-radius: 10px;
    width: 100%;
    box-sizing: border-box;
}
textarea {
    line-height: 1.5;
}
button {
    display: block;
    margin-top: 20px;
    padding: 10px 30px;
    color: #fff;
    border-radius: 10px;
    cursor: pointer;
}
button[name=&quot;post_btn&quot;] {
    border: 1px solid rgb(148, 148, 218);
    background-color: rgb(94, 94, 255);
}
button[name=&quot;update_btn&quot;],
button[name=&quot;update_submit_btn&quot;] {
    border: 1px solid rgb(62, 150, 62);
    background-color: rgb(74, 152, 74);
}
button[name=&quot;delete_btn&quot;],
button[name=&quot;delete_submit_btn&quot;] {
    border: 1px solid rgb(255, 31, 31);
    background-color: rgb(255, 48, 48);
}
button[name=&quot;cancel_btn&quot;] {
    border: 1px solid rgb(172, 172, 172);
    background-color: rgb(182, 182, 182);
}
button[name=&quot;post_btn&quot;]:hover {
    background-color: rgb(116, 116, 255);
}
button[name=&quot;update_btn&quot;]:hover,
button[name=&quot;update_submit_btn&quot;]:hover {
    background-color: rgb(83, 169, 83);
}
button[name=&quot;delete_btn&quot;]:hover,
button[name=&quot;delete_submit_btn&quot;]:hover {
    background-color: rgb(255, 82, 82);
}
button[name=&quot;cancel_btn&quot;]:hover {
    background-color: rgb(189, 189, 189);
}
.btn--mg-c {
    margin: 0 auto;
}
.post-list button {
    margin: 30px 0 0 0;
    padding: 8px 20px;
}
.post-list li {
    margin-bottom: 15px;
    padding: 20px 30px;
    background-color: #fff;
    border: 1px solid rgb(188, 188, 188);
    border-radius: 10px;
}
.post-list span {
    display: inline-block;
    margin-bottom: 25px;
}
.post-form__flex {
    display: flex;
    justify-content: center;
    column-gap: 15px;
    margin-bottom: 20px;
}
.post-form__flex&gt;div:first-child {
    width: 250px;
}
.post-form__flex&gt;div:last-child {
    flex: 1;
}
.btn-flex {
    display: flex;
    justify-content: center;
    column-gap: 15px;
}
.post-list li:last-child {
    margin-bottom: 0;
}
.post-datetime {
    display: inline-block;
    margin-top: 25px;
    font-size: 12px;
    color: gray;
}
.post-datetime__updated {
    display: inline-block;
    margin-left: 10px;
}
.updated-post {
    margin-left: auto;
    padding: 2px 5px;
    width: fit-content;
    font-size: 12px;
    border: 1px solid rgb(105, 105, 105);
    border-radius: 5px;
    color: rgb(105, 105, 105);
}
.no-post-msg {
    text-align: center;
}
.delete-confirm-msg {
    text-align: center;
    margin-bottom: 30px;
    color: red;
    font-weight: bold;
}
.delete-success-msg {
    text-align: center;
}
.err {
    color: red;
    font-size: 13px;
}
/* 
改行もそのまま表示するための指定
これが無いと改行が半角スペースに変換されて
表示されてしまう
 */
.p-pre {
    white-space: pre-wrap;
}</code></pre></div>
</div></details>
</div>
</div>



<div id="tab-a10a9a3a-2" class="c-tabBody__item" aria-hidden="true">
<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">board.php</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php

/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();

/**
 * 投稿者ID（20桁）を生成
 */
if (isset($_SESSION[&#39;cont_id&#39;])) {
    $cont_id = $_SESSION[&#39;cont_id&#39;];
} else {
    $_SESSION[&#39;cont_id&#39;] = 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90));
    $cont_id = $_SESSION[&#39;cont_id&#39;];
}

/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;

/**
 * 投稿ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;post_btn&#39;])) {

    // 更新操作用の処理
    unset($_SESSION[&#39;id&#39;]);

    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }

    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }

    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;

    /**
     * 必要項目がすべて入力されてたら投稿処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];

        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);

            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                INSERT INTO
                    board_info (title, comment, contributor_id)
                VALUES
                    (:TITLE, :COMMENT, :CONTRIBUTOR_ID)
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:CONTRIBUTOR_ID&#39;, $cont_id, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();

            // 投稿に成功したらセッション変数を破棄
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}

/**
 * 投稿一覧取得処理
 */
try {
    /**
     * DB接続処理
     */
    $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
        PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
        PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
    ]);

    $sql = (&#39;
        SELECT * 
        FROM board_info 
        ORDER BY id DESC
    &#39;);
    $stmt = $pdo-&gt;prepare($sql);

    // SQL実行
    $stmt-&gt;execute();

    // 投稿情報を辞書形式ですべて取得
    $post_list = $stmt-&gt;fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    echo &#39;接続失敗&#39; . $e-&gt;getMessage();
    exit();
}

?&gt;

&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;

&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;h1&gt;掲示板アプリ&lt;/h1&gt;

    &lt;!-- 投稿フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル（※最大30文字）&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容（※最大1000文字）&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;])) echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;button class=&quot;btn--mg-c&quot; type=&quot;submit&quot; name=&quot;post_btn&quot; value=&quot;post_btn&quot;&gt;投稿&lt;/button&gt;
        &lt;/form&gt;
    &lt;/section&gt;

    &lt;hr&gt;

    &lt;!-- 投稿一覧 --&gt;
    &lt;section class=&quot;post-list&quot;&gt;
        &lt;?php if (count($post_list) === 0) : ?&gt;
            &lt;!-- 投稿が無いときはメッセージを表示する --&gt;
            &lt;p class=&quot;no-post-msg&quot;&gt;現在、投稿はありません。&lt;/p&gt;
        &lt;?php else : ?&gt;
            &lt;ul&gt;
                &lt;!-- 投稿情報の出力 --&gt;
                &lt;?php foreach ($post_list as $post_item) : ?&gt;
                    &lt;li&gt;
                        &lt;form action=&quot;&quot; method=&quot;post&quot;&gt;
                            &lt;!-- 投稿ID --&gt;
                            &lt;span&gt;ID：&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;　&lt;/span&gt;
                            &lt;!-- 投稿タイトル --&gt;
                            &lt;span&gt;&lt;?php echo $post_item[&#39;title&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿者ID --&gt;
                            &lt;span&gt;／投稿者：&lt;?php echo $post_item[&#39;contributor_id&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿内容 --&gt;
                            &lt;p class=&quot;p-pre&quot;&gt;&lt;?php echo $post_item[&#39;comment&#39;]; ?&gt;&lt;/p&gt;
                            &lt;!-- 投稿日時 --&gt;
                            &lt;span class=&quot;post-datetime&quot;&gt;投稿日時：&lt;?php echo $post_item[&#39;created_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 過去に更新されていたら更新日時も表示 --&gt;
                            &lt;?php if ($post_item[&#39;created_at&#39;] &lt; $post_item[&#39;updated_at&#39;]) : ?&gt;
                                &lt;span class=&quot;post-datetime post-datetime__updated&quot;&gt;更新日時：&lt;?php echo $post_item[&#39;updated_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;?php endif; ?&gt;
                        &lt;/form&gt;
                        &lt;!-- 自分の投稿内容かつセッションが有効な間は編集・削除が可能 --&gt;
                        &lt;?php if ($post_item[&#39;contributor_id&#39;] === $cont_id) : ?&gt;
                            &lt;div class=&quot;btn-flex&quot;&gt;
                                &lt;form action=&quot;update-edit.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;update_btn&quot;&gt;編集&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                                &lt;form action=&quot;delete-confirm.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;delete_btn&quot;&gt;削除&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                            &lt;/div&gt;
                        &lt;?php endif; ?&gt;
                        &lt;?php if (isset($_SESSION[&#39;id&#39;]) && ($_SESSION[&#39;id&#39;] == $post_item[&#39;id&#39;])): ?&gt;
                            &lt;p class=&#39;updated-post&#39;&gt;更新しました&lt;/p&gt;
                        &lt;?php endif; ?&gt;
                    &lt;/li&gt;
                &lt;?php endforeach; ?&gt;
            &lt;/ul&gt;
        &lt;?php endif; ?&gt;
    &lt;/section&gt;
&lt;/body&gt;

&lt;/html&gt;</code></pre></div>
</div></details>
</div>
</div>
</div></div>



<p class="is-style-balloon_box2"><strong>セキュリティ対策を施したコード</strong></p>



<div class="swell-block-tab is-style-balloon has-border -border01" data-width-pc="auto" data-width-sp="auto"><ul class="c-tabList" role="tablist"><li class="c-tabList__item" role="presentation"><button role="tab" class="c-tabList__button" aria-selected="true" aria-controls="tab-61bcf5ce-0" data-onclick="tabControl">掲示板アプリ全体のコード</button></li><li class="c-tabList__item" role="presentation"><button role="tab" class="c-tabList__button" aria-selected="false" aria-controls="tab-61bcf5ce-1" data-onclick="tabControl">style.css</button></li></ul><div class="c-tabBody">
<div id="tab-61bcf5ce-0" class="c-tabBody__item" aria-hidden="false">
<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">board.php（掲示板トップ）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
// ★【セッションハイジャック】セッションIDを新しいものに置き換える
session_regenerate_id();
/**
 * 投稿者ID（20桁）を生成
 */
if (isset($_SESSION[&#39;cont_id&#39;])) {
    $cont_id = $_SESSION[&#39;cont_id&#39;];
} else {
    $_SESSION[&#39;cont_id&#39;] =
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90));
    $cont_id = $_SESSION[&#39;cont_id&#39;];
}
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_path&#39;;
/**
 * 投稿ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;post_btn&#39;])) {
    // ★【CSRF】トークンチェック
    if(empty($_SESSION[&#39;board_token&#39;]) || ($_SESSION[&#39;board_token&#39;] !== $_POST[&#39;board_token&#39;])){
        exit(&#39;不正な投稿です&#39;);
    }
    if(isset($_SESSION[&#39;board_token&#39;])) unset($_SESSION[&#39;board_token&#39;]);//トークン破棄
    if(isset($_POST[&#39;board_token&#39;])) unset($_POST[&#39;board_token&#39;]);//トークン破棄
    // 更新操作用の処理
    unset($_SESSION[&#39;id&#39;]);
    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }
    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }
    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;
    /**
     * 必要項目がすべて入力されてたら投稿処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
                PDO::ATTR_EMULATE_PREPARES =&gt; false,              // ★【SQLインジェクション】静的プレースホルダーを使用
            ]);
            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                INSERT INTO
                    board_info (title, comment, contributor_id)
                VALUES
                    (:TITLE, :COMMENT, :CONTRIBUTOR_ID)
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:CONTRIBUTOR_ID&#39;, $cont_id, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿に成功したらセッション変数を破棄
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 投稿一覧取得処理
 */
try {
    /**
     * DB接続処理
     */
    $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
        PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
        PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
        PDO::ATTR_EMULATE_PREPARES =&gt; false,              // ★【SQLインジェクション】静的プレースホルダーを使用
    ]);
    $sql = (&#39;
        SELECT * 
        FROM board_info 
        ORDER BY id DESC
    &#39;);
    $stmt = $pdo-&gt;prepare($sql);
    // SQL実行
    $stmt-&gt;execute();
    // 投稿情報を辞書形式ですべて取得
    $post_list = $stmt-&gt;fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    echo &#39;接続失敗&#39; . $e-&gt;getMessage();
    exit();
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;掲示板アプリ&lt;/h1&gt;
    &lt;!-- 投稿フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル（※最大30文字）&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo htmlspecialchars($_SESSION[&#39;title&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo htmlspecialchars(&quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;, ENT_QUOTES, &#39;UTF-8&#39;);
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容（※最大1000文字）&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;])) echo htmlspecialchars($_SESSION[&#39;comment&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) echo htmlspecialchars(&quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;, ENT_QUOTES, &#39;UTF-8&#39;);; ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;?php 
            //★ 不正リクエストチェック用のトークン生成
            $token = sha1(uniqid(mt_rand(), true));
            $_SESSION[&#39;board_token&#39;] = $token;
            echo &#39;&lt;input type=&quot;hidden&quot; name=&quot;board_token&quot; value=&quot;&#39;.$token.&#39;&quot; /&gt;&#39;;
            ?&gt;
            &lt;button class=&quot;btn--mg-c&quot; type=&quot;submit&quot; name=&quot;post_btn&quot; value=&quot;post_btn&quot;&gt;投稿&lt;/button&gt;
        &lt;/form&gt;
    &lt;/section&gt;
    &lt;hr&gt;
    &lt;!-- 投稿一覧 --&gt;
    &lt;section class=&quot;post-list&quot;&gt;
        &lt;?php if (count($post_list) === 0) : ?&gt;
            &lt;!-- 投稿が無いときはメッセージを表示する --&gt;
            &lt;p class=&quot;no-post-msg&quot;&gt;現在、投稿はありません。&lt;/p&gt;
        &lt;?php else : ?&gt;
            &lt;ul&gt;
                &lt;!-- 投稿情報の出力 --&gt;
                &lt;?php foreach ($post_list as $post_item) : ?&gt;
                    &lt;li&gt;
                        &lt;form action=&quot;&quot; method=&quot;post&quot;&gt;
                            &lt;!-- 投稿ID --&gt;
                            &lt;span&gt;ID：&lt;?php echo htmlspecialchars($post_item[&#39;id&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;　&lt;/span&gt;
                            &lt;!-- 投稿タイトル --&gt;
                            &lt;span&gt;&lt;?php echo htmlspecialchars($post_item[&#39;title&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿者ID --&gt;
                            &lt;span&gt;／投稿者：&lt;?php echo htmlspecialchars($post_item[&#39;contributor_id&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿内容 --&gt;
                            &lt;p class=&quot;p-pre&quot;&gt;&lt;?php echo htmlspecialchars($post_item[&#39;comment&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&lt;/p&gt;
                            &lt;!-- 投稿日時 --&gt;
                            &lt;span class=&quot;post-datetime&quot;&gt;投稿日時：&lt;?php echo htmlspecialchars($post_item[&#39;created_at&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&lt;/span&gt;
                            &lt;!-- 過去に更新されていたら更新日時も表示 --&gt;
                            &lt;?php if ($post_item[&#39;created_at&#39;] &lt; $post_item[&#39;updated_at&#39;]) : ?&gt;
                                &lt;span class=&quot;post-datetime post-datetime__updated&quot;&gt;更新日時：&lt;?php echo htmlspecialchars($post_item[&#39;updated_at&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&lt;/span&gt;
                            &lt;?php endif; ?&gt;
                        &lt;/form&gt;
                        &lt;!-- 自分の投稿内容かつセッションが有効な間は編集・削除が可能 --&gt;
                        &lt;?php if ($post_item[&#39;contributor_id&#39;] === $cont_id) : ?&gt;
                            &lt;div class=&quot;btn-flex&quot;&gt;
                                &lt;form action=&quot;update-edit.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;update_btn&quot;&gt;編集&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo htmlspecialchars($post_item[&#39;id&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&quot;&gt;
                                &lt;/form&gt;
                                &lt;form action=&quot;delete-confirm.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;delete_btn&quot;&gt;削除&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo htmlspecialchars($post_item[&#39;id&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&quot;&gt;
                                &lt;/form&gt;
                            &lt;/div&gt;
                        &lt;?php endif; ?&gt;
                        &lt;?php if (isset($_SESSION[&#39;id&#39;]) && ($_SESSION[&#39;id&#39;] == $post_item[&#39;id&#39;])) : ?&gt;
                            &lt;p class=&#39;updated-post&#39;&gt;更新しました&lt;/p&gt;
                        &lt;?php endif; ?&gt;
                    &lt;/li&gt;
                &lt;?php endforeach; ?&gt;
            &lt;/ul&gt;
        &lt;?php endif; ?&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>



<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">update-edit.php（編集画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
// ★【セッションハイジャック】セッションIDを新しいものに置き換える
session_regenerate_id();
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_path&#39;;
/**
 * 編集ボタンで遷移してきたときの処理
 */
if (isset($_POST[&#39;update_btn&#39;])) {
    /**
     * 編集対象の投稿情報を取得
     */
    if (isset($_POST[&#39;post_id&#39;]) && $_POST[&#39;post_id&#39;] != &#39;&#39;) {
        // セッションに投稿IDを保持
        $_SESSION[&#39;id&#39;] = $_POST[&#39;post_id&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
                PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
                PDO::ATTR_EMULATE_PREPARES =&gt; false,              // ★【SQLインジェクション】静的プレースホルダーを使用
            ]);
            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                SELECT id, title, comment
                FROM board_info 
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿情報の取得
            $post_info = $stmt-&gt;fetch();
            $_SESSION[&#39;title&#39;] = $post_info[&#39;title&#39;];
            $_SESSION[&#39;comment&#39;] = $post_info[&#39;comment&#39;];
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 更新ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;update_submit_btn&#39;])) {
    // ★【CSRF】トークンチェック
    if (empty($_SESSION[&#39;board_token&#39;]) || ($_SESSION[&#39;board_token&#39;] !== $_POST[&#39;board_token&#39;])) {
        exit(&#39;不正な投稿です&#39;);
    }
    if (isset($_SESSION[&#39;board_token&#39;])) unset($_SESSION[&#39;board_token&#39;]); //トークン破棄
    if (isset($_POST[&#39;board_token&#39;])) unset($_POST[&#39;board_token&#39;]); //トークン破棄
    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }
    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }
    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;
    /**
     * 必要項目がすべて入力されてたら投稿処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
                PDO::ATTR_EMULATE_PREPARES =&gt; false,              // ★【SQLインジェクション】静的プレースホルダーを使用
            ]);
            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                UPDATE board_info 
                SET title = :TITLE, comment = :COMMENT
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿に成功したらセッション変数を破棄
            // unset($_SESSION[&#39;id&#39;]);  // ※投稿IDは敢えて破棄せず、掲示板ページでID判定をするために情報を保持する
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
            // 掲示板ページへ戻る
            header(&#39;Location: board.php&#39;);
            exit();
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * キャンセルボタンが押下されたら
 * セッション情報を破棄して
 * 掲示板一覧画面へ戻る
 */
if (isset($_POST[&#39;cancel_btn&#39;])) {
    unset($_SESSION[&#39;id&#39;]);
    unset($_SESSION[&#39;title&#39;]);
    unset($_SESSION[&#39;comment&#39;]);
    header(&#39;Location: board.php&#39;);
    exit();
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;投稿編集画面&lt;/h1&gt;
    &lt;!-- 投稿編集フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo htmlspecialchars($_SESSION[&#39;title&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo htmlspecialchars(&quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;, ENT_QUOTES, &#39;UTF-8&#39;);
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;]))  echo htmlspecialchars($_SESSION[&#39;comment&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) echo htmlspecialchars(&quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;, ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            
            &lt;?php 
            //★ 不正リクエストチェック用のトークン生成
            $token = sha1(uniqid(mt_rand(), true));
            $_SESSION[&#39;board_token&#39;] = $token;
            echo &#39;&lt;input type=&quot;hidden&quot; name=&quot;board_token&quot; value=&quot;&#39;.$token.&#39;&quot; /&gt;&#39;;
            ?&gt;
            &lt;div class=&quot;btn-flex&quot;&gt;
                &lt;button type=&quot;submit&quot; name=&quot;update_submit_btn&quot; value=&quot;update_submit_btn&quot;&gt;更新&lt;/button&gt;
                &lt;button type=&quot;submit&quot; name=&quot;cancel_btn&quot; value=&quot;cancel_btn&quot;&gt;キャンセル&lt;/button&gt;
            &lt;/div&gt;
        &lt;/form&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>



<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">delete-confirm.php（削除確認画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
// ★【セッションハイジャック】セッションIDを新しいものに置き換える
session_regenerate_id();
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_path&#39;;
/**
 * 削除ボタンで遷移してきたときの処理
 */
if (isset($_POST[&#39;delete_btn&#39;])) {
    /**
     * 編集対象の投稿情報を取得
     */
    if (isset($_POST[&#39;post_id&#39;]) && $_POST[&#39;post_id&#39;] != &#39;&#39;) {
        // セッションに投稿IDを保持
        $_SESSION[&#39;id&#39;] = $_POST[&#39;post_id&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
                PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
                PDO::ATTR_EMULATE_PREPARES =&gt; false,              // ★【SQLインジェクション】静的プレースホルダーを使用
            ]);
            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                SELECT id, title, comment
                FROM board_info 
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿情報の取得
            $post_info = $stmt-&gt;fetch();
            $_SESSION[&#39;title&#39;] = $post_info[&#39;title&#39;];
            $_SESSION[&#39;comment&#39;] = $post_info[&#39;comment&#39;];
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 削除ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;delete_submit_btn&#39;])) {
    // ★【CSRF】トークンチェック
    if (empty($_SESSION[&#39;board_token&#39;]) || ($_SESSION[&#39;board_token&#39;] !== $_POST[&#39;board_token&#39;])) {
        exit(&#39;不正な投稿です&#39;);
    }
    if (isset($_SESSION[&#39;board_token&#39;])) unset($_SESSION[&#39;board_token&#39;]); //トークン破棄
    if (isset($_POST[&#39;board_token&#39;])) unset($_POST[&#39;board_token&#39;]); //トークン破棄
    try {
        /**
         * DB接続処理
         */
        $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
            PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            PDO::ATTR_EMULATE_PREPARES =&gt; false,              // ★【SQLインジェクション】静的プレースホルダーを使用
        ]);
        /**
         * 投稿内容削除処理
         */
        $sql = (&#39;
            DELETE FROM board_info 
            WHERE id = :ID
        &#39;);
        $stmt = $pdo-&gt;prepare($sql);
        // プレースホルダーに値をセット
        $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
        // SQL実行
        $stmt-&gt;execute();
        // 削除に成功したらセッション変数を破棄
        unset($_SESSION[&#39;id&#39;]);
        unset($_SESSION[&#39;title&#39;]);
        unset($_SESSION[&#39;comment&#39;]);
        // 削除成功画面へ遷移
        header(&#39;Location: delete-success.php&#39;);
        exit();
    } catch (PDOException $e) {
        echo &#39;接続失敗&#39; . $e-&gt;getMessage();
        exit();
    }
    // DBとの接続を切る
    $pdo = null;
    $stmt = null;
}
/**
 * キャンセルボタンが押下されたら
 * セッション情報を破棄して
 * 掲示板一覧画面へ戻る
 */
if (isset($_POST[&#39;cancel_btn&#39;])) {
    unset($_SESSION[&#39;id&#39;]);
    unset($_SESSION[&#39;title&#39;]);
    unset($_SESSION[&#39;comment&#39;]);
    header(&#39;Location: board.php&#39;);
    return;
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;削除確認&lt;/h1&gt;
    &lt;p class=&quot;delete-confirm-msg&quot;&gt;以下の投稿を削除します。&lt;/p&gt;
    &lt;!-- 削除確認画面 --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;p&gt;タイトル&lt;/p&gt;
                    &lt;p&gt;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo htmlspecialchars($_SESSION[&#39;title&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&lt;/p&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;p&gt;投稿内容&lt;/p&gt;
                    &lt;p class=&quot;p-pre&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;])) echo htmlspecialchars($_SESSION[&#39;comment&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&lt;/p&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;?php 
            //★【CSRF】 不正リクエストチェック用のトークン生成
            $token = sha1(uniqid(mt_rand(), true));
            $_SESSION[&#39;board_token&#39;] = $token;
            echo &#39;&lt;input type=&quot;hidden&quot; name=&quot;board_token&quot; value=&quot;&#39;.$token.&#39;&quot; /&gt;&#39;;
            ?&gt;
            &lt;div class=&quot;btn-flex&quot;&gt;
                &lt;button type=&quot;submit&quot; name=&quot;delete_submit_btn&quot; value=&quot;delete_submit_btn&quot;&gt;削除&lt;/button&gt;
                &lt;button type=&quot;submit&quot; name=&quot;cancel_btn&quot; value=&quot;cancel_btn&quot;&gt;キャンセル&lt;/button&gt;
            &lt;/div&gt;
        &lt;/form&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>



<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">delete-success.php（削除成功画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * 掲示場TOPへ自動で遷移する処理
 */
header(&#39;refresh: 3; url=board.php&#39;);
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;削除が完了しました。&lt;/h1&gt;
    &lt;p class=&quot;delete-success-msg&quot;&gt;3秒後に自動で掲示板TOPへ戻ります。&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>
</div>
</div>



<div id="tab-61bcf5ce-1" class="c-tabBody__item" aria-hidden="true">
<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">style.css（同じ見た目にしたい方用）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-css" data-lang="CSS"><code>body {
    margin: 0 auto;
    width: 700px;
    background-color: rgb(224, 224, 224);
}
hr {
    margin: 40px 0;
    border-color: rgb(137, 137, 137);
}
h1 {
    text-align: center;
}
li {
    list-style: none;
}
p {
    margin: 0;
}
p,
span {
    color: #333;
}
input,
textarea {
    padding: 10px;
    border: 1px solid gray;
    border-radius: 10px;
    width: 100%;
    box-sizing: border-box;
}
textarea {
    line-height: 1.5;
}
button {
    display: block;
    margin-top: 20px;
    padding: 10px 30px;
    color: #fff;
    border-radius: 10px;
    cursor: pointer;
}
button[name=&quot;post_btn&quot;] {
    border: 1px solid rgb(148, 148, 218);
    background-color: rgb(94, 94, 255);
}
button[name=&quot;update_btn&quot;],
button[name=&quot;update_submit_btn&quot;] {
    border: 1px solid rgb(62, 150, 62);
    background-color: rgb(74, 152, 74);
}
button[name=&quot;delete_btn&quot;],
button[name=&quot;delete_submit_btn&quot;] {
    border: 1px solid rgb(255, 31, 31);
    background-color: rgb(255, 48, 48);
}
button[name=&quot;cancel_btn&quot;] {
    border: 1px solid rgb(172, 172, 172);
    background-color: rgb(182, 182, 182);
}
button[name=&quot;post_btn&quot;]:hover {
    background-color: rgb(116, 116, 255);
}
button[name=&quot;update_btn&quot;]:hover,
button[name=&quot;update_submit_btn&quot;]:hover {
    background-color: rgb(83, 169, 83);
}
button[name=&quot;delete_btn&quot;]:hover,
button[name=&quot;delete_submit_btn&quot;]:hover {
    background-color: rgb(255, 82, 82);
}
button[name=&quot;cancel_btn&quot;]:hover {
    background-color: rgb(189, 189, 189);
}
.btn--mg-c {
    margin: 0 auto;
}
.post-list button {
    margin: 30px 0 0 0;
    padding: 8px 20px;
}
.post-list li {
    margin-bottom: 15px;
    padding: 20px 30px;
    background-color: #fff;
    border: 1px solid rgb(188, 188, 188);
    border-radius: 10px;
}
.post-list span {
    display: inline-block;
    margin-bottom: 25px;
}
.post-form__flex {
    display: flex;
    justify-content: center;
    column-gap: 15px;
    margin-bottom: 20px;
}
.post-form__flex&gt;div:first-child {
    width: 250px;
}
.post-form__flex&gt;div:last-child {
    flex: 1;
}
.btn-flex {
    display: flex;
    justify-content: center;
    column-gap: 15px;
}
.post-list li:last-child {
    margin-bottom: 0;
}
.post-datetime {
    display: inline-block;
    margin-top: 25px;
    font-size: 12px;
    color: gray;
}
.post-datetime__updated {
    display: inline-block;
    margin-left: 10px;
}
.updated-post {
    margin-left: auto;
    padding: 2px 5px;
    width: fit-content;
    font-size: 12px;
    border: 1px solid rgb(105, 105, 105);
    border-radius: 5px;
    color: rgb(105, 105, 105);
}
.no-post-msg {
    text-align: center;
}
.delete-confirm-msg {
    text-align: center;
    margin-bottom: 30px;
    color: red;
    font-weight: bold;
}
.delete-success-msg {
    text-align: center;
}
.err {
    color: red;
    font-size: 13px;
}
/* 
改行もそのまま表示するための指定
これが無いと改行が半角スペースに変換されて
表示されてしまう
 */
.p-pre {
    white-space: pre-wrap;
}</code></pre></div>
</div></details>
</div>
</div>



<div id="tab-61bcf5ce-2" class="c-tabBody__item" aria-hidden="true">
<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">board.php</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php

/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();

/**
 * 投稿者ID（20桁）を生成
 */
if (isset($_SESSION[&#39;cont_id&#39;])) {
    $cont_id = $_SESSION[&#39;cont_id&#39;];
} else {
    $_SESSION[&#39;cont_id&#39;] = 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90));
    $cont_id = $_SESSION[&#39;cont_id&#39;];
}

/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;

/**
 * 投稿ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;post_btn&#39;])) {

    // 更新操作用の処理
    unset($_SESSION[&#39;id&#39;]);

    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }

    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }

    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;

    /**
     * 必要項目がすべて入力されてたら投稿処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];

        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);

            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                INSERT INTO
                    board_info (title, comment, contributor_id)
                VALUES
                    (:TITLE, :COMMENT, :CONTRIBUTOR_ID)
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:CONTRIBUTOR_ID&#39;, $cont_id, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();

            // 投稿に成功したらセッション変数を破棄
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}

/**
 * 投稿一覧取得処理
 */
try {
    /**
     * DB接続処理
     */
    $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
        PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
        PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
    ]);

    $sql = (&#39;
        SELECT * 
        FROM board_info 
        ORDER BY id DESC
    &#39;);
    $stmt = $pdo-&gt;prepare($sql);

    // SQL実行
    $stmt-&gt;execute();

    // 投稿情報を辞書形式ですべて取得
    $post_list = $stmt-&gt;fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    echo &#39;接続失敗&#39; . $e-&gt;getMessage();
    exit();
}

?&gt;

&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;

&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;h1&gt;掲示板アプリ&lt;/h1&gt;

    &lt;!-- 投稿フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル（※最大30文字）&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容（※最大1000文字）&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;])) echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;button class=&quot;btn--mg-c&quot; type=&quot;submit&quot; name=&quot;post_btn&quot; value=&quot;post_btn&quot;&gt;投稿&lt;/button&gt;
        &lt;/form&gt;
    &lt;/section&gt;

    &lt;hr&gt;

    &lt;!-- 投稿一覧 --&gt;
    &lt;section class=&quot;post-list&quot;&gt;
        &lt;?php if (count($post_list) === 0) : ?&gt;
            &lt;!-- 投稿が無いときはメッセージを表示する --&gt;
            &lt;p class=&quot;no-post-msg&quot;&gt;現在、投稿はありません。&lt;/p&gt;
        &lt;?php else : ?&gt;
            &lt;ul&gt;
                &lt;!-- 投稿情報の出力 --&gt;
                &lt;?php foreach ($post_list as $post_item) : ?&gt;
                    &lt;li&gt;
                        &lt;form action=&quot;&quot; method=&quot;post&quot;&gt;
                            &lt;!-- 投稿ID --&gt;
                            &lt;span&gt;ID：&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;　&lt;/span&gt;
                            &lt;!-- 投稿タイトル --&gt;
                            &lt;span&gt;&lt;?php echo $post_item[&#39;title&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿者ID --&gt;
                            &lt;span&gt;／投稿者：&lt;?php echo $post_item[&#39;contributor_id&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿内容 --&gt;
                            &lt;p class=&quot;p-pre&quot;&gt;&lt;?php echo $post_item[&#39;comment&#39;]; ?&gt;&lt;/p&gt;
                            &lt;!-- 投稿日時 --&gt;
                            &lt;span class=&quot;post-datetime&quot;&gt;投稿日時：&lt;?php echo $post_item[&#39;created_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 過去に更新されていたら更新日時も表示 --&gt;
                            &lt;?php if ($post_item[&#39;created_at&#39;] &lt; $post_item[&#39;updated_at&#39;]) : ?&gt;
                                &lt;span class=&quot;post-datetime post-datetime__updated&quot;&gt;更新日時：&lt;?php echo $post_item[&#39;updated_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;?php endif; ?&gt;
                        &lt;/form&gt;
                        &lt;!-- 自分の投稿内容かつセッションが有効な間は編集・削除が可能 --&gt;
                        &lt;?php if ($post_item[&#39;contributor_id&#39;] === $cont_id) : ?&gt;
                            &lt;div class=&quot;btn-flex&quot;&gt;
                                &lt;form action=&quot;update-edit.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;update_btn&quot;&gt;編集&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                                &lt;form action=&quot;delete-confirm.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;delete_btn&quot;&gt;削除&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                            &lt;/div&gt;
                        &lt;?php endif; ?&gt;
                        &lt;?php if (isset($_SESSION[&#39;id&#39;]) && ($_SESSION[&#39;id&#39;] == $post_item[&#39;id&#39;])): ?&gt;
                            &lt;p class=&#39;updated-post&#39;&gt;更新しました&lt;/p&gt;
                        &lt;?php endif; ?&gt;
                    &lt;/li&gt;
                &lt;?php endforeach; ?&gt;
            &lt;/ul&gt;
        &lt;?php endif; ?&gt;
    &lt;/section&gt;
&lt;/body&gt;

&lt;/html&gt;</code></pre></div>
</div></details>
</div>
</div>
</div></div>



<p class="is-style-icon_info">上記のコードの内、セキュリティ対策に関係しているコードには★マークを付けてあります。<br>ただし、XSS対策用のコードは記述箇所が多いため★マークは付けていません。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>その辺りも含め、これから詳しく解説をしていきます。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<h2 class="wp-block-heading">【解説】掲示板アプリで実施したセキュリティ対策</h2>



<p>今回のコードでは、以下の<strong><span class="swl-marker mark_yellow">4種類のセキュリティ対策</span></strong>を実施しました。</p>



<div class="swell-block-capbox cap_box is-style-onborder_ttl2"><div class="cap_box_ttl"><span><span data-icon="LsLightbulb" data-id="0" style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" aria-hidden="true" class="swl-inline-icon"> </span><strong>掲示板アプリに実施したセキュリティ対策</strong></span></div><div class="cap_box_content">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>XSS（クロスサイト・スクリプティング）</li>



<li>CSRF（クロスサイト・リクエスト・フォージェリ）</li>



<li>SQLインジェクション</li>



<li>セッションハイジャック</li>
</ul>
</div></div>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>それぞれのセキュリティ攻撃ついての詳しい解説は（セッションハイジャックを除き）以下の記事でまとめています。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>

<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">あわせて読みたい</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2024/04/eye-catch__xss-php__961-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/xss-php/">【XSS】クロスサイト・スクリプティングとは？対策方法も解説【PHP】</a>
						<span class="p-blogCard__excerpt">今回はWebアプリにおけるセキュリティ攻撃の１つであるXSS（クロスサイト・スクリプティング）について解説をしていきます。  この記事を読むと分かること XSS（クロス&#8230;</span>					</div>
				</div>
			</div>
		</div>

<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">あわせて読みたい</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2024/04/eye-catch__csrf-php__918-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/csrf-php/">【CSRF】攻撃の流れやPHPでの対策方法を解説【クロスサイトリクエストフォージェリ】</a>
						<span class="p-blogCard__excerpt">Webサイトへのセキュリティ攻撃の１つにCSRF（クロスサイトリクエストフォージェリ）というものがあります。 この記事では、 CSRFの攻撃の流れ 攻撃による影響・被害 PH&#8230;</span>					</div>
				</div>
			</div>
		</div>

<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">あわせて読みたい</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2024/04/eye-catch__sql-inj-php__1106-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/sql-inj-php/">【PHP】SQLインジェクションの原因や攻撃手法【対策コード付き】</a>
						<span class="p-blogCard__excerpt">この記事ではセキュリティ攻撃の１つであるSQLインジェクションについて、その対策方法も含めて解説をしていきます。  この記事で分かること SQLインジェクション攻撃の&#8230;</span>					</div>
				</div>
			</div>
		</div>


<p>とは言え、まったく知識が無いとプログラムコードを見ても何をしているのかイメージしづらくなってしまうため、各セキュリティ攻撃について簡単にご説明します。</p>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h3 class="wp-block-heading">XSS（クロスサイト・スクリプティング）</h3>



<div class="swell-block-capbox cap_box is-style-onborder_ttl2" data-colset="col3"><div class="cap_box_ttl"><span><strong>XSS（クロスサイト・スクリプティング）</strong>とは</span></div><div class="cap_box_content">
<p><strong>XSS（クロスサイト・スクリプティング）</strong>は、Webサイト内に悪意あるスクリプトを埋め込む攻撃です。</p>



<p>例えば、悪意あるスクリプトが埋め込まれているサイトへユーザがアクセスしてしまうと、そのユーザのブラウザ上で悪意のあるスクリプトが実行され、個人情報漏洩などに繋がります。</p>



<p>掲示板アプリで言うと、投稿内にスクリプトを埋め込まれるイメージです。</p>
</div></div>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/困った顔-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/困った顔-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>ただ掲示板アプリを利用したいだけのユーザからしたら堪ったものではないですね……。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>詳しくは後述しますが</p>



<p class="is-style-big_icon_point">XSS（クロスサイト・スクリプティング）対策のキーワードは「<strong>エスケープ処理</strong>」です。</p>



<h3 class="wp-block-heading">CSRF（クロスサイト・リクエスト・フォージェリ）</h3>



<div class="swell-block-capbox cap_box is-style-onborder_ttl2" data-colset="col3"><div class="cap_box_ttl"><span><strong><strong>CSRF（クロスサイト・リクエスト・フォージェリ）</strong></strong>とは</span></div><div class="cap_box_content">
<p><strong>CSRF（クロスサイト・リクエスト・フォージェリ）</strong>は、悪意あるスクリプトが含まれているボタンやリンクをユーザにクリックさせることで、攻撃対象のサイトへ何らかの攻撃を仕掛けるセキュリティ攻撃です。</p>



<p>例えば、迷惑メールのリンクをクリックした先に罠サイトがあり、その中のボタンなどを押下してしまうと、攻撃対象の掲示板サイトに不正投稿が行われてしまうといった攻撃です。</p>
</div></div>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/困った顔-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/困った顔-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>ユーザからすると、例えば知らない内に「脅迫的内容の投稿」をしていたことになっていて、突然逮捕されてしまうといった事態になったりします。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>この対策を怠ると被害を被るのは運営者だけではないということですね。</p>



<p>また、掲示板サイトでCSRF対策を怠ると、簡単に外部サイトから投稿することができてしまい、一般ユーザに多大な迷惑がかかります。</p>



<p>詳しくは後述しますが</p>



<p class="is-style-big_icon_point">CSRF攻撃へ有効な対策は「<strong>トークン認証</strong>」です。</p>



<h3 class="wp-block-heading">SQLインジェクション</h3>



<div class="swell-block-capbox cap_box is-style-onborder_ttl2" data-colset="col3"><div class="cap_box_ttl"><span><strong><strong><strong>SQLインジェクション</strong></strong></strong>とは</span></div><div class="cap_box_content">
<p><strong>SQLインジェクション</strong>はデータベース処理の脆弱性をつき、不正なSQLを注入（インジェクション）することでログイン情報などを抜き取る攻撃手法です。</p>
</div></div>



<p>本掲示板アプリでは個人情報は保持しない仕様ですが、SQLインジェクションを許容してしまうと最悪の場合、投稿内容をすべて削除されてしまう事態にもなりかねないため対策が欠かせません。</p>



<p>ただ、実はこちらのSQLインジェクション対策については、元々の<strong>掲示板アプリ記事の時点ですでに処理が実装されています。</strong></p>



<p>それに加えてPDOクラスを扱う際のオプションのひとつを追加しただけという形になります。</p>



<h3 class="wp-block-heading">セッションハイジャック</h3>



<div class="swell-block-capbox cap_box is-style-onborder_ttl2" data-colset="col3"><div class="cap_box_ttl"><span><strong>セッションハイジャック</strong>とは</span></div><div class="cap_box_content">
<p><strong>セッションハイジャック</strong>は、文字通りセッションを乗っ取る攻撃手法です。</p>
</div></div>



<p>本掲示板アプリではセッションを利用したユーザ識別を行ない、それにより編集や削除機能を有効化しています。</p>



<p>つまり</p>



<p>セッションを乗っ取られたら、簡単に投稿内容を編集されたり削除されたりしてしまい、ユーザが大きな被害を被ることになってしまいます。</p>



<p>セッションハイジャックが起こる原因はいくつかありますが</p>



<p class="is-style-big_icon_point">有効な対処法は「ページ遷移の度にセッションIDを刷新する」</p>



<p>です。</p>



<p>これにより、仮にセッションを一時的にでも乗っ取られてもページ遷移した際にセッションIDが新しくなるため、ハイジャックは解除されます。</p>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">【解説】セキュリティ対策ごとのソースコード</h2>



<p>ここからは<strong><span class="swl-marker mark_yellow">実際のコードを見ながらセキュリティ対策について解説</span></strong>をしていきます。</p>



<h3 class="wp-block-heading">XSS（クロスサイト・スクリプティング）</h3>



<p>まずはXSS対策からです。</p>



<p>こちらの対策箇所は唯一★マークを付けていませんが、方法はシンプルで、<span><span class="marker-under" style=""><b>掲示板上で何かしら出力する部分に対してhtmlspecialchars</b></span></span><strong>関数</strong><strong><span class="marker-under">を利用</span>し、エスケープ処理を施しています。</strong></p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>htmlspecialchars($post_item[&#39;title&#39;], ENT_QUOTES, &#39;UTF-8&#39;);</code></pre></div>



<p>こちらは、ユーザが掲示板へ投稿した<strong>投稿のタイトル（$post_item[&#8216;title]）を出力する箇所</strong>の記述です。</p>



<p>通常であれば、<strong>$post_item[&#8216;title]</strong>と記述していたところに、htmlspecialcharsというPHPの関数で囲ってあげているという形です。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>これにより、<strong>$post_item[&#8216;title]</strong>をエスケープ処理し、不正な入力値（スクリプト）が紛れていたとしてもそれをただの文字列として表示させる＝実行させないようにすることが可能です。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>引数が後ろに２つ付いていますが、<strong>第二引数のENT_QUOTES</strong>はどの文字までをエスケープ対象とするかを表しています。</p>



<p><strong>第三引数</strong>は文字コードUTF-8を基準にエスケープするという意味です。</p>



<p class="is-style-alert-box has-box-style">HTMLの文字形式（&lt;meta charset=&#8221;UTF-8&#8243;&gt;の部分）をUTF-8に指定することが推奨されます。指定しないと、攻撃者にUTF-8以外の別の文字コードに書き替えられ、htmlspecialchars関数を無効化されてしまう恐れがあります。</p>



<p>以上が<strong>XSS対策</strong>です。</p>



<p class="is-style-good-box has-box-style is-style-big_icon_point">何かしら出力する箇所はくまなくhtmlspecialchars関数でエスケープする</p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">あわせて読みたい</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2024/04/eye-catch__xss-php__961-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/xss-php/">【XSS】クロスサイト・スクリプティングとは？対策方法も解説【PHP】</a>
						<span class="p-blogCard__excerpt">今回はWebアプリにおけるセキュリティ攻撃の１つであるXSS（クロスサイト・スクリプティング）について解説をしていきます。  この記事を読むと分かること XSS（クロス&#8230;</span>					</div>
				</div>
			</div>
		</div>


<h3 class="wp-block-heading">CSRF（クロスサイト・リクエスト・フォージェリ）</h3>



<p>続くCSRFでのキーワードは「<strong>トークン認証</strong>」です。</p>



<div class="swell-block-capbox cap_box is-style-onborder_ttl2" data-colset="col3"><div class="cap_box_ttl"><span>トークン認証とは</span></div><div class="cap_box_content">
<p>トークン認証とは、いわば合言葉で正しいリクエストかどうかを認証するということです。</p>
</div></div>



<p>先ほど簡単にCSRFについてご説明をしましたが、CSRFでは攻撃対象のサイトへ不正リクエストを送信し、意図しない動作をさせます。</p>



<p>つまり、<strong><span class="swl-marker mark_yellow">攻撃を受ける側でリクエストを正しく振り分けできていれば、この攻撃は阻止できる</span></strong>のです。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>そこで使用するのが<strong>トークン</strong>と呼ばれるランダムな文字列です。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>これを実際の処理で見ると、以下のようなものになっています。</p>



<p class="is-style-balloon_box2">トークンを利用した処理</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php 
//★ 不正リクエストチェック用のトークン生成
$token = sha1(uniqid(mt_rand(), true));
$_SESSION[&#39;board_token&#39;] = $token;
echo &#39;&lt;input type=&quot;hidden&quot; name=&quot;board_token&quot; value=&quot;&#39;.$token.&#39;&quot; /&gt;&#39;;
&gt;</code></pre></div>



<p>この処理は、「投稿ボタンform」の中に組み込まれています。</p>



<p>つまり、投稿ボタンを押下すると、<span class="marker-under-red">①<strong>hidden属性で隠されたトークンが一緒にPOST送信</strong></span>されます。</p>



<p>また、その直前で<span class="marker-under-red">②<strong>セッション変数に格納</strong></span>しています。</p>



<p>そして、①と②を、<strong><span class="marker-under">実際に投稿処理を行う前に比較（以下の処理）し、一致すれば正しいリクエスト</span></strong>であると判断するという流れです。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>// ★【CSRF】トークンチェック
if(empty($_SESSION[&#39;board_token&#39;]) || ($_SESSION[&#39;board_token&#39;] !== $_POST[&#39;board_token&#39;])){
    exit(&#39;不正な投稿です&#39;);
}
if(isset($_SESSION[&#39;board_token&#39;])) unset($_SESSION[&#39;board_token&#39;]);//トークン破棄
if(isset($_POST[&#39;board_token&#39;])) unset($_POST[&#39;board_token&#39;]);//トークン破棄</code></pre></div>



<p>トークンは１回使用したらすぐに破棄します。</p>



<p>理由は</p>



<p class="has-border -border03">トークンを何度も使い回す仕様にすると、トークン自体が盗まれた時点で攻撃が成立するようになってしまうため</p>



<p>です。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>合言葉に毎回異なるものを使用することでなりすましを防いでいるのです。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>

<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">あわせて読みたい</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2024/04/eye-catch__csrf-php__918-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/csrf-php/">【CSRF】攻撃の流れやPHPでの対策方法を解説【クロスサイトリクエストフォージェリ】</a>
						<span class="p-blogCard__excerpt">Webサイトへのセキュリティ攻撃の１つにCSRF（クロスサイトリクエストフォージェリ）というものがあります。 この記事では、 CSRFの攻撃の流れ 攻撃による影響・被害 PH&#8230;</span>					</div>
				</div>
			</div>
		</div>


<h3 class="wp-block-heading">SQLインジェクション</h3>



<p>SQLインジェクション対策として追記しているのは以下の★マークの箇所です。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP" data-line="[5,6,7]"><code>/**
 * DB接続処理
 */
$pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
    PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
    PDO::ATTR_EMULATE_PREPARES =&gt; false,              // ★【SQLインジェクション】静的プレースホルダーを使用
]);</code></pre></div>



<p>「静的プレースホルダーを使用」と書いてありますが、これを説明するにはまずプレースホルダーを理解していただく必要があります。</p>



<p><strong>プレースホルダー</strong>とは、以下の処理の部分のことです。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain" data-line="[7,8,12,13,14,15]"><code>/**
* 投稿内容登録処理
*/
$sql = (&#39;
    INSERT INTO
        board_info (title, comment, contributor_id)
    VALUES
        (:TITLE, :COMMENT, :CONTRIBUTOR_ID)
    &#39;);
$stmt = $pdo-&gt;prepare($sql);
// プレースホルダーに値をセット
$stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
$stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
$stmt-&gt;bindValue(&#39;:CONTRIBUTOR_ID&#39;, $cont_id, PDO::PARAM_STR);
</code></pre></div>



<p>注目して頂きたいのはハイライトされている箇所の「:」が付いている変数です。</p>



<p>これがいわゆる<strong>プレースホルダー</strong>と呼ばれるもので、意味としては「一時的なスペース」です。</p>



<p>なぜこのようなものを使用しているのかというと、プレースホルダーを間に挟むことで不正なSQLの実行を阻止することができるためです。</p>



<p>詳しいご説明は割愛させて頂きますが、このプレースホルダーには<strong>静的</strong>と<strong>動的</strong>の2種類があり、静的プレースホルダーを利用すると、SQLの構造が確定するタイミングと実行タイミングの兼ね合いから、<strong><span class="marker-under">理論上SQLインジェクションが成功しなくなる</span></strong>のです。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>SQLインジェクションは、後からSQLの構造を無理やり変えることで不正な操作を行います。<br>しかし、静的プレースホルダーを利用すると、後から構造が変わることが無くなるため、SQLインジェクションが成立しなくなります。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>Webアプリケーションの仕様によっては動的プレースホルダーを利用する必要がある場合も出てくるのですが、そうでないのなら<strong><span class="marker-under">静的プレースホルダーを利用するのが確実</span></strong>です。</p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">あわせて読みたい</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2024/04/eye-catch__sql-inj-php__1106-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/sql-inj-php/">【PHP】SQLインジェクションの原因や攻撃手法【対策コード付き】</a>
						<span class="p-blogCard__excerpt">この記事ではセキュリティ攻撃の１つであるSQLインジェクションについて、その対策方法も含めて解説をしていきます。  この記事で分かること SQLインジェクション攻撃の&#8230;</span>					</div>
				</div>
			</div>
		</div>


<h3 class="wp-block-heading">セッションハイジャック</h3>



<p>先ほど、セッションハイジャックの説明の中で、ページ遷移ごとにセッションIDを刷新することが対策になるとお伝えしました。</p>



<p>それを行っているのが以下の箇所です。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain" data-line="[9,10,11]"><code>/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
// ★【セッションハイジャック】セッションIDを新しいものに置き換える
session_regenerate_id();
</code></pre></div>



<p><strong>session_regenerate_id()</strong>関数は、セッションIDを新しいものと置き換える関数です。</p>



<p>その際、セッションに元々格納済みのデータは維持されます。</p>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">【まとめ】正しいセキュリティ対策で安全なWebアプリケーション開発を</h2>



<p>最後に改めて、セキュリティ対策を施した全体のコードを掲載します。</p>



<div class="swell-block-tab is-style-balloon has-border -border01" data-width-pc="auto" data-width-sp="auto"><ul class="c-tabList" role="tablist"><li class="c-tabList__item" role="presentation"><button role="tab" class="c-tabList__button" aria-selected="true" aria-controls="tab-159a1a47-0" data-onclick="tabControl">掲示板アプリ全体のコード</button></li><li class="c-tabList__item" role="presentation"><button role="tab" class="c-tabList__button" aria-selected="false" aria-controls="tab-159a1a47-1" data-onclick="tabControl">style.css</button></li></ul><div class="c-tabBody">
<div id="tab-159a1a47-0" class="c-tabBody__item" aria-hidden="false">
<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">board.php（掲示板トップ）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * 投稿者ID（20桁）を生成
 */
if (isset($_SESSION[&#39;cont_id&#39;])) {
    $cont_id = $_SESSION[&#39;cont_id&#39;];
} else {
    $_SESSION[&#39;cont_id&#39;] = 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90));
    $cont_id = $_SESSION[&#39;cont_id&#39;];
}
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;
/**
 * 投稿ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;post_btn&#39;])) {
    // 更新操作用の処理
    unset($_SESSION[&#39;id&#39;]);
    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }
    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }
    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;
    /**
     * 必要項目がすべて入力されてたら投稿処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                INSERT INTO
                    board_info (title, comment, contributor_id)
                VALUES
                    (:TITLE, :COMMENT, :CONTRIBUTOR_ID)
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:CONTRIBUTOR_ID&#39;, $cont_id, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿に成功したらセッション変数を破棄
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 投稿一覧取得処理
 */
try {
    /**
     * DB接続処理
     */
    $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
        PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
        PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
    ]);
    $sql = (&#39;
        SELECT * 
        FROM board_info 
        ORDER BY id DESC
    &#39;);
    $stmt = $pdo-&gt;prepare($sql);
    // SQL実行
    $stmt-&gt;execute();
    // 投稿情報を辞書形式ですべて取得
    $post_list = $stmt-&gt;fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    echo &#39;接続失敗&#39; . $e-&gt;getMessage();
    exit();
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;掲示板アプリ&lt;/h1&gt;
    &lt;!-- 投稿フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル（※最大30文字）&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容（※最大1000文字）&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;])) echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;button class=&quot;btn--mg-c&quot; type=&quot;submit&quot; name=&quot;post_btn&quot; value=&quot;post_btn&quot;&gt;投稿&lt;/button&gt;
        &lt;/form&gt;
    &lt;/section&gt;
    &lt;hr&gt;
    &lt;!-- 投稿一覧 --&gt;
    &lt;section class=&quot;post-list&quot;&gt;
        &lt;?php if (count($post_list) === 0) : ?&gt;
            &lt;!-- 投稿が無いときはメッセージを表示する --&gt;
            &lt;p class=&quot;no-post-msg&quot;&gt;現在、投稿はありません。&lt;/p&gt;
        &lt;?php else : ?&gt;
            &lt;ul&gt;
                &lt;!-- 投稿情報の出力 --&gt;
                &lt;?php foreach ($post_list as $post_item) : ?&gt;
                    &lt;li&gt;
                        &lt;form action=&quot;&quot; method=&quot;post&quot;&gt;
                            &lt;!-- 投稿ID --&gt;
                            &lt;span&gt;ID：&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;　&lt;/span&gt;
                            &lt;!-- 投稿タイトル --&gt;
                            &lt;span&gt;&lt;?php echo $post_item[&#39;title&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿者ID --&gt;
                            &lt;span&gt;／投稿者：&lt;?php echo $post_item[&#39;contributor_id&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿内容 --&gt;
                            &lt;p class=&quot;p-pre&quot;&gt;&lt;?php echo $post_item[&#39;comment&#39;]; ?&gt;&lt;/p&gt;
                            &lt;!-- 投稿日時 --&gt;
                            &lt;span class=&quot;post-datetime&quot;&gt;投稿日時：&lt;?php echo $post_item[&#39;created_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 過去に更新されていたら更新日時も表示 --&gt;
                            &lt;?php if ($post_item[&#39;created_at&#39;] &lt; $post_item[&#39;updated_at&#39;]) : ?&gt;
                                &lt;span class=&quot;post-datetime post-datetime__updated&quot;&gt;更新日時：&lt;?php echo $post_item[&#39;updated_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;?php endif; ?&gt;
                        &lt;/form&gt;
                        &lt;!-- 自分の投稿内容かつセッションが有効な間は編集・削除が可能 --&gt;
                        &lt;?php if ($post_item[&#39;contributor_id&#39;] === $cont_id) : ?&gt;
                            &lt;div class=&quot;btn-flex&quot;&gt;
                                &lt;form action=&quot;update-edit.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;update_btn&quot;&gt;編集&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                                &lt;form action=&quot;delete-confirm.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;delete_btn&quot;&gt;削除&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                            &lt;/div&gt;
                        &lt;?php endif; ?&gt;
                        &lt;?php if (isset($_SESSION[&#39;id&#39;]) && ($_SESSION[&#39;id&#39;] == $post_item[&#39;id&#39;])): ?&gt;
                            &lt;p class=&#39;updated-post&#39;&gt;更新しました&lt;/p&gt;
                        &lt;?php endif; ?&gt;
                    &lt;/li&gt;
                &lt;?php endforeach; ?&gt;
            &lt;/ul&gt;
        &lt;?php endif; ?&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>



<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">update-edit.php（編集画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;
/**
 * 編集ボタンで遷移してきたときの処理
 */
if (isset($_POST[&#39;update_btn&#39;])) {
    /**
     * 編集対象の投稿情報を取得
     */
    if (isset($_POST[&#39;post_id&#39;]) && $_POST[&#39;post_id&#39;] != &#39;&#39;) {
        // セッションに投稿IDを保持
        $_SESSION[&#39;id&#39;] = $_POST[&#39;post_id&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容取得処理
             */
            $sql = (&#39;
                SELECT id, title, comment
                FROM board_info 
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿情報の取得
            $post_info = $stmt-&gt;fetch();
            $_SESSION[&#39;title&#39;] = $post_info[&#39;title&#39;];
            $_SESSION[&#39;comment&#39;] = $post_info[&#39;comment&#39;];
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 更新ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;update_submit_btn&#39;])) {
    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }
    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }
    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;
    /**
     * 必要項目がすべて入力されてたら更新処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容更新処理
             */
            $sql = (&#39;
                UPDATE board_info 
                SET title = :TITLE, comment = :COMMENT
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();
            // 更新に成功したらセッション変数を破棄
            // unset($_SESSION[&#39;id&#39;]);  // ※投稿IDは敢えて破棄せず、掲示板ページでID判定をするために情報を保持する★
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
            // 掲示板ページへ戻る
            header(&#39;Location: board.php&#39;);
            exit();
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * キャンセルボタンが押下されたら
 * セッション情報を破棄して
 * 掲示板一覧画面へ戻る
 */
if (isset($_POST[&#39;cancel_btn&#39;])) {
    unset($_SESSION[&#39;id&#39;]);
    unset($_SESSION[&#39;title&#39;]);
    unset($_SESSION[&#39;comment&#39;]);
    header(&#39;Location: board.php&#39;);
    exit();
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;投稿編集画面&lt;/h1&gt;
    &lt;!-- 投稿編集フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;]))  echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;; ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;btn-flex&quot;&gt;
                &lt;button type=&quot;submit&quot; name=&quot;update_submit_btn&quot; value=&quot;update_submit_btn&quot;&gt;更新&lt;/button&gt;
                &lt;button type=&quot;submit&quot; name=&quot;cancel_btn&quot; value=&quot;cancel_btn&quot;&gt;キャンセル&lt;/button&gt;
            &lt;/div&gt;
        &lt;/form&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>



<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">delete-confirm.php（削除確認画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;
/**
 * 削除ボタンで遷移してきたときの処理
 */
if (isset($_POST[&#39;delete_btn&#39;])) {
    /**
     * 編集対象の投稿情報を取得
     */
    if (isset($_POST[&#39;post_id&#39;]) && $_POST[&#39;post_id&#39;] != &#39;&#39;) {
        // セッションに投稿IDを保持
        $_SESSION[&#39;id&#39;] = $_POST[&#39;post_id&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                SELECT id, title, comment
                FROM board_info 
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿情報の取得
            $post_info = $stmt-&gt;fetch();
            $_SESSION[&#39;title&#39;] = $post_info[&#39;title&#39;];
            $_SESSION[&#39;comment&#39;] = $post_info[&#39;comment&#39;];
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 削除ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;delete_submit_btn&#39;])) {
    try {
        /**
         * DB接続処理
         */
        $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
            PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
        ]);
        /**
         * 投稿内容削除処理
         */
        $sql = (&#39;
            DELETE FROM board_info 
            WHERE id = :ID
        &#39;);
        $stmt = $pdo-&gt;prepare($sql);
        // プレースホルダーに値をセット
        $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
        // SQL実行
        $stmt-&gt;execute();
        // 削除に成功したらセッション変数を破棄
        unset($_SESSION[&#39;id&#39;]);
        unset($_SESSION[&#39;title&#39;]);
        unset($_SESSION[&#39;comment&#39;]);
        // 削除成功画面へ遷移
        header(&#39;Location: delete-success.php&#39;);
        exit();
    } catch (PDOException $e) {
        echo &#39;接続失敗&#39; . $e-&gt;getMessage();
        exit();
    }
    // DBとの接続を切る
    $pdo = null;
    $stmt = null;
}
/**
 * キャンセルボタンが押下されたら
 * セッション情報を破棄して
 * 掲示板一覧画面へ戻る
 */
if (isset($_POST[&#39;cancel_btn&#39;])) {
    unset($_SESSION[&#39;id&#39;]);
    unset($_SESSION[&#39;title&#39;]);
    unset($_SESSION[&#39;comment&#39;]);
    header(&#39;Location: board.php&#39;);
    return;
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;削除確認&lt;/h1&gt;
    &lt;p class=&quot;delete-confirm-msg&quot;&gt;以下の投稿を削除します。&lt;/p&gt;
    &lt;!-- 削除確認画面 --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;p&gt;タイトル&lt;/p&gt;
                    &lt;p&gt;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&lt;/p&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;p&gt;投稿内容&lt;/p&gt;
                    &lt;p class=&quot;p-pre&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;]))  echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/p&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;btn-flex&quot;&gt;
                &lt;button type=&quot;submit&quot; name=&quot;delete_submit_btn&quot; value=&quot;delete_submit_btn&quot;&gt;削除&lt;/button&gt;
                &lt;button type=&quot;submit&quot; name=&quot;cancel_btn&quot; value=&quot;cancel_btn&quot;&gt;キャンセル&lt;/button&gt;
            &lt;/div&gt;
        &lt;/form&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>



<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">delete-success.php（削除成功画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * 掲示場TOPへ自動で遷移する処理★
 */
header(&#39;refresh: 3; url=board.php&#39;);
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;削除が完了しました。&lt;/h1&gt;
    &lt;p class=&quot;delete-success-msg&quot;&gt;3秒後に自動で掲示板TOPへ戻ります。&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>
</div>
</div>



<div id="tab-159a1a47-1" class="c-tabBody__item" aria-hidden="true">
<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">style.css（同じ見た目にしたい方用）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-css" data-lang="CSS"><code>body {
    margin: 0 auto;
    width: 700px;
    background-color: rgb(224, 224, 224);
}
hr {
    margin: 40px 0;
    border-color: rgb(137, 137, 137);
}
h1 {
    text-align: center;
}
li {
    list-style: none;
}
p {
    margin: 0;
}
p,
span {
    color: #333;
}
input,
textarea {
    padding: 10px;
    border: 1px solid gray;
    border-radius: 10px;
    width: 100%;
    box-sizing: border-box;
}
textarea {
    line-height: 1.5;
}
button {
    display: block;
    margin-top: 20px;
    padding: 10px 30px;
    color: #fff;
    border-radius: 10px;
    cursor: pointer;
}
button[name=&quot;post_btn&quot;] {
    border: 1px solid rgb(148, 148, 218);
    background-color: rgb(94, 94, 255);
}
button[name=&quot;update_btn&quot;],
button[name=&quot;update_submit_btn&quot;] {
    border: 1px solid rgb(62, 150, 62);
    background-color: rgb(74, 152, 74);
}
button[name=&quot;delete_btn&quot;],
button[name=&quot;delete_submit_btn&quot;] {
    border: 1px solid rgb(255, 31, 31);
    background-color: rgb(255, 48, 48);
}
button[name=&quot;cancel_btn&quot;] {
    border: 1px solid rgb(172, 172, 172);
    background-color: rgb(182, 182, 182);
}
button[name=&quot;post_btn&quot;]:hover {
    background-color: rgb(116, 116, 255);
}
button[name=&quot;update_btn&quot;]:hover,
button[name=&quot;update_submit_btn&quot;]:hover {
    background-color: rgb(83, 169, 83);
}
button[name=&quot;delete_btn&quot;]:hover,
button[name=&quot;delete_submit_btn&quot;]:hover {
    background-color: rgb(255, 82, 82);
}
button[name=&quot;cancel_btn&quot;]:hover {
    background-color: rgb(189, 189, 189);
}
.btn--mg-c {
    margin: 0 auto;
}
.post-list button {
    margin: 30px 0 0 0;
    padding: 8px 20px;
}
.post-list li {
    margin-bottom: 15px;
    padding: 20px 30px;
    background-color: #fff;
    border: 1px solid rgb(188, 188, 188);
    border-radius: 10px;
}
.post-list span {
    display: inline-block;
    margin-bottom: 25px;
}
.post-form__flex {
    display: flex;
    justify-content: center;
    column-gap: 15px;
    margin-bottom: 20px;
}
.post-form__flex&gt;div:first-child {
    width: 250px;
}
.post-form__flex&gt;div:last-child {
    flex: 1;
}
.btn-flex {
    display: flex;
    justify-content: center;
    column-gap: 15px;
}
.post-list li:last-child {
    margin-bottom: 0;
}
.post-datetime {
    display: inline-block;
    margin-top: 25px;
    font-size: 12px;
    color: gray;
}
.post-datetime__updated {
    display: inline-block;
    margin-left: 10px;
}
.updated-post {
    margin-left: auto;
    padding: 2px 5px;
    width: fit-content;
    font-size: 12px;
    border: 1px solid rgb(105, 105, 105);
    border-radius: 5px;
    color: rgb(105, 105, 105);
}
.no-post-msg {
    text-align: center;
}
.delete-confirm-msg {
    text-align: center;
    margin-bottom: 30px;
    color: red;
    font-weight: bold;
}
.delete-success-msg {
    text-align: center;
}
.err {
    color: red;
    font-size: 13px;
}
/* 
改行もそのまま表示するための指定
これが無いと改行が半角スペースに変換されて
表示されてしまう
 */
.p-pre {
    white-space: pre-wrap;
}</code></pre></div>
</div></details>
</div>
</div>



<div id="tab-159a1a47-2" class="c-tabBody__item" aria-hidden="true">
<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">board.php</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php

/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();

/**
 * 投稿者ID（20桁）を生成
 */
if (isset($_SESSION[&#39;cont_id&#39;])) {
    $cont_id = $_SESSION[&#39;cont_id&#39;];
} else {
    $_SESSION[&#39;cont_id&#39;] = 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90));
    $cont_id = $_SESSION[&#39;cont_id&#39;];
}

/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;

/**
 * 投稿ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;post_btn&#39;])) {

    // 更新操作用の処理
    unset($_SESSION[&#39;id&#39;]);

    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }

    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }

    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;

    /**
     * 必要項目がすべて入力されてたら投稿処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];

        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);

            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                INSERT INTO
                    board_info (title, comment, contributor_id)
                VALUES
                    (:TITLE, :COMMENT, :CONTRIBUTOR_ID)
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:CONTRIBUTOR_ID&#39;, $cont_id, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();

            // 投稿に成功したらセッション変数を破棄
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}

/**
 * 投稿一覧取得処理
 */
try {
    /**
     * DB接続処理
     */
    $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
        PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
        PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
    ]);

    $sql = (&#39;
        SELECT * 
        FROM board_info 
        ORDER BY id DESC
    &#39;);
    $stmt = $pdo-&gt;prepare($sql);

    // SQL実行
    $stmt-&gt;execute();

    // 投稿情報を辞書形式ですべて取得
    $post_list = $stmt-&gt;fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    echo &#39;接続失敗&#39; . $e-&gt;getMessage();
    exit();
}

?&gt;

&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;

&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;h1&gt;掲示板アプリ&lt;/h1&gt;

    &lt;!-- 投稿フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル（※最大30文字）&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容（※最大1000文字）&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;])) echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;button class=&quot;btn--mg-c&quot; type=&quot;submit&quot; name=&quot;post_btn&quot; value=&quot;post_btn&quot;&gt;投稿&lt;/button&gt;
        &lt;/form&gt;
    &lt;/section&gt;

    &lt;hr&gt;

    &lt;!-- 投稿一覧 --&gt;
    &lt;section class=&quot;post-list&quot;&gt;
        &lt;?php if (count($post_list) === 0) : ?&gt;
            &lt;!-- 投稿が無いときはメッセージを表示する --&gt;
            &lt;p class=&quot;no-post-msg&quot;&gt;現在、投稿はありません。&lt;/p&gt;
        &lt;?php else : ?&gt;
            &lt;ul&gt;
                &lt;!-- 投稿情報の出力 --&gt;
                &lt;?php foreach ($post_list as $post_item) : ?&gt;
                    &lt;li&gt;
                        &lt;form action=&quot;&quot; method=&quot;post&quot;&gt;
                            &lt;!-- 投稿ID --&gt;
                            &lt;span&gt;ID：&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;　&lt;/span&gt;
                            &lt;!-- 投稿タイトル --&gt;
                            &lt;span&gt;&lt;?php echo $post_item[&#39;title&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿者ID --&gt;
                            &lt;span&gt;／投稿者：&lt;?php echo $post_item[&#39;contributor_id&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿内容 --&gt;
                            &lt;p class=&quot;p-pre&quot;&gt;&lt;?php echo $post_item[&#39;comment&#39;]; ?&gt;&lt;/p&gt;
                            &lt;!-- 投稿日時 --&gt;
                            &lt;span class=&quot;post-datetime&quot;&gt;投稿日時：&lt;?php echo $post_item[&#39;created_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 過去に更新されていたら更新日時も表示 --&gt;
                            &lt;?php if ($post_item[&#39;created_at&#39;] &lt; $post_item[&#39;updated_at&#39;]) : ?&gt;
                                &lt;span class=&quot;post-datetime post-datetime__updated&quot;&gt;更新日時：&lt;?php echo $post_item[&#39;updated_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;?php endif; ?&gt;
                        &lt;/form&gt;
                        &lt;!-- 自分の投稿内容かつセッションが有効な間は編集・削除が可能 --&gt;
                        &lt;?php if ($post_item[&#39;contributor_id&#39;] === $cont_id) : ?&gt;
                            &lt;div class=&quot;btn-flex&quot;&gt;
                                &lt;form action=&quot;update-edit.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;update_btn&quot;&gt;編集&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                                &lt;form action=&quot;delete-confirm.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;delete_btn&quot;&gt;削除&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                            &lt;/div&gt;
                        &lt;?php endif; ?&gt;
                        &lt;?php if (isset($_SESSION[&#39;id&#39;]) && ($_SESSION[&#39;id&#39;] == $post_item[&#39;id&#39;])): ?&gt;
                            &lt;p class=&#39;updated-post&#39;&gt;更新しました&lt;/p&gt;
                        &lt;?php endif; ?&gt;
                    &lt;/li&gt;
                &lt;?php endforeach; ?&gt;
            &lt;/ul&gt;
        &lt;?php endif; ?&gt;
    &lt;/section&gt;
&lt;/body&gt;

&lt;/html&gt;</code></pre></div>
</div></details>
</div>
</div>
</div></div>



<p>今回は前回こちらの記事で解説をした掲示板アプリにおける<strong>セキュリティ対策</strong>について解説をしてきました。</p>


<div class="swell-block-postLink">			<div class="p-blogCard -external" data-type="type3" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">ケケンタの独学ITブログ</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/eye-catch__board-app-php__2739.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/board-app-php/" target="_blank" rel="noopener noreferrer">掲示板アプリの作り方｜プログラミング初心者向け【PHP】 | ケケンタの独学ITブログ</a>
						<span class="p-blogCard__excerpt">初心者向けにPHPで掲示板アプリを作成する方法を解説しています。PHPの基礎学習後、初めてのWebアプリ開発におすすめの記事です。</span>					</div>
				</div>
			</div>
		</div>


<p>しかし、実を言うと</p>



<p class="has-border -border03">セキュリティ対策に100%は無く、<strong>できるだけ防御率を100%に近づける</strong>という考え方が正しい</p>



<p>です。</p>



<p>また、<strong><span class="marker-under">アプリの仕様によって取るべき対策は異なります。</span></strong>そのため、セキュリティ対策の知識はある意味プログラミング言語の学習よりも重要で大変なものだったりします。</p>



<p>僕は以下の書籍（通称「徳丸本」と呼ばれるWeb開発者必携の書籍です）を参考に、いつもWebアプリ開発をしています。</p>


<div id="rinkerid3655" class="yyi-rinker-contents  yyi-rinker-postid-3655 yyi-rinker-img-m yyi-rinker-catid-5 yyi-rinker-catid-72 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://hb.afl.rakuten.co.jp/hgc/g00q072g.bdzz22a5.g00q072g.bdzz326e/Rinker_i_20240325051043?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fbook%2F15472730%2F&#038;m=http%3A%2F%2Fm.rakuten.co.jp%2Fbook%2Fi%2F19130417%2F&#038;rafcid=wsc_i_is_1047822029026699702" rel="nofollow" class="yyi-rinker-tracking"  data-click-tracking="rakuten_img 3655 体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 [ 徳丸 浩 ]" data-vars-click-id="rakuten_img 3655 体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 [ 徳丸 浩 ]"><img decoding="async" src="https://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/3163/9784797393163.jpg?_ex=128x128"  width="128" height="128" class="yyi-rinker-main-img" style="border: none;"></a>					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://hb.afl.rakuten.co.jp/hgc/g00q072g.bdzz22a5.g00q072g.bdzz326e/Rinker_t_20240325051043?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fbook%2F15472730%2F&#038;m=http%3A%2F%2Fm.rakuten.co.jp%2Fbook%2Fi%2F19130417%2F&#038;rafcid=wsc_i_is_1047822029026699702" rel="nofollow" class="yyi-rinker-tracking" data-click-tracking="rakuten_title 3655 体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 [ 徳丸 浩 ]" data-vars-amp-click-id="rakuten_title 3655 体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 [ 徳丸 浩 ]" >体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 [ 徳丸 浩 ]</a>							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							<span title="" class="price">¥3,520</span>
															<span class="price_at">(2026/04/18 17:08:50時点&nbsp;楽天市場調べ-</span><span title="このサイトで掲載されている情報は当サイトの作成者により運営されています。価格、販売可能情報は、変更される場合があります。購入時に楽天市場店舗（www.rakuten.co.jp）に表示されている価格がその商品の販売に適用されます。">詳細)</span>
																	</div>
						</div>
						<ul class="yyi-rinker-links">
																	<li class="amazonkindlelink">
						<a href="https://www.amazon.co.jp/%E4%BD%93%E7%B3%BB%E7%9A%84%E3%81%AB%E5%AD%A6%E3%81%B6-%E5%AE%89%E5%85%A8%E3%81%AAWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-%E7%AC%AC2%E7%89%88%EF%BC%BB%E5%9B%BA%E5%AE%9A%E7%89%88%EF%BC%BD-%E8%84%86%E5%BC%B1%E6%80%A7%E3%81%8C%E7%94%9F%E3%81%BE%E3%82%8C%E3%82%8B%E5%8E%9F%E7%90%86%E3%81%A8%E5%AF%BE%E7%AD%96%E3%81%AE%E5%AE%9F%E8%B7%B5-%E5%BE%B3%E4%B8%B8-%E6%B5%A9-ebook/dp/B07DVY4H3M?_encoding=UTF8&amp;dib_tag=se&amp;dib=eyJ2IjoiMSJ9.ksxMxdA4KTXnYLFgVxMFijL3FSdFSR0LKwwn0F-UPgnO4-c3ozCV4u_yzlUP10v8KPCWYU6aPhFknUSSGvFmOEDGJ7u_LQxIZPLfydTHs_AWTWMCbT_FAR33FxKzQdND0le-SUmRnBHzYhR8SX_lsohxpGeQkIATYHxCJlB0aHhgwHHQ_THHRbyVElNccJqEMDb7ELZa0F--eVduuVxaejEJv9h9ZmItplRO6lE6VyZJA2Jej7Jvd7bD0ypm9krDwLy3e-Ea8YDtZc7KF66Cb-ea0Tp3FGBrFX0K3fiRlfA.KN6w39aSpN4iCwmHQ6974qNXMN0yNo0Ib071kV4gNk4&amp;qid=1723712413&amp;sr=8-6&amp;linkCode=ll1&amp;tag=kekenta03am0b-22&amp;linkId=3aee57ca3ac28d84506bf0e0db6cec11&amp;language=ja_JP&amp;ref_=as_li_ss_tl" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon_kindle 3655 体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 [ 徳丸 浩 ]"  data-vars-amp-click-id="amazon_kindle 3655 体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 [ 徳丸 浩 ]">Kindle</a>					</li>
								                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/%E4%BD%93%E7%B3%BB%E7%9A%84%E3%81%AB%E5%AD%A6%E3%81%B6-%E5%AE%89%E5%85%A8%E3%81%AAWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-%E7%AC%AC2%E7%89%88-%E8%84%86%E5%BC%B1%E6%80%A7%E3%81%8C%E7%94%9F%E3%81%BE%E3%82%8C%E3%82%8B%E5%8E%9F%E7%90%86%E3%81%A8%E5%AF%BE%E7%AD%96%E3%81%AE%E5%AE%9F%E8%B7%B5-%E5%BE%B3%E4%B8%B8/dp/4797393165?dib=eyJ2IjoiMSJ9.ksxMxdA4KTXnYLFgVxMFijL3FSdFSR0LKwwn0F-UPgnO4-c3ozCV4u_yzlUP10v8KPCWYU6aPhFknUSSGvFmOEDGJ7u_LQxIZPLfydTHs_AWTWMCbT_FAR33FxKzQdND0le-SUmRnBHzYhR8SX_lsohxpGeQkIATYHxCJlB0aHhgwHHQ_THHRbyVElNccJqEMDb7ELZa0F--eVduuVxaejEJv9h9ZmItplRO6lE6VyZJA2Jej7Jvd7bD0ypm9krDwLy3e-Ea8YDtZc7KF66Cb-ea0Tp3FGBrFX0K3fiRlfA.KN6w39aSpN4iCwmHQ6974qNXMN0yNo0Ib071kV4gNk4&amp;dib_tag=se&amp;keywords=%E5%AE%89%E5%85%A8%E3%81%AAWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3&amp;qid=1723712376&amp;sr=8-1&amp;linkCode=ll1&amp;tag=https://www.amazon.co.jp/PHP%E6%9C%AC%E6%A0%BC%E5%85%A5%E9%96%80-%E4%B8%8A-%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%A8%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E3%81%AE%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E9%80%A3%E6%90%BA%E3%81%BE%E3%81%A7-%E5%A4%A7%E5%AE%B6-%E6%AD%A3%E7%99%BB/dp/4297114682?dib=eyJ2IjoiMSJ9.74YDItYNn-AHro6XQ1cSslRSHUvp_S8S4MVJtvnW_XswliMGieYQktGbaTJY9E-Qpy3y3roMKB8M-zKI3K7otpqjDxkuoq7ncq-6mLf3BEkcNW05BAHDZZ17WZueAniDY7peSrmp4Ji0L0BkXOaJIBbpqa628I6bjQBED1FQ9V7BJqUJVUUxz6ns2GIHnoSItDTgCRaIpNi9fMcBrt3jqZr1qNJxCmBn8-xPR9N3usFpENEEChvMwvGdHoHu1hjsq6g9GvJDwPPBTwhQvDgXG2KZQ5CBlEx_wQjQy06hFcw.xxCKw6aGhA397JIEATXvL3RNC7D4_k4avRIYczzkjHw&amp;dib_tag=se&amp;keywords=PHP%E6%9C%AC%E6%A0%BC%E5%85%A5%E9%96%80&amp;qid=1723712413&amp;sr=8-6&amp;linkCode=ll1&amp;tag=kekenta03am0b-22&amp;linkId=16a4b7edeeedcc86aef9f0b8c45cc669&amp;language=ja_JP&amp;ref_=as_li_ss_tl-22&amp;linkId=04fec4999f3ec4094bf4fd1126da8b84&amp;language=ja_JP&amp;ref_=as_li_ss_tl" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon 3655 体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 [ 徳丸 浩 ]"  data-vars-amp-click-id="amazon 3655 体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 [ 徳丸 浩 ]">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://hb.afl.rakuten.co.jp/hgc/g00q072g.bdzz22a5.g00q072g.bdzz326e/Rinker_t_20240325051043?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fbook%2F15472730%2F&amp;m=http%3A%2F%2Fm.rakuten.co.jp%2Fbook%2Fi%2F19130417%2F&amp;rafcid=wsc_i_is_1047822029026699702" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="rakuten 3655 体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 [ 徳丸 浩 ]"  data-vars-amp-click-id="rakuten 3655 体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 [ 徳丸 浩 ]">楽天市場</a>					</li>
								                											</ul>
					</div>
	</div>
</div>



<p class="is-style-bg_stripe"><a href="https://www.amazon.co.jp/%E4%BD%93%E7%B3%BB%E7%9A%84%E3%81%AB%E5%AD%A6%E3%81%B6-%E5%AE%89%E5%85%A8%E3%81%AAWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-%E7%AC%AC2%E7%89%88-%E8%84%86%E5%BC%B1%E6%80%A7%E3%81%8C%E7%94%9F%E3%81%BE%E3%82%8C%E3%82%8B%E5%8E%9F%E7%90%86%E3%81%A8%E5%AF%BE%E7%AD%96%E3%81%AE%E5%AE%9F%E8%B7%B5-%E5%BE%B3%E4%B8%B8/dp/4797393165?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&amp;crid=1FQAOXKEGI9HT&amp;dib=eyJ2IjoiMSJ9.ksxMxdA4KTXnYLFgVxMFis4f3XHMUvarmNijcsU4Nmvl3Tud_nU0g7agEl3ercb-Os7uj_I-9w5xejzyw_JwMcs7FC4uVP9jc3sHC7c9ZuDT_gwuJFliueZNV3zuXq4731v-JAlEh4pR64KI-_puhFly0i_zkfDlsH2xTLQWoeNNIM9FkS584d43eeD8-mNtPjbtKK1lmvjecUb-VALfXImg-mACYpqlPWhTawzlYmnCmT85BL5k4gVzrtlErnyRPeFE4qCXwaN884rSGk9l6PGCfVcIoDQOg1lp8Ia-RWA.i4wIGc7KFczkxeNgrmVo03tuk6Fod-K6t-LEHGJtLtE&amp;dib_tag=se&amp;keywords=Web%E3%82%A2%E3%83%97%E3%83%AA+%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3&amp;qid=1718235109&amp;sprefix=web%E3%82%A2%E3%83%97%E3%83%AA+%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%2Caps%2C186&amp;sr=8-1&amp;linkCode=ll1&amp;tag=kekenta03amaz-22&amp;linkId=dc5df2a77d4a028f4519e6b2a07ffb84&amp;language=ja_JP&amp;ref_=as_li_ss_tl"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNNDQgMkgzMGMtMS4xIDAtMiAuOS0yIDJzLjkgMiAyIDJoOS4yTDI0IDIxLjJjLS44LjgtLjggMiAwIDIuOHMyIC44IDIuOCAwTDQyIDguOFYxOGMwIDEuMS45IDIgMiAyczItLjkgMi0yVjRjMC0xLjEtLjktMi0yLTJ6Ij48L3BhdGg+PHBhdGggZD0iTTQxIDI3Yy0xLjEgMC0yIC45LTIgMnYxMGMwIDEuMS0uOSAyLTIgMkg5Yy0xLjEgMC0yLS45LTItMlYxMWMwLTEuMS45LTIgMi0yaDEwYzEuMSAwIDItLjkgMi0ycy0uOS0yLTItMkg5Yy0zLjMgMC02IDIuNy02IDZ2MjhjMCAzLjMgMi43IDYgNiA2aDI4YzMuMyAwIDYtMi43IDYtNlYyOWMwLTEuMS0uOS0yLTItMnoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsExternalLink" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span>体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 脆弱性が生まれる原理と対策の実践</a><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMTEuNyAxLjQgNi44IDVjLS41LjQtLjggMS0uOCAxLjZ2MjguN2MwIC44LjUgMS41IDEuMiAxLjhsMjQgMTAuM2MxLjMuNiAyLjgtLjQgMi44LTEuOFYxOWMwLS44LS41LTEuNS0xLjItMS44TDEwLjIgNy41bDIuOS0yLjJjLjktLjYgMi0uOCAzLS40bDIwLjYgOC44Yy43LjMgMS4yIDEgMS4yIDEuOFY0Mi45YzAgLjkgMSAxLjMgMS43LjhsMS43LTEuNWMuNC0uNC43LS45LjctMS41VjEzYzAtLjgtLjUtMS41LTEuMi0xLjhMMTYuNy44Yy0xLjctLjctMy42LS41LTUgLjZ6Ij48L3BhdGg+PC9zdmc+)" data-icon="LsBook" data-id="47" aria-hidden="true" class="swl-inline-icon"> </span><br>徳丸 浩／著　SBクリエイティブ／出版│<a href="https://www.amazon.co.jp/%E4%BD%93%E7%B3%BB%E7%9A%84%E3%81%AB%E5%AD%A6%E3%81%B6-%E5%AE%89%E5%85%A8%E3%81%AAWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-%E7%AC%AC2%E7%89%88-%E8%84%86%E5%BC%B1%E6%80%A7%E3%81%8C%E7%94%9F%E3%81%BE%E3%82%8C%E3%82%8B%E5%8E%9F%E7%90%86%E3%81%A8%E5%AF%BE%E7%AD%96%E3%81%AE%E5%AE%9F%E8%B7%B5-%E5%BE%B3%E4%B8%B8/dp/4797393165?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&amp;crid=1FQAOXKEGI9HT&amp;dib=eyJ2IjoiMSJ9.ksxMxdA4KTXnYLFgVxMFis4f3XHMUvarmNijcsU4Nmvl3Tud_nU0g7agEl3ercb-Os7uj_I-9w5xejzyw_JwMcs7FC4uVP9jc3sHC7c9ZuDT_gwuJFliueZNV3zuXq4731v-JAlEh4pR64KI-_puhFly0i_zkfDlsH2xTLQWoeNNIM9FkS584d43eeD8-mNtPjbtKK1lmvjecUb-VALfXImg-mACYpqlPWhTawzlYmnCmT85BL5k4gVzrtlErnyRPeFE4qCXwaN884rSGk9l6PGCfVcIoDQOg1lp8Ia-RWA.i4wIGc7KFczkxeNgrmVo03tuk6Fod-K6t-LEHGJtLtE&amp;dib_tag=se&amp;keywords=Web%E3%82%A2%E3%83%97%E3%83%AA+%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3&amp;qid=1718235109&amp;sprefix=web%E3%82%A2%E3%83%97%E3%83%AA+%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%2Caps%2C186&amp;sr=8-1&amp;linkCode=ll1&amp;tag=kekenta03amaz-22&amp;linkId=dc5df2a77d4a028f4519e6b2a07ffb84&amp;language=ja_JP&amp;ref_=as_li_ss_tl">Amazon</a></p>



<p>それでも本当に対策ができているのか不安なので、色々なネット記事も参考にしながら開発をしています。</p>



<p>セキュリティ攻撃は残念なことに日々新しい手法が誕生していっている分野なので、開発する側もしっかりと学習を継続することが大切です。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>それでは本記事は以上とさせていただきます。<br>最後までお読みいただきありがとうございました！</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>

<div id="rinkerid3653" class="yyi-rinker-contents  yyi-rinker-postid-3653 yyi-rinker-img-m yyi-rinker-catid-5 yyi-rinker-catid-72 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://hb.afl.rakuten.co.jp/hgc/g00q072g.bdzz22a5.g00q072g.bdzz326e/Rinker_i_20240325050010?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fbook%2F16371381%2F&#038;m=http%3A%2F%2Fm.rakuten.co.jp%2Fbook%2Fi%2F20055321%2F&#038;rafcid=wsc_i_is_1047822029026699702" rel="nofollow" class="yyi-rinker-tracking"  data-click-tracking="rakuten_img 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]" data-vars-click-id="rakuten_img 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]"><img decoding="async" src="https://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/4688/9784297114688.jpg?_ex=128x128"  width="128" height="128" class="yyi-rinker-main-img" style="border: none;"></a>					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://hb.afl.rakuten.co.jp/hgc/g00q072g.bdzz22a5.g00q072g.bdzz326e/Rinker_t_20240325050010?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fbook%2F16371381%2F&#038;m=http%3A%2F%2Fm.rakuten.co.jp%2Fbook%2Fi%2F20055321%2F&#038;rafcid=wsc_i_is_1047822029026699702" rel="nofollow" class="yyi-rinker-tracking" data-click-tracking="rakuten_title 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]" data-vars-amp-click-id="rakuten_title 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]" >PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]</a>							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							<span title="" class="price">¥3,938</span>
															<span class="price_at">(2026/04/18 18:42:17時点&nbsp;楽天市場調べ-</span><span title="このサイトで掲載されている情報は当サイトの作成者により運営されています。価格、販売可能情報は、変更される場合があります。購入時に楽天市場店舗（www.rakuten.co.jp）に表示されている価格がその商品の販売に適用されます。">詳細)</span>
																	</div>
						</div>
						<ul class="yyi-rinker-links">
																	<li class="amazonkindlelink">
						<a href="https://www.amazon.co.jp/PHP%E6%9C%AC%E6%A0%BC%E5%85%A5%E9%96%80%EF%BC%BB%E4%B8%8A%EF%BC%BD-%EF%BD%9E%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%A8%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E3%81%AE%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E9%80%A3%E6%90%BA%E3%81%BE%E3%81%A7-%E5%A4%A7%E5%AE%B6-%E6%AD%A3%E7%99%BB-ebook/dp/B08DXRK18C?_encoding=UTF8&amp;dib_tag=se&amp;dib=eyJ2IjoiMSJ9.74YDItYNn-AHro6XQ1cSslRSHUvp_S8S4MVJtvnW_XswliMGieYQktGbaTJY9E-Qpy3y3roMKB8M-zKI3K7otpqjDxkuoq7ncq-6mLf3BEkcNW05BAHDZZ17WZueAniDY7peSrmp4Ji0L0BkXOaJIBbpqa628I6bjQBED1FQ9V7BJqUJVUUxz6ns2GIHnoSItDTgCRaIpNi9fMcBrt3jqZr1qNJxCmBn8-xPR9N3usFpENEEChvMwvGdHoHu1hjsq6g9GvJDwPPBTwhQvDgXG2KZQ5CBlEx_wQjQy06hFcw.xxCKw6aGhA397JIEATXvL3RNC7D4_k4avRIYczzkjHw&amp;qid=1723712413&amp;sr=8-6&amp;linkCode=ll1&amp;tag=kekenta03am0b-22&amp;linkId=8de435cc399443bbfb43b9e7b8e0c9f1&amp;language=ja_JP&amp;ref_=as_li_ss_tl" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon_kindle 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]"  data-vars-amp-click-id="amazon_kindle 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]">Kindle</a>					</li>
								                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/PHP%E6%9C%AC%E6%A0%BC%E5%85%A5%E9%96%80-%E4%B8%8A-%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%A8%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E3%81%AE%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E9%80%A3%E6%90%BA%E3%81%BE%E3%81%A7-%E5%A4%A7%E5%AE%B6-%E6%AD%A3%E7%99%BB/dp/4297114682?dib=eyJ2IjoiMSJ9.74YDItYNn-AHro6XQ1cSslRSHUvp_S8S4MVJtvnW_XswliMGieYQktGbaTJY9E-Qpy3y3roMKB8M-zKI3K7otpqjDxkuoq7ncq-6mLf3BEkcNW05BAHDZZ17WZueAniDY7peSrmp4Ji0L0BkXOaJIBbpqa628I6bjQBED1FQ9V7BJqUJVUUxz6ns2GIHnoSItDTgCRaIpNi9fMcBrt3jqZr1qNJxCmBn8-xPR9N3usFpENEEChvMwvGdHoHu1hjsq6g9GvJDwPPBTwhQvDgXG2KZQ5CBlEx_wQjQy06hFcw.xxCKw6aGhA397JIEATXvL3RNC7D4_k4avRIYczzkjHw&amp;dib_tag=se&amp;keywords=PHP%E6%9C%AC%E6%A0%BC%E5%85%A5%E9%96%80&amp;qid=1723712413&amp;sr=8-6&amp;linkCode=ll1&amp;tag=kekenta03am0b-22&amp;linkId=16a4b7edeeedcc86aef9f0b8c45cc669&amp;language=ja_JP&amp;ref_=as_li_ss_tl" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]"  data-vars-amp-click-id="amazon 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://hb.afl.rakuten.co.jp/hgc/g00q072g.bdzz22a5.g00q072g.bdzz326e/Rinker_t_20240325050010?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fbook%2F16371381%2F&amp;m=http%3A%2F%2Fm.rakuten.co.jp%2Fbook%2Fi%2F20055321%2F&amp;rafcid=wsc_i_is_1047822029026699702" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="rakuten 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]"  data-vars-amp-click-id="rakuten 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]">楽天市場</a>					</li>
								                											</ul>
					</div>
	</div>
</div>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>SQLの書き方｜PHPでアプリ開発するなら必須のCRUDとは？</title>
		<link>https://kekenta-it-blog.com/php-sql-basic/</link>
		
		<dc:creator><![CDATA[ケケンタ]]></dc:creator>
		<pubDate>Mon, 04 Mar 2024 23:20:07 +0000</pubDate>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[Webアプリ]]></category>
		<category><![CDATA[PHP]]></category>
		<guid isPermaLink="false">https://kekenta-it-blog.com/?p=3232</guid>

					<description><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/eye-catch__php-sql-basic__3232-1024x576.jpg" class="webfeedsFeaturedVisual" /></p>今回はPHPのWebアプリ開発をするなら必須のSQLの書き方について解説をしていきます。 SQLはデータベースを操作するための言語です。 しかし、いま現在PHPを学ばれていて、これからWebアプリ開発をしたいと考えている [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/eye-catch__php-sql-basic__3232-1024x576.jpg" class="webfeedsFeaturedVisual" /></p><div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>こんにちは！　ケケンタです。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>今回はPHPのWebアプリ開発をするなら必須の<strong>SQL</strong>の書き方について解説をしていきます。</p>



<div class="swell-block-capbox cap_box is-style-shadow"><div class="cap_box_ttl"><span><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsLightbulb" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span><strong>この記事で分かること</strong></span></div><div class="cap_box_content">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>PHPのWebアプリ開発で必要なSQLの知識</li>



<li>CRUDとは何か？</li>



<li>SQLの基本構文</li>
</ul>
</div></div>



<p>SQLは<strong>データベースを操作するための言語</strong>です。</p>



<p>しかし、いま現在PHPを学ばれていて、これからWebアプリ開発をしたいと考えている方は、SQLの中でも基本となる<strong>CRUD（クラッド）</strong>の書き方を理解する必要があります。</p>



<p>この記事をご覧いただくことで、<strong><span class="swl-marker mark_yellow">PHPでのWebアプリ開発において不可欠なSQLを理解することができます。</span></strong></p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>SQLの基本構文を習得することでTODOアプリや掲示板アプリを開発できるレベルに１つ近づくことができます。<br><br>PHPの勉強はとても大変で、その上「SQLもやるのか……」と思われる方もいらっしゃるかと思いますが、PHPに比べれば<strong>覚えるべきことは非常に少なく、また簡単</strong>です。<br><br>この記事を通して、ぜひSQLの基本構文を理解していってください。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>

<div class="swell-block-postLink">			<a href="https://kekenta-it-blog.com/php-rakuten-api/" class="c-blogLink -internal" data-style="text">
				<!-- <i class="c-blogLink__icon icon-link" role="presentation"></i> -->
				<span class="c-blogLink__icon">
					<svg xmlns="http://www.w3.org/2000/svg" class="swl-svg-link __svg" width="1em" height="1em" viewBox="0 0 48 48" role="img" aria-hidden="true" focusable="false"><path d="M21.2 30.2c-.5 0-1-.2-1.4-.6l-.7-.7c-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l7.1-7.1c2.3-2.3 5.3-3.5 8.5-3.5s6.2 1.2 8.5 3.5c4.7 4.7 4.7 12.3 0 17l-3.5 3.5c-.8.8-2 .8-2.8 0-.8-.8-.8-2 0-2.8l3.5-3.5c3.1-3.1 3.1-8.2 0-11.3-1.5-1.5-3.5-2.3-5.7-2.3-2.1 0-4.2.8-5.7 2.3l-7.1 7.1c-1.5 1.5-2.3 3.5-2.3 5.7s.8 4.2 2.3 5.7l.7.7c.8.8.8 2 0 2.8-.4.3-.9.5-1.4.5z" /><path d="M13.4 46.6c-3.1 0-6.1-1.2-8.5-3.5-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l3.5-3.5c.8-.8 2-.8 2.8 0 .8.8.8 2 0 2.8l-3.5 3.5c-1.5 1.5-2.3 3.5-2.3 5.7 0 2.1.8 4.2 2.3 5.7 3.1 3.1 8.2 3.1 11.3 0l7.1-7.1c1.5-1.5 2.3-3.5 2.3-5.7 0-2.1-.8-4.2-2.3-5.7l-.7-.7c-.8-.8-.8-2 0-2.8.8-.8 2-.8 2.8 0l.7.7c2.3 2.3 3.5 5.3 3.5 8.5s-1.2 6.2-3.5 8.5l-7.1 7.1c-2.3 2.3-5.3 3.5-8.4 3.5z" /></svg>				</span>
				<span class="c-blogLink__text">【PHP】APIとは？楽天APIで商品検索機能を作成する方法</span>
			</a>
		</div>

<div class="swell-block-postLink">			<a href="https://kekenta-it-blog.com/alone-php-study/" class="c-blogLink -internal" data-style="text">
				<!-- <i class="c-blogLink__icon icon-link" role="presentation"></i> -->
				<span class="c-blogLink__icon">
					<svg xmlns="http://www.w3.org/2000/svg" class="swl-svg-link __svg" width="1em" height="1em" viewBox="0 0 48 48" role="img" aria-hidden="true" focusable="false"><path d="M21.2 30.2c-.5 0-1-.2-1.4-.6l-.7-.7c-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l7.1-7.1c2.3-2.3 5.3-3.5 8.5-3.5s6.2 1.2 8.5 3.5c4.7 4.7 4.7 12.3 0 17l-3.5 3.5c-.8.8-2 .8-2.8 0-.8-.8-.8-2 0-2.8l3.5-3.5c3.1-3.1 3.1-8.2 0-11.3-1.5-1.5-3.5-2.3-5.7-2.3-2.1 0-4.2.8-5.7 2.3l-7.1 7.1c-1.5 1.5-2.3 3.5-2.3 5.7s.8 4.2 2.3 5.7l.7.7c.8.8.8 2 0 2.8-.4.3-.9.5-1.4.5z" /><path d="M13.4 46.6c-3.1 0-6.1-1.2-8.5-3.5-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l3.5-3.5c.8-.8 2-.8 2.8 0 .8.8.8 2 0 2.8l-3.5 3.5c-1.5 1.5-2.3 3.5-2.3 5.7 0 2.1.8 4.2 2.3 5.7 3.1 3.1 8.2 3.1 11.3 0l7.1-7.1c1.5-1.5 2.3-3.5 2.3-5.7 0-2.1-.8-4.2-2.3-5.7l-.7-.7c-.8-.8-.8-2 0-2.8.8-.8 2-.8 2.8 0l.7.7c2.3 2.3 3.5 5.3 3.5 8.5s-1.2 6.2-3.5 8.5l-7.1 7.1c-2.3 2.3-5.3 3.5-8.4 3.5z" /></svg>				</span>
				<span class="c-blogLink__text">PHPはこうして習得した！約１年間の勉強内容【プログラミング独学】</span>
			</a>
		</div>

<div class="swell-block-postLink">			<a href="https://kekenta-it-blog.com/php-deploy-xserver-for-zip/" class="c-blogLink -internal" data-style="text">
				<!-- <i class="c-blogLink__icon icon-link" role="presentation"></i> -->
				<span class="c-blogLink__icon">
					<svg xmlns="http://www.w3.org/2000/svg" class="swl-svg-link __svg" width="1em" height="1em" viewBox="0 0 48 48" role="img" aria-hidden="true" focusable="false"><path d="M21.2 30.2c-.5 0-1-.2-1.4-.6l-.7-.7c-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l7.1-7.1c2.3-2.3 5.3-3.5 8.5-3.5s6.2 1.2 8.5 3.5c4.7 4.7 4.7 12.3 0 17l-3.5 3.5c-.8.8-2 .8-2.8 0-.8-.8-.8-2 0-2.8l3.5-3.5c3.1-3.1 3.1-8.2 0-11.3-1.5-1.5-3.5-2.3-5.7-2.3-2.1 0-4.2.8-5.7 2.3l-7.1 7.1c-1.5 1.5-2.3 3.5-2.3 5.7s.8 4.2 2.3 5.7l.7.7c.8.8.8 2 0 2.8-.4.3-.9.5-1.4.5z" /><path d="M13.4 46.6c-3.1 0-6.1-1.2-8.5-3.5-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l3.5-3.5c.8-.8 2-.8 2.8 0 .8.8.8 2 0 2.8l-3.5 3.5c-1.5 1.5-2.3 3.5-2.3 5.7 0 2.1.8 4.2 2.3 5.7 3.1 3.1 8.2 3.1 11.3 0l7.1-7.1c1.5-1.5 2.3-3.5 2.3-5.7 0-2.1-.8-4.2-2.3-5.7l-.7-.7c-.8-.8-.8-2 0-2.8.8-.8 2-.8 2.8 0l.7.7c2.3 2.3 3.5 5.3 3.5 8.5s-1.2 6.2-3.5 8.5l-7.1 7.1c-2.3 2.3-5.3 3.5-8.4 3.5z" /></svg>				</span>
				<span class="c-blogLink__text">【PHP】エックスサーバーへデプロイする方法【初心者でも簡単！】</span>
			</a>
		</div>

<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">あわせて読みたい</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/03/eye-catch__school-php-and-wp__14099-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/school-php-and-wp/">PHPやWordPressを学ぶのにおすすめのプログラミングスクール【７選】</a>
						<span class="p-blogCard__excerpt">僕はこれまで独学でPHPを学習してきました。結論から言えば、それでもPHPを習得することはできました。 しかし、それに費やした累計学習期間は1年ほど。モチベーション&#8230;</span>					</div>
				</div>
			</div>
		</div>


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



<p>大前提として、<strong>SQLとは何か？</strong>についてお話をします。</p>



<p class="is-style-border-left-box has-box-style"><strong>SQL</strong>とは</p>



<p class="is-style-border-left-box has-box-style has-border -border03"><strong><span class="marker-under">データベースを操作するために使用するデータベース言語</span></strong></p>



<p class="is-style-border-left-box has-box-style">です。</p>



<p>データベースにはWebアプリで必要となるユーザー情報やコンテンツ情報などをデータとして保存しておきます。</p>



<p>そのデータ量は実際に運営されているWebアプリの場合、非常に膨大なものとなります。</p>



<p><strong><span class="marker-under">その膨大なデータを操作するために使用される言語</span></strong>が<strong>SQL</strong>です。</p>



<h2 class="wp-block-heading">SQLの基本であるCRUD（クラッド）とは？</h2>



<p>SQLの説明の最後に「操作するために使用される言語」とお伝えしました。</p>



<p>ここで言っている<strong>操作</strong>というのが、いわゆる<strong>CRUD</strong>と呼ばれるものになります。</p>



<div class="swell-block-capbox cap_box is-style-onborder_ttl2"><div class="cap_box_ttl"><span><strong>CRUDとは？</strong></span></div><div class="cap_box_content">
<p>CRUDとは、Webアプリケーションにおいて欠かせない以下<strong>４つのデータベース操作の基本機能</strong>を言い表したものです。</p>



<p><strong>C</strong>reate（作成）<br><strong>R</strong>ead（読み取り）<br><strong>U</strong>pdate（更新）<br><strong>D</strong>elete（削除）</p>



<p>これらの頭文字を取ったのが<strong>CRUD</strong>（クラッド）です。</p>
</div></div>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">CRUD（クラッド）の４大要素</h2>



<p>繰り返しになりますが、<strong>CRUD</strong>はWebアプリケーションにおいて不可欠なデータベース操作の４つの頭文字を組み合わせたものです。</p>



<p>これらをSQLの基本構文と対応させると以下のようになります。</p>



<p class="is-style-balloon_box2"><strong>CRUD（クラッド）</strong></p>



<ul class="wp-block-list is-style-check_list">
<li><strong>C</strong>reate（作成） …… <strong>INSERT文</strong></li>



<li><strong>R</strong>ead（読み取り）…… <strong>SELECT文</strong></li>



<li><strong>U</strong>pdate（更新） …… <strong>UPDATE文</strong></li>



<li><strong>D</strong>elete（削除） …… <strong>DELETE文</strong></li>
</ul>



<p>PHPに限らず、Webアプリケーションを開発する際には、上記４種類のSQL文の使用が欠かせません。</p>



<p>言い換えれば、これらをしっかり理解できれば<strong><span class="marker-under">Webアプリケーションを開発するために最低限必要なSQLは習得した</span></strong>と言えるということです。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>それでは以下より各SQL文の概要と構文を解説していきます。<br>なお、CRUDでは先頭がINSERT文になっていますが、当記事ではSQLにおいて最も基本である<strong>SELECT文の書き方</strong>からご説明させていただきます。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<h2 class="wp-block-heading">SELECT</h2>



<p class="is-style-border-left-box has-box-style"><strong>SELECT文</strong>は</p>



<p class="is-style-border-left-box has-box-style has-border -border03">データベースから特定のデータを取得したい際に使用するSQL文</p>



<p class="is-style-border-left-box has-box-style">です。</p>



<p>使用例としては、掲示板アプリで投稿情報を表示したいとき、<strong>投稿情報をデータベースから取得する</strong>ときなどが挙げられます。</p>


<div class="wp-block-image">
<figure data-wp-context="{&quot;imageId&quot;:&quot;69e3e8ace31c1&quot;}" data-wp-interactive="core/image" data-wp-key="69e3e8ace31c1" class="aligncenter size-large is-resized has-custom-border wp-lightbox-container"><img decoding="async" width="1024" height="491" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://kekenta-it-blog.com/wp-content/uploads/2024/03/9e3cb31030868cbdd8936df71b916ddf-1024x491.jpg" alt="SELECT文用例⓵" class="wp-image-3245" style="border-width:1px;width:530px" srcset="https://kekenta-it-blog.com/wp-content/uploads/2024/03/9e3cb31030868cbdd8936df71b916ddf-1024x491.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/9e3cb31030868cbdd8936df71b916ddf-300x144.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/9e3cb31030868cbdd8936df71b916ddf-768x368.jpg 768w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/9e3cb31030868cbdd8936df71b916ddf-1536x737.jpg 1536w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/9e3cb31030868cbdd8936df71b916ddf.jpg 1551w" sizes="(max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="拡大する"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>
</div>


<p>上図ではIDが２のデータを選択する様子を示していますが、実際には例えば名前や色に対して条件を指定する形でデータを取得することが可能です。</p>



<p>本章ではパターンとして以下<strong>３つ</strong>について解説します。</p>



<div class="wp-block-group is-style-big_icon_good"><div class="wp-block-group__inner-container">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li><strong>すべてのデータを取得する場合</strong></li>



<li><strong>列を指定しつつ、すべてのデータを取得する場合</strong></li>



<li><strong>条件に一致するすべてのデータを取得する場合</strong></li>
</ul>
</div></div>



<h3 class="wp-block-heading">すべてのデータを取得する場合</h3>



<p><strong>すべてのデータを取得する</strong>場合、SQLは以下のようになります。</p>



<p class="is-style-balloon_box2">すべてのデータを取得するSQL文</p>



<p class="is-style-light-background-box has-box-style has-border -border03"><strong>SELECT * FROM テーブル名;</strong></p>


<div class="wp-block-image">
<figure data-wp-context="{&quot;imageId&quot;:&quot;69e3e8ace3e39&quot;}" data-wp-interactive="core/image" data-wp-key="69e3e8ace3e39" class="aligncenter size-large is-resized has-custom-border wp-lightbox-container"><img decoding="async" width="1024" height="675" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://kekenta-it-blog.com/wp-content/uploads/2024/03/82c49525781257b73820bd49fee352ed-1024x675.jpg" alt="" class="wp-image-3250" style="border-width:1px;width:530px" srcset="https://kekenta-it-blog.com/wp-content/uploads/2024/03/82c49525781257b73820bd49fee352ed-1024x675.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/82c49525781257b73820bd49fee352ed-300x198.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/82c49525781257b73820bd49fee352ed-768x506.jpg 768w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/82c49525781257b73820bd49fee352ed-1536x1012.jpg 1536w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/82c49525781257b73820bd49fee352ed.jpg 1551w" sizes="(max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="拡大する"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>
</div>


<p class="is-style-big_icon_point">SQLでは基本的に<strong>メインとなる命令（SELECT）</strong>を先頭に書きます。<br>その後ろに続く<strong>*（アスタリスク）</strong>と<strong>FROM テーブル名</strong>はそれぞれ以下のような意味を持ちます。<br><br><strong>・*（アスタリスク）</strong>……<strong>すべての列（カラム）</strong><br>・<strong>FROM テーブル名</strong>……<strong>『テーブル名』から取得する</strong><br><br>また、このSQL文では、条件の指定を行っていません。<br>したがって、上記の１文により、「『テーブル名』からすべてのデータを取得する」という意味になります。</p>



<h3 class="wp-block-heading"><strong>列を指定しつつ、すべてのデータを取得する場合</strong></h3>



<p>データを取得する際、<strong>特定の列情報</strong>があれば十分な場合があります。</p>



<p>そんなときは以下のように記述をします。</p>



<p class="is-style-balloon_box2">特定の列からのみデータを取得する</p>



<p class="is-style-light-background-box has-box-style has-border -border03"><strong>SELECT <span class="swl-inline-color has-swl-deep-02-color">名前, 数量</span> FROM テーブル名;</strong></p>


<div class="wp-block-image">
<figure data-wp-context="{&quot;imageId&quot;:&quot;69e3e8ace46d0&quot;}" data-wp-interactive="core/image" data-wp-key="69e3e8ace46d0" class="aligncenter size-large is-resized has-custom-border wp-lightbox-container"><img decoding="async" width="886" height="1024" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://kekenta-it-blog.com/wp-content/uploads/2024/03/63830cb63f97e099b45ddff984e5f484-886x1024.jpg" alt="" class="wp-image-3261" style="border-width:1px;width:530px" srcset="https://kekenta-it-blog.com/wp-content/uploads/2024/03/63830cb63f97e099b45ddff984e5f484-886x1024.jpg 886w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/63830cb63f97e099b45ddff984e5f484-260x300.jpg 260w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/63830cb63f97e099b45ddff984e5f484-768x888.jpg 768w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/63830cb63f97e099b45ddff984e5f484-1329x1536.jpg 1329w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/63830cb63f97e099b45ddff984e5f484.jpg 1551w" sizes="(max-width: 886px) 100vw, 886px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="拡大する"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>
</div>


<p class="is-style-big_icon_point">SELECTの後ろに<strong>カラム名（列名）をカンマ区切りで記述</strong>しています。<br>こうすることで、特定のカラムだけを取得することが可能です。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>もちろん、<strong>１列だけ選択するという記述の仕方も可能</strong>です。<br><br>また補足として、以下の<strong>①、②</strong>のSQL文は同じ取得結果になります。<br>①<strong>SELECT * テーブル名;</strong><br>②<strong>SELECT ID, 名前, 色 ,数量 FROM テーブル名;</strong></p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<h3 class="wp-block-heading"><strong>条件に一致するすべてのデータを取得する場合</strong></h3>



<p><strong>条件を指定してデータを取得する</strong>場合は、これまでの構文に加えて<strong>WHERE文</strong>を使用します。</p>



<p>書き方は以下の通りです。</p>



<p class="is-style-balloon_box2">条件を指定してデータを取得するSQL文</p>



<p class="is-style-light-background-box has-box-style has-border -border03"><strong>SELECT * FROM テーブル名 <span class="swl-inline-color has-swl-deep-02-color">WHERE 条件</span>;</strong></p>



<p>また、<strong><span class="marker-under">複数の条件を指定</span></strong>することも可能で、その場合は<strong><span class="bold-blue">AND</span></strong>や<strong><span class="bold-blue">OR</span></strong>を使用します。</p>



<p class="is-style-balloon_box2"><span class="marker-under">複数の条件を</span>指定するSQL文</p>



<p class="is-style-light-background-box has-box-style has-border -border03"><strong>SELECT * FROM テーブル名 <span class="swl-inline-color has-swl-deep-02-color">WHERE 条件⓵ <span class="bold-blue">OR</span> 条件⓶</span>;</strong></p>



<p>以下の例では、「<strong>IDが２または数量が20のデータ</strong>」を取得します。</p>


<div class="wp-block-image">
<figure data-wp-context="{&quot;imageId&quot;:&quot;69e3e8ace5395&quot;}" data-wp-interactive="core/image" data-wp-key="69e3e8ace5395" class="aligncenter size-large is-resized has-custom-border wp-lightbox-container"><img decoding="async" width="1024" height="828" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://kekenta-it-blog.com/wp-content/uploads/2024/03/64fa391fd6ed79af24669718d285de22-1024x828.jpg" alt="" class="wp-image-3267" style="border-width:1px;width:630px" srcset="https://kekenta-it-blog.com/wp-content/uploads/2024/03/64fa391fd6ed79af24669718d285de22-1024x828.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/64fa391fd6ed79af24669718d285de22-300x242.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/64fa391fd6ed79af24669718d285de22-768x621.jpg 768w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/64fa391fd6ed79af24669718d285de22-1536x1242.jpg 1536w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/64fa391fd6ed79af24669718d285de22-2048x1655.jpg 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="拡大する"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>
</div>

<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>このようにSQLでは<strong><span class="swl-marker mark_yellow">基本的な構文を組み合わせることで様々なデータを取得する</span></strong>ことが可能です。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>

<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">INSERT</h2>



<p class="is-style-border-left-box has-box-style"><strong>INSERT文</strong>は、<strong>既存のテーブルに新しいデータを追加する際に使用</strong>します。</p>



<p>Webアプリケーションでは、例えば掲示板アプリに投稿があった際、<strong>投稿データをテーブルにINSERTする</strong>といったシチュエーションが挙げられます。</p>



<p>基本的な書き方は以下の通りです。</p>



<p class="is-style-balloon_box2">INSERT文の基本的な書き方</p>



<p class="is-style-light-background-box has-box-style has-border -border03"><strong>INSERT INTO テーブル名&nbsp;(列名1, 列名2,&#8230;) VALUES (値1, 値2,&#8230;);</strong></p>



<p><span class="swl-marker mark_blue"><strong>以下の例</strong></span>では、<strong>既存テーブルに「いちご」の情報を新規追加</strong>します。</p>



<p class="is-style-light-background-box has-box-style has-border -border03"><strong>INSERT INTO テーブル名&nbsp;(ID, 名前, 色, 数量) VALUES (5, &#8216;いちご&#8217;, &#8216;レッド&#8217;, 13);</strong></p>


<div class="wp-block-image">
<figure data-wp-context="{&quot;imageId&quot;:&quot;69e3e8ace5e68&quot;}" data-wp-interactive="core/image" data-wp-key="69e3e8ace5e68" class="aligncenter size-large is-resized has-custom-border wp-lightbox-container"><img decoding="async" width="1024" height="635" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://kekenta-it-blog.com/wp-content/uploads/2024/03/3b3f1d182b940772dafa92429dbf0ffe-1-1024x635.jpg" alt="" class="wp-image-3299" style="border-width:1px;width:600px;height:auto" srcset="https://kekenta-it-blog.com/wp-content/uploads/2024/03/3b3f1d182b940772dafa92429dbf0ffe-1-1024x635.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/3b3f1d182b940772dafa92429dbf0ffe-1-300x186.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/3b3f1d182b940772dafa92429dbf0ffe-1-768x476.jpg 768w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/3b3f1d182b940772dafa92429dbf0ffe-1-1536x952.jpg 1536w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/3b3f1d182b940772dafa92429dbf0ffe-1.jpg 2003w" sizes="(max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="拡大する"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>
</div>


<p class="is-style-alert-box has-box-style">この例では説明のためにIDの情報も記述していますが、基本的にデータを一意に識別するための連番は<strong>データベース側の設定で自動的に入力</strong>されるようにします。</p>



<p class="is-style-alert-box has-box-style">したがって、実際の開発の際にはIDの部分は省略してしまって大丈夫なケースがほとんどです。</p>



<h2 class="wp-block-heading">UPDATE</h2>



<p class="is-style-border-left-box has-box-style"><strong>UPDATE文</strong>は、<strong>既存データを更新したいときに使用</strong>します。</p>



<p>例えば掲示板アプリでは、<strong>過去に投稿した投稿内容を修正する機能</strong>で使用します。</p>



<p>基本的な書き方はこちらです。</p>



<p class="is-style-balloon_box2">UPDATE文の基本的な書き方</p>



<p class="is-style-light-background-box has-box-style has-border -border03"><strong>UPDATE (テーブル名) SET (カラム名1) = (値１) WHERE (条件);</strong></p>



<p>少々見づらいかもしれませんが、<strong>日本語で簡単に見ると</strong></p>



<p class="is-style-bg_stripe">指定したテーブル内の条件に当てはまるデータの内、指定したカラムの情報を（値１）に置き換える</p>



<p>という意味です。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>イメージが湧きづらい方は、まず<strong>UPDATE～（値１）</strong>までを１つのまとまりとして捉えてみて下さい。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>例えば、<strong>IDが１のデータの数量を15に更新する</strong>というSQL文は以下のようになります。</p>



<p class="is-style-light-background-box has-box-style has-border -border03"><strong>UPDATE テーブル名 SET 数量 = 値１ WHERE ID = 1;</strong></p>


<div class="wp-block-image">
<figure data-wp-context="{&quot;imageId&quot;:&quot;69e3e8ace705f&quot;}" data-wp-interactive="core/image" data-wp-key="69e3e8ace705f" class="aligncenter size-large is-resized has-custom-border wp-lightbox-container"><img decoding="async" width="926" height="1024" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://kekenta-it-blog.com/wp-content/uploads/2024/03/b83113e7dd27c30dcc38db78e3e30063-1-926x1024.jpg" alt="UPDATE文用例" class="wp-image-3305" style="border-width:1px;width:530px;height:auto" srcset="https://kekenta-it-blog.com/wp-content/uploads/2024/03/b83113e7dd27c30dcc38db78e3e30063-1-926x1024.jpg 926w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/b83113e7dd27c30dcc38db78e3e30063-1-271x300.jpg 271w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/b83113e7dd27c30dcc38db78e3e30063-1-768x850.jpg 768w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/b83113e7dd27c30dcc38db78e3e30063-1-1389x1536.jpg 1389w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/b83113e7dd27c30dcc38db78e3e30063-1-1851x2048.jpg 1851w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/b83113e7dd27c30dcc38db78e3e30063-1.jpg 2025w" sizes="(max-width: 926px) 100vw, 926px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="拡大する"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>
</div>


<h2 class="wp-block-heading">DELETE</h2>



<p>最後は<strong>DELETE文</strong>です。</p>



<p class="is-style-border-left-box has-box-style"><strong>DELETE文</strong>は、<strong>条件に一致する既存データを削除したいときに使用</strong>します。</p>



<p>例えば掲示板アプリでは、<strong>過去の投稿内容を削除する機能</strong>で使用します。</p>



<p>基本的な書き方は以下の通りです。</p>



<p class="is-style-balloon_box2">DELETE文の基本的な書き方</p>



<p class="is-style-light-background-box has-box-style has-border -border03"><strong>DELETE FROM テーブル名 WHERE 条件</strong>;</p>



<p><strong><span class="swl-marker mark_blue">以下の例</span></strong>では、<strong>IDが３のデータを削除</strong>しています。</p>



<p class="is-style-light-background-box has-box-style has-border -border03"><strong>DELETE FROM テーブル名 WHERE ID</strong> <strong>= 3</strong>;</p>


<div class="wp-block-image">
<figure data-wp-context="{&quot;imageId&quot;:&quot;69e3e8ace7ac2&quot;}" data-wp-interactive="core/image" data-wp-key="69e3e8ace7ac2" class="aligncenter size-large is-resized has-custom-border wp-lightbox-container"><img decoding="async" width="926" height="1024" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://kekenta-it-blog.com/wp-content/uploads/2024/03/f4b6b3528c21afadf5940628238b2204-926x1024.jpg" alt="DELETE文用例" class="wp-image-3309" style="border-width:1px;width:550px;height:auto" srcset="https://kekenta-it-blog.com/wp-content/uploads/2024/03/f4b6b3528c21afadf5940628238b2204-926x1024.jpg 926w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/f4b6b3528c21afadf5940628238b2204-271x300.jpg 271w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/f4b6b3528c21afadf5940628238b2204-768x850.jpg 768w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/f4b6b3528c21afadf5940628238b2204-1389x1536.jpg 1389w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/f4b6b3528c21afadf5940628238b2204-1851x2048.jpg 1851w, https://kekenta-it-blog.com/wp-content/uploads/2024/03/f4b6b3528c21afadf5940628238b2204.jpg 2025w" sizes="(max-width: 926px) 100vw, 926px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="拡大する"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>
</div>


<p class="is-style-alert-box has-box-style is-style-icon_info">注意点として、仮に以下のように<strong><span class="swl-marker mark_orange">条件を省いてDELETE文を実行した場合、テーブル内のデータがすべて削除されてしまいます。</span></strong><br><br>そのため、DELETE文を使用する際は、必ずWHEREで条件を指定するようにしましょう。</p>



<p class="is-style-alert-box has-box-style has-border -border03"><strong>DELETE FROM テーブル名</strong>;</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>以上が<strong>CRUD</strong>の解説でした。<br><br>余談ですが、今回の例ではすべてアルファベットを大文字で記述していましたが、SQLでは全角と半角の区別は無いため、<strong>半角で記述することも可能</strong>です。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>

<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">SQLの基本であるCRUDの書き方を理解してPHPでWebアプリ開発をしよう</h2>



<p>以上がWebアプリ開発をする際に必要不可欠なSQLの基本、CRUDの解説でした。</p>



<p>改めて、CRUDとはWebアプリにおけるデータベース操作の４つの基本機能の頭文字を取った用語でした。</p>



<div class="wp-block-group has-border -border01"><div class="wp-block-group__inner-container">
<ul class="wp-block-list is-style-check_list">
<li><strong>C</strong>reate（作成） …… <strong>INSERT文</strong></li>



<li><strong>R</strong>ead（読み取り）…… <strong>SELECT文</strong></li>



<li><strong>U</strong>pdate（更新） …… <strong>UPDATE文</strong></li>



<li><strong>D</strong>elete（削除） …… <strong>DELETE文</strong></li>
</ul>
</div></div>



<p>これらの書き方をきちんと理解できれば、Webアプリを開発することが可能です。</p>



<p>PHPの基礎を習得し、Webアプリを開発するとなれば避けては通れないSQLですが、この記事の内容が理解できたなら、実際に使えるようになるまでそう時間はかかりません。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>もしも実際にCRUDを使用している様子をご覧になりたいという場合は、以下の記事もおすすめです。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>

<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">あわせて読みたい</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/eye-catch__board-app-php__2739-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/board-app-php/">掲示板アプリの作り方｜プログラミング初心者向け【PHP】</a>
						<span class="p-blogCard__excerpt">この記事ではPHPによる 掲示板アプリの作り方 をご紹介します。 掲示板アプリを作成するためには、PHPの基本文法をはじめ、データベース操作（いわゆるCRUD）やHTTPリク&#8230;</span>					</div>
				</div>
			</div>
		</div>


<p>最後までご覧いただきありがとうございました！</p>



<p>また別の記事でお会いできるのを楽しみにしております。</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>掲示板アプリの作り方｜プログラミング初心者向け【PHP】</title>
		<link>https://kekenta-it-blog.com/board-app-php/</link>
		
		<dc:creator><![CDATA[ケケンタ]]></dc:creator>
		<pubDate>Mon, 26 Feb 2024 08:42:17 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Webアプリ]]></category>
		<guid isPermaLink="false">https://kekenta-it-blog.com/?p=2739</guid>

					<description><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/eye-catch__board-app-php__2739-1024x576.jpg" class="webfeedsFeaturedVisual" /></p>この記事ではPHPによる 掲示板アプリの作り方 をご紹介します。 掲示板アプリを作成するためには、PHPの基本文法をはじめ、データベース操作（いわゆるCRUD）やHTTPリクエストなどの知識が不可欠です。 今回ご紹介する [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/eye-catch__board-app-php__2739-1024x576.jpg" class="webfeedsFeaturedVisual" /></p>
<p>この記事では<strong>PHP</strong>による</p>



<p class="has-text-align-center is-style-big_kakko_box"><strong><span class="marker-under">掲示板アプリの作り方</span></strong></p>



<p>をご紹介します。</p>



<p>掲示板アプリを作成するためには、PHPの<strong>基本文法</strong>をはじめ、<strong>データベース操作（いわゆるCRUD）</strong>や<strong>HTTPリクエスト</strong>などの知識が不可欠です。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>PHPの基礎学習後の「総まとめ課題」として、ぜひ<strong>掲示板アプリの作り方</strong>を学んでいって下さい！</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<div class="swell-block-capbox cap_box is-style-shadow"><div class="cap_box_ttl"><span><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsLightbulb" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span><strong>この記事で分かること</strong></span></div><div class="cap_box_content">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>PHPでの掲示板アプリの作り方</li>



<li>掲示板アプリを作成するために必要な知識</li>
</ul>
</div></div>



<p>今回ご紹介する掲示板アプリは、データベース操作に加えて、<strong>セッションも組み合わせて実装</strong>しています。</p>



<p>セッションもWebアプリを開発する上でしっかり使い方を理解しておく必要があるため、ぜひ参考にしていただければと思います。</p>



<p class="is-style-alert-box has-box-style is-style-icon_info">本記事でご紹介する掲示板アプリは、機能面の解説をできるだけ簡素化するために<strong>セキュリティ対策を考慮せずに作成</strong>しています。<strong>セキュリティ対策</strong>の解説については<a href="https://kekenta-it-blog.com/php-board-app-secure/">以下の記事</a>をご覧下さい。</p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">あわせて読みたい</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/eye-catch__php-board-app-secure__3549-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/php-board-app-secure/">【PHP】掲示板アプリの作り方｜正しいセキュリティ対策</a>
						<span class="p-blogCard__excerpt">以前にこちらの記事で掲示板アプリの作成方法を解説しました。 記事内でもお伝えしているように、上の記事で解説している掲示板アプリではセキュリティ対策はしておらず&#8230;</span>					</div>
				</div>
			</div>
		</div>

<div class="swell-block-postLink">			<a href="https://kekenta-it-blog.com/alone-php-study/" class="c-blogLink -internal" data-style="text">
				<!-- <i class="c-blogLink__icon icon-link" role="presentation"></i> -->
				<span class="c-blogLink__icon">
					<svg xmlns="http://www.w3.org/2000/svg" class="swl-svg-link __svg" width="1em" height="1em" viewBox="0 0 48 48" role="img" aria-hidden="true" focusable="false"><path d="M21.2 30.2c-.5 0-1-.2-1.4-.6l-.7-.7c-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l7.1-7.1c2.3-2.3 5.3-3.5 8.5-3.5s6.2 1.2 8.5 3.5c4.7 4.7 4.7 12.3 0 17l-3.5 3.5c-.8.8-2 .8-2.8 0-.8-.8-.8-2 0-2.8l3.5-3.5c3.1-3.1 3.1-8.2 0-11.3-1.5-1.5-3.5-2.3-5.7-2.3-2.1 0-4.2.8-5.7 2.3l-7.1 7.1c-1.5 1.5-2.3 3.5-2.3 5.7s.8 4.2 2.3 5.7l.7.7c.8.8.8 2 0 2.8-.4.3-.9.5-1.4.5z" /><path d="M13.4 46.6c-3.1 0-6.1-1.2-8.5-3.5-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l3.5-3.5c.8-.8 2-.8 2.8 0 .8.8.8 2 0 2.8l-3.5 3.5c-1.5 1.5-2.3 3.5-2.3 5.7 0 2.1.8 4.2 2.3 5.7 3.1 3.1 8.2 3.1 11.3 0l7.1-7.1c1.5-1.5 2.3-3.5 2.3-5.7 0-2.1-.8-4.2-2.3-5.7l-.7-.7c-.8-.8-.8-2 0-2.8.8-.8 2-.8 2.8 0l.7.7c2.3 2.3 3.5 5.3 3.5 8.5s-1.2 6.2-3.5 8.5l-7.1 7.1c-2.3 2.3-5.3 3.5-8.4 3.5z" /></svg>				</span>
				<span class="c-blogLink__text">PHPはこうして習得した！約１年間の勉強内容【プログラミング独学】</span>
			</a>
		</div>

<div class="swell-block-postLink">			<a href="https://kekenta-it-blog.com/php-deploy-xserver-for-zip/" class="c-blogLink -internal" data-style="text">
				<!-- <i class="c-blogLink__icon icon-link" role="presentation"></i> -->
				<span class="c-blogLink__icon">
					<svg xmlns="http://www.w3.org/2000/svg" class="swl-svg-link __svg" width="1em" height="1em" viewBox="0 0 48 48" role="img" aria-hidden="true" focusable="false"><path d="M21.2 30.2c-.5 0-1-.2-1.4-.6l-.7-.7c-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l7.1-7.1c2.3-2.3 5.3-3.5 8.5-3.5s6.2 1.2 8.5 3.5c4.7 4.7 4.7 12.3 0 17l-3.5 3.5c-.8.8-2 .8-2.8 0-.8-.8-.8-2 0-2.8l3.5-3.5c3.1-3.1 3.1-8.2 0-11.3-1.5-1.5-3.5-2.3-5.7-2.3-2.1 0-4.2.8-5.7 2.3l-7.1 7.1c-1.5 1.5-2.3 3.5-2.3 5.7s.8 4.2 2.3 5.7l.7.7c.8.8.8 2 0 2.8-.4.3-.9.5-1.4.5z" /><path d="M13.4 46.6c-3.1 0-6.1-1.2-8.5-3.5-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l3.5-3.5c.8-.8 2-.8 2.8 0 .8.8.8 2 0 2.8l-3.5 3.5c-1.5 1.5-2.3 3.5-2.3 5.7 0 2.1.8 4.2 2.3 5.7 3.1 3.1 8.2 3.1 11.3 0l7.1-7.1c1.5-1.5 2.3-3.5 2.3-5.7 0-2.1-.8-4.2-2.3-5.7l-.7-.7c-.8-.8-.8-2 0-2.8.8-.8 2-.8 2.8 0l.7.7c2.3 2.3 3.5 5.3 3.5 8.5s-1.2 6.2-3.5 8.5l-7.1 7.1c-2.3 2.3-5.3 3.5-8.4 3.5z" /></svg>				</span>
				<span class="c-blogLink__text">【PHP】エックスサーバーへデプロイする方法【初心者でも簡単！】</span>
			</a>
		</div>

<div class="swell-block-postLink">			<a href="https://kekenta-it-blog.com/school-php-and-wp/" class="c-blogLink -internal" data-style="text">
				<!-- <i class="c-blogLink__icon icon-link" role="presentation"></i> -->
				<span class="c-blogLink__icon">
					<svg xmlns="http://www.w3.org/2000/svg" class="swl-svg-link __svg" width="1em" height="1em" viewBox="0 0 48 48" role="img" aria-hidden="true" focusable="false"><path d="M21.2 30.2c-.5 0-1-.2-1.4-.6l-.7-.7c-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l7.1-7.1c2.3-2.3 5.3-3.5 8.5-3.5s6.2 1.2 8.5 3.5c4.7 4.7 4.7 12.3 0 17l-3.5 3.5c-.8.8-2 .8-2.8 0-.8-.8-.8-2 0-2.8l3.5-3.5c3.1-3.1 3.1-8.2 0-11.3-1.5-1.5-3.5-2.3-5.7-2.3-2.1 0-4.2.8-5.7 2.3l-7.1 7.1c-1.5 1.5-2.3 3.5-2.3 5.7s.8 4.2 2.3 5.7l.7.7c.8.8.8 2 0 2.8-.4.3-.9.5-1.4.5z" /><path d="M13.4 46.6c-3.1 0-6.1-1.2-8.5-3.5-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l3.5-3.5c.8-.8 2-.8 2.8 0 .8.8.8 2 0 2.8l-3.5 3.5c-1.5 1.5-2.3 3.5-2.3 5.7 0 2.1.8 4.2 2.3 5.7 3.1 3.1 8.2 3.1 11.3 0l7.1-7.1c1.5-1.5 2.3-3.5 2.3-5.7 0-2.1-.8-4.2-2.3-5.7l-.7-.7c-.8-.8-.8-2 0-2.8.8-.8 2-.8 2.8 0l.7.7c2.3 2.3 3.5 5.3 3.5 8.5s-1.2 6.2-3.5 8.5l-7.1 7.1c-2.3 2.3-5.3 3.5-8.4 3.5z" /></svg>				</span>
				<span class="c-blogLink__text">PHPやWordPressを学ぶのにおすすめのプログラミングスクール【７選】</span>
			</a>
		</div>


<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h2 class="wp-block-heading">掲示板アプリのイメージ</h2>



<p>あれこれと説明を始める前に、まずは<strong>掲示板アプリのイメージ</strong>を掴んでいただくことが大切かと思いますので、先に<strong>３つの基本機能</strong>のイメージをお伝えします。</p>



<div class="swell-block-capbox cap_box is-style-shadow" data-colset="col1"><div class="cap_box_ttl"><span><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsLightbulb" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span><strong>掲示板アプリの基本機能</strong></span></div><div class="cap_box_content">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>投稿</li>



<li>編集</li>



<li>削除</li>
</ul>
</div></div>



<p>まず、今回作成する掲示板アプリの<strong>トップページ</strong>がこちらです。</p>


<div class="wp-block-image is-style-shadow">
<figure data-wp-context="{&quot;imageId&quot;:&quot;69e3e8ad03808&quot;}" data-wp-interactive="core/image" data-wp-key="69e3e8ad03808" class="aligncenter size-full is-resized has-custom-border wp-lightbox-container"><img decoding="async" width="777" height="912" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://kekenta-it-blog.com/wp-content/uploads/2024/02/image-7.png" alt="掲示板アプリトップページ" class="wp-image-2747" style="border-width:1px;width:539px;height:auto" srcset="https://kekenta-it-blog.com/wp-content/uploads/2024/02/image-7.png 777w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/image-7-256x300.png 256w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/image-7-768x901.png 768w" sizes="(max-width: 777px) 100vw, 777px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="拡大する"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">トップページ</figcaption></figure>
</div>


<p>続いて、以下が<strong>各機能のイメージ</strong>です。</p>



<h3 class="wp-block-heading">投稿機能</h3>


<div class="wp-block-image is-style-shadow size_s">
<figure data-wp-context="{&quot;imageId&quot;:&quot;69e3e8ad03d34&quot;}" data-wp-interactive="core/image" data-wp-key="69e3e8ad03d34" class="aligncenter size-large wp-lightbox-container"><img decoding="async" width="1024" height="1008" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://kekenta-it-blog.com/wp-content/uploads/2024/02/8d5c3c671b07078cad80b5eabfc440e3-1024x1008.jpg" alt="掲示板アプリ投稿機能の流れ" class="wp-image-3100" srcset="https://kekenta-it-blog.com/wp-content/uploads/2024/02/8d5c3c671b07078cad80b5eabfc440e3-1024x1008.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/8d5c3c671b07078cad80b5eabfc440e3-300x295.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/8d5c3c671b07078cad80b5eabfc440e3-768x756.jpg 768w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/8d5c3c671b07078cad80b5eabfc440e3-1536x1512.jpg 1536w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/8d5c3c671b07078cad80b5eabfc440e3-2048x2016.jpg 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="拡大する"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">投稿機能の流れ</figcaption></figure>
</div>


<div class="swell-block-capbox cap_box is-style-shadow"><div class="cap_box_ttl"><span><span data-icon="FasCircleCheck" data-id="0" style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGQ9Ik0yNTYgNTEyYzE0MS40IDAgMjU2LTExNC42IDI1Ni0yNTZTMzk3LjQgMCAyNTYgMFMwIDExNC42IDAgMjU2UzExNC42IDUxMiAyNTYgNTEyek0zNjkgMjA5TDI0MSAzMzdjLTkuNCA5LjQtMjQuNiA5LjQtMzMuOSAwbC02NC02NGMtOS40LTkuNC05LjQtMjQuNiAwLTMzLjlzMjQuNi05LjQgMzMuOSAwbDQ3IDQ3TDMzNSAxNzVjOS40LTkuNCAyNC42LTkuNCAzMy45IDBzOS40IDI0LjYgMCAzMy45eiI+PC9wYXRoPjwvc3ZnPg==)" aria-hidden="true" class="swl-inline-icon"> </span> <strong>投稿機能の流れ</strong></span></div><div class="cap_box_content">
<ul class="wp-block-list is-style-num_circle -list-under-dashed">
<li>「タイトル」と「投稿内容」に任意のテキストを入力</li>



<li>「投稿ボタン」を押下</li>



<li>投稿一覧に投稿が追加される</li>
</ul>
</div></div>



<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h3 class="wp-block-heading">編集機能</h3>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e3e8ad045c7&quot;}" data-wp-interactive="core/image" data-wp-key="69e3e8ad045c7" class="wp-block-image size-large is-style-shadow size_s wp-lightbox-container"><img decoding="async" width="1024" height="809" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://kekenta-it-blog.com/wp-content/uploads/2024/02/8ba6d47fc77f50f3162e15c0a8d4dc19-1024x809.jpg" alt="掲示板アプリ投稿編集機能の流れ" class="wp-image-3052" srcset="https://kekenta-it-blog.com/wp-content/uploads/2024/02/8ba6d47fc77f50f3162e15c0a8d4dc19-1024x809.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/8ba6d47fc77f50f3162e15c0a8d4dc19-300x237.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/8ba6d47fc77f50f3162e15c0a8d4dc19-768x607.jpg 768w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/8ba6d47fc77f50f3162e15c0a8d4dc19-1536x1213.jpg 1536w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/8ba6d47fc77f50f3162e15c0a8d4dc19-2048x1617.jpg 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="拡大する"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">編集機能の流れ</figcaption></figure>



<div class="swell-block-capbox cap_box is-style-shadow"><div class="cap_box_ttl"><span><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGQ9Ik0yNTYgNTEyYzE0MS40IDAgMjU2LTExNC42IDI1Ni0yNTZTMzk3LjQgMCAyNTYgMFMwIDExNC42IDAgMjU2UzExNC42IDUxMiAyNTYgNTEyek0zNjkgMjA5TDI0MSAzMzdjLTkuNCA5LjQtMjQuNiA5LjQtMzMuOSAwbC02NC02NGMtOS40LTkuNC05LjQtMjQuNiAwLTMzLjlzMjQuNi05LjQgMzMuOSAwbDQ3IDQ3TDMzNSAxNzVjOS40LTkuNCAyNC42LTkuNCAzMy45IDBzOS40IDI0LjYgMCAzMy45eiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasCircleCheck" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span> <strong>編集機能の流れ</strong></span></div><div class="cap_box_content">
<ul class="wp-block-list is-style-num_circle -list-under-dashed">
<li>編集したい投稿の「編集ボタン」を押下</li>



<li>投稿編集画面へ遷移</li>



<li>編集内容を入力</li>



<li>「更新ボタン」を押下</li>



<li>掲示板トップへ遷移</li>



<li>投稿に編集内容が反映、また「更新しました」が表示される</li>
</ul>
</div></div>



<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h3 class="wp-block-heading">削除機能</h3>


<div class="wp-block-image is-style-shadow size_s">
<figure data-wp-context="{&quot;imageId&quot;:&quot;69e3e8ad04e5c&quot;}" data-wp-interactive="core/image" data-wp-key="69e3e8ad04e5c" class="aligncenter size-large wp-lightbox-container"><img decoding="async" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://kekenta-it-blog.com/wp-content/uploads/2024/02/98ba59fab650b7da59c78996601fbefd-1024x646.jpg" alt="掲示板アプリ投稿削除機能の流れ" class="wp-image-3058"/><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="拡大する"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">削除機能の流れ</figcaption></figure>
</div>


<div class="swell-block-capbox cap_box is-style-shadow" data-colset="col3"><div class="cap_box_ttl"><span><strong><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGQ9Ik0yNTYgNTEyYzE0MS40IDAgMjU2LTExNC42IDI1Ni0yNTZTMzk3LjQgMCAyNTYgMFMwIDExNC42IDAgMjU2UzExNC42IDUxMiAyNTYgNTEyek0zNjkgMjA5TDI0MSAzMzdjLTkuNCA5LjQtMjQuNiA5LjQtMzMuOSAwbC02NC02NGMtOS40LTkuNC05LjQtMjQuNiAwLTMzLjlzMjQuNi05LjQgMzMuOSAwbDQ3IDQ3TDMzNSAxNzVjOS40LTkuNCAyNC42LTkuNCAzMy45IDBzOS40IDI0LjYgMCAzMy45eiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasCircleCheck" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span> 削除機能の流れ</strong></span></div><div class="cap_box_content">
<ul class="wp-block-list is-style-num_circle -list-under-dashed">
<li>削除したい投稿の「削除ボタン」を押下</li>



<li>削除確認画面へ遷移</li>



<li>「削除ボタン」を押下</li>



<li>削除完了画面へ遷移</li>



<li>3秒後に自動で掲示板トップへ遷移</li>
</ul>
</div></div>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h2 class="wp-block-heading">掲示板アプリを作成するために必要な知識・スキル</h2>



<p>ここまで、<strong>掲示板アプリのイメージ</strong>をお見せしました。</p>



<p>では、この掲示板アプリを実際に作成するためには、具体的に<strong>どういった知識・スキルが必要になるのでしょうか？</strong></p>



<p>本章では、<strong><span class="swl-marker mark_yellow">掲示板アプリを作成する際に必要となる知識</span></strong>についてご紹介します。</p>



<div class="swell-block-capbox cap_box" data-colset="col1"><div class="cap_box_ttl"><span><span data-icon="LsLightbulb" data-id="0" style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" aria-hidden="true" class="swl-inline-icon"> </span><strong>掲示板アプリ作成で必要な知識・スキル</strong></span></div><div class="cap_box_content">
<ul class="wp-block-list -list-under-dashed is-style-num_circle">
<li>PHPの基本文法</li>



<li>HTTPリクエスト（POST送信）</li>



<li>データベース操作（PDO）</li>



<li>セッション</li>



<li>SQL</li>
</ul>
</div></div>



<p class="is-style-memo-box has-box-style is-style-icon_info">本番環境への公開を前提とするなら、上記に加えて<strong>セキュリティ対策</strong>の知識も不可欠となります。<br>※詳しくは<a href="https://kekenta-it-blog.com/php-board-app-secure">以下の記事</a>で解説をしています。</p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">あわせて読みたい</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/eye-catch__php-board-app-secure__3549-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/php-board-app-secure/">【PHP】掲示板アプリの作り方｜正しいセキュリティ対策</a>
						<span class="p-blogCard__excerpt">以前にこちらの記事で掲示板アプリの作成方法を解説しました。 記事内でもお伝えしているように、上の記事で解説している掲示板アプリではセキュリティ対策はしておらず&#8230;</span>					</div>
				</div>
			</div>
		</div>


<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<p>PHPの基礎を学ばれてきた方であれば、上記に並んでいる知識・スキル名は恐らく見たことのあるものがほとんどかと思います。</p>



<p>しかし、この中で<strong>PDO</strong>については初めて聞くという方が比較的多いことが予想されるため簡単に説明します。</p>



<div class="swell-block-capbox cap_box" data-colset="col1"><div class="cap_box_ttl"><span><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsLightbulb" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span><strong>PDOとは？</strong></span></div><div class="cap_box_content">
<p>PDOとは、<strong><span class="swl-marker mark_yellow">PHPからデータベースへ簡単にアクセスできるようにするための拡張モジュール</span></strong>です。</p>



<p>通常、データベース関係の処理はMySQLならMySQL用に、PostgreSQLならPostgreSQL用に記述する必要があります。しかし、PDOを利用すると<strong>同じ処理の書き方で異なるデータベースソフトウェアと連携することが可能</strong>となります。</p>



<p>これにより、PHPでデータベース操作するのが楽になります。</p>
</div></div>



<p>今回の掲示板アプリ作成には上記５つの知識・スキルの理解が必須です。</p>



<p>この記事をご覧いただく分には問題ありませんが、実際にご自身で掲示板アプリを作成してみようとなったとき、理解が不足していると感じるものがあるようであれば以下の記事を参考にしていただければと思います。</p>



<p class="is-style-balloon_box"><strong>参考記事</strong></p>


<div class="swell-block-postLink">			<a href="https://kekenta-it-blog.com/http-request-get-post/" class="c-blogLink -internal" data-style="text">
				<!-- <i class="c-blogLink__icon icon-link" role="presentation"></i> -->
				<span class="c-blogLink__icon">
					<svg xmlns="http://www.w3.org/2000/svg" class="swl-svg-link __svg" width="1em" height="1em" viewBox="0 0 48 48" role="img" aria-hidden="true" focusable="false"><path d="M21.2 30.2c-.5 0-1-.2-1.4-.6l-.7-.7c-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l7.1-7.1c2.3-2.3 5.3-3.5 8.5-3.5s6.2 1.2 8.5 3.5c4.7 4.7 4.7 12.3 0 17l-3.5 3.5c-.8.8-2 .8-2.8 0-.8-.8-.8-2 0-2.8l3.5-3.5c3.1-3.1 3.1-8.2 0-11.3-1.5-1.5-3.5-2.3-5.7-2.3-2.1 0-4.2.8-5.7 2.3l-7.1 7.1c-1.5 1.5-2.3 3.5-2.3 5.7s.8 4.2 2.3 5.7l.7.7c.8.8.8 2 0 2.8-.4.3-.9.5-1.4.5z" /><path d="M13.4 46.6c-3.1 0-6.1-1.2-8.5-3.5-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l3.5-3.5c.8-.8 2-.8 2.8 0 .8.8.8 2 0 2.8l-3.5 3.5c-1.5 1.5-2.3 3.5-2.3 5.7 0 2.1.8 4.2 2.3 5.7 3.1 3.1 8.2 3.1 11.3 0l7.1-7.1c1.5-1.5 2.3-3.5 2.3-5.7 0-2.1-.8-4.2-2.3-5.7l-.7-.7c-.8-.8-.8-2 0-2.8.8-.8 2-.8 2.8 0l.7.7c2.3 2.3 3.5 5.3 3.5 8.5s-1.2 6.2-3.5 8.5l-7.1 7.1c-2.3 2.3-5.3 3.5-8.4 3.5z" /></svg>				</span>
				<span class="c-blogLink__text">【PHP】HTTPリクエストとは？GETとPOSTの意味</span>
			</a>
		</div>

<div class="swell-block-postLink">			<a href="https://kekenta-it-blog.com/php-session-cookie/" class="c-blogLink -internal" data-style="text">
				<!-- <i class="c-blogLink__icon icon-link" role="presentation"></i> -->
				<span class="c-blogLink__icon">
					<svg xmlns="http://www.w3.org/2000/svg" class="swl-svg-link __svg" width="1em" height="1em" viewBox="0 0 48 48" role="img" aria-hidden="true" focusable="false"><path d="M21.2 30.2c-.5 0-1-.2-1.4-.6l-.7-.7c-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l7.1-7.1c2.3-2.3 5.3-3.5 8.5-3.5s6.2 1.2 8.5 3.5c4.7 4.7 4.7 12.3 0 17l-3.5 3.5c-.8.8-2 .8-2.8 0-.8-.8-.8-2 0-2.8l3.5-3.5c3.1-3.1 3.1-8.2 0-11.3-1.5-1.5-3.5-2.3-5.7-2.3-2.1 0-4.2.8-5.7 2.3l-7.1 7.1c-1.5 1.5-2.3 3.5-2.3 5.7s.8 4.2 2.3 5.7l.7.7c.8.8.8 2 0 2.8-.4.3-.9.5-1.4.5z" /><path d="M13.4 46.6c-3.1 0-6.1-1.2-8.5-3.5-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l3.5-3.5c.8-.8 2-.8 2.8 0 .8.8.8 2 0 2.8l-3.5 3.5c-1.5 1.5-2.3 3.5-2.3 5.7 0 2.1.8 4.2 2.3 5.7 3.1 3.1 8.2 3.1 11.3 0l7.1-7.1c1.5-1.5 2.3-3.5 2.3-5.7 0-2.1-.8-4.2-2.3-5.7l-.7-.7c-.8-.8-.8-2 0-2.8.8-.8 2-.8 2.8 0l.7.7c2.3 2.3 3.5 5.3 3.5 8.5s-1.2 6.2-3.5 8.5l-7.1 7.1c-2.3 2.3-5.3 3.5-8.4 3.5z" /></svg>				</span>
				<span class="c-blogLink__text">【PHP】セッションとクッキー？違いと使い方を解説</span>
			</a>
		</div>

<div class="swell-block-postLink">			<a href="https://kekenta-it-blog.com/php-sql-basic/" class="c-blogLink -internal" data-style="text">
				<!-- <i class="c-blogLink__icon icon-link" role="presentation"></i> -->
				<span class="c-blogLink__icon">
					<svg xmlns="http://www.w3.org/2000/svg" class="swl-svg-link __svg" width="1em" height="1em" viewBox="0 0 48 48" role="img" aria-hidden="true" focusable="false"><path d="M21.2 30.2c-.5 0-1-.2-1.4-.6l-.7-.7c-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l7.1-7.1c2.3-2.3 5.3-3.5 8.5-3.5s6.2 1.2 8.5 3.5c4.7 4.7 4.7 12.3 0 17l-3.5 3.5c-.8.8-2 .8-2.8 0-.8-.8-.8-2 0-2.8l3.5-3.5c3.1-3.1 3.1-8.2 0-11.3-1.5-1.5-3.5-2.3-5.7-2.3-2.1 0-4.2.8-5.7 2.3l-7.1 7.1c-1.5 1.5-2.3 3.5-2.3 5.7s.8 4.2 2.3 5.7l.7.7c.8.8.8 2 0 2.8-.4.3-.9.5-1.4.5z" /><path d="M13.4 46.6c-3.1 0-6.1-1.2-8.5-3.5-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l3.5-3.5c.8-.8 2-.8 2.8 0 .8.8.8 2 0 2.8l-3.5 3.5c-1.5 1.5-2.3 3.5-2.3 5.7 0 2.1.8 4.2 2.3 5.7 3.1 3.1 8.2 3.1 11.3 0l7.1-7.1c1.5-1.5 2.3-3.5 2.3-5.7 0-2.1-.8-4.2-2.3-5.7l-.7-.7c-.8-.8-.8-2 0-2.8.8-.8 2-.8 2.8 0l.7.7c2.3 2.3 3.5 5.3 3.5 8.5s-1.2 6.2-3.5 8.5l-7.1 7.1c-2.3 2.3-5.3 3.5-8.4 3.5z" /></svg>				</span>
				<span class="c-blogLink__text">SQLの書き方｜PHPでアプリ開発するなら必須のCRUDとは？</span>
			</a>
		</div>


<p>なお、以下の書籍「<strong>PHP本格入門（上）</strong>」では、SQLを除く<strong>掲示板アプリを作成するために必要な知識</strong>を網羅的に学習することが可能です。</p>


<div id="rinkerid3653" class="yyi-rinker-contents  yyi-rinker-postid-3653 yyi-rinker-img-m yyi-rinker-catid-5 yyi-rinker-catid-72 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://hb.afl.rakuten.co.jp/hgc/g00q072g.bdzz22a5.g00q072g.bdzz326e/Rinker_i_20240325050010?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fbook%2F16371381%2F&#038;m=http%3A%2F%2Fm.rakuten.co.jp%2Fbook%2Fi%2F20055321%2F&#038;rafcid=wsc_i_is_1047822029026699702" rel="nofollow" class="yyi-rinker-tracking"  data-click-tracking="rakuten_img 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]" data-vars-click-id="rakuten_img 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]"><img decoding="async" src="https://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/4688/9784297114688.jpg?_ex=128x128"  width="128" height="128" class="yyi-rinker-main-img" style="border: none;"></a>					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://hb.afl.rakuten.co.jp/hgc/g00q072g.bdzz22a5.g00q072g.bdzz326e/Rinker_t_20240325050010?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fbook%2F16371381%2F&#038;m=http%3A%2F%2Fm.rakuten.co.jp%2Fbook%2Fi%2F20055321%2F&#038;rafcid=wsc_i_is_1047822029026699702" rel="nofollow" class="yyi-rinker-tracking" data-click-tracking="rakuten_title 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]" data-vars-amp-click-id="rakuten_title 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]" >PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]</a>							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							<span title="" class="price">¥3,938</span>
															<span class="price_at">(2026/04/18 18:42:17時点&nbsp;楽天市場調べ-</span><span title="このサイトで掲載されている情報は当サイトの作成者により運営されています。価格、販売可能情報は、変更される場合があります。購入時に楽天市場店舗（www.rakuten.co.jp）に表示されている価格がその商品の販売に適用されます。">詳細)</span>
																	</div>
						</div>
						<ul class="yyi-rinker-links">
																	<li class="amazonkindlelink">
						<a href="https://www.amazon.co.jp/PHP%E6%9C%AC%E6%A0%BC%E5%85%A5%E9%96%80%EF%BC%BB%E4%B8%8A%EF%BC%BD-%EF%BD%9E%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%A8%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E3%81%AE%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E9%80%A3%E6%90%BA%E3%81%BE%E3%81%A7-%E5%A4%A7%E5%AE%B6-%E6%AD%A3%E7%99%BB-ebook/dp/B08DXRK18C?_encoding=UTF8&amp;dib_tag=se&amp;dib=eyJ2IjoiMSJ9.74YDItYNn-AHro6XQ1cSslRSHUvp_S8S4MVJtvnW_XswliMGieYQktGbaTJY9E-Qpy3y3roMKB8M-zKI3K7otpqjDxkuoq7ncq-6mLf3BEkcNW05BAHDZZ17WZueAniDY7peSrmp4Ji0L0BkXOaJIBbpqa628I6bjQBED1FQ9V7BJqUJVUUxz6ns2GIHnoSItDTgCRaIpNi9fMcBrt3jqZr1qNJxCmBn8-xPR9N3usFpENEEChvMwvGdHoHu1hjsq6g9GvJDwPPBTwhQvDgXG2KZQ5CBlEx_wQjQy06hFcw.xxCKw6aGhA397JIEATXvL3RNC7D4_k4avRIYczzkjHw&amp;qid=1723712413&amp;sr=8-6&amp;linkCode=ll1&amp;tag=kekenta03am0b-22&amp;linkId=8de435cc399443bbfb43b9e7b8e0c9f1&amp;language=ja_JP&amp;ref_=as_li_ss_tl" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon_kindle 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]"  data-vars-amp-click-id="amazon_kindle 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]">Kindle</a>					</li>
								                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/PHP%E6%9C%AC%E6%A0%BC%E5%85%A5%E9%96%80-%E4%B8%8A-%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%A8%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E3%81%AE%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E9%80%A3%E6%90%BA%E3%81%BE%E3%81%A7-%E5%A4%A7%E5%AE%B6-%E6%AD%A3%E7%99%BB/dp/4297114682?dib=eyJ2IjoiMSJ9.74YDItYNn-AHro6XQ1cSslRSHUvp_S8S4MVJtvnW_XswliMGieYQktGbaTJY9E-Qpy3y3roMKB8M-zKI3K7otpqjDxkuoq7ncq-6mLf3BEkcNW05BAHDZZ17WZueAniDY7peSrmp4Ji0L0BkXOaJIBbpqa628I6bjQBED1FQ9V7BJqUJVUUxz6ns2GIHnoSItDTgCRaIpNi9fMcBrt3jqZr1qNJxCmBn8-xPR9N3usFpENEEChvMwvGdHoHu1hjsq6g9GvJDwPPBTwhQvDgXG2KZQ5CBlEx_wQjQy06hFcw.xxCKw6aGhA397JIEATXvL3RNC7D4_k4avRIYczzkjHw&amp;dib_tag=se&amp;keywords=PHP%E6%9C%AC%E6%A0%BC%E5%85%A5%E9%96%80&amp;qid=1723712413&amp;sr=8-6&amp;linkCode=ll1&amp;tag=kekenta03am0b-22&amp;linkId=16a4b7edeeedcc86aef9f0b8c45cc669&amp;language=ja_JP&amp;ref_=as_li_ss_tl" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]"  data-vars-amp-click-id="amazon 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://hb.afl.rakuten.co.jp/hgc/g00q072g.bdzz22a5.g00q072g.bdzz326e/Rinker_t_20240325050010?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fbook%2F16371381%2F&amp;m=http%3A%2F%2Fm.rakuten.co.jp%2Fbook%2Fi%2F20055321%2F&amp;rafcid=wsc_i_is_1047822029026699702" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="rakuten 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]"  data-vars-amp-click-id="rakuten 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]">楽天市場</a>					</li>
								                											</ul>
					</div>
	</div>
</div>



<p>当記事とこちらの書籍を組み合わせて学習することで、掲示板アプリの作成方法をよりしっかりと理解できるようになるかと思います。</p>



<p>ちなみに僕自身、<strong><span class="swl-marker mark_yellow">PHPはこの書籍で学習し、知識を組み合わせて使用することで初めてのWebアプリを作成</span>しました。</strong></p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>また、<strong>SQLを学びたい方</strong>には評判の良い以下の書籍がおすすめです。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>

<div id="rinkerid4622" class="yyi-rinker-contents  yyi-rinker-postid-4622 yyi-rinker-img-m yyi-rinker-catid-5 yyi-rinker-catid-72 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://hb.afl.rakuten.co.jp/hgc/g00q072g.bdzz22a5.g00q072g.bdzz326e/Rinker_i_20240414220830?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fbook%2F14244722%2F&#038;m=http%3A%2F%2Fm.rakuten.co.jp%2Fbook%2Fi%2F18029096%2F&#038;rafcid=wsc_i_is_1047822029026699702" rel="nofollow" class="yyi-rinker-tracking"  data-click-tracking="rakuten_img 4622 SQL 第2版 ゼロからはじめるデータベース操作 （プログラミング学習シリーズ） [ ミック ]" data-vars-click-id="rakuten_img 4622 SQL 第2版 ゼロからはじめるデータベース操作 （プログラミング学習シリーズ） [ ミック ]"><img decoding="async" src="https://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/4450/9784798144450.jpg?_ex=128x128"  width="128" height="128" class="yyi-rinker-main-img" style="border: none;"></a>					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://hb.afl.rakuten.co.jp/hgc/g00q072g.bdzz22a5.g00q072g.bdzz326e/Rinker_t_20240414220830?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fbook%2F14244722%2F&#038;m=http%3A%2F%2Fm.rakuten.co.jp%2Fbook%2Fi%2F18029096%2F&#038;rafcid=wsc_i_is_1047822029026699702" rel="nofollow" class="yyi-rinker-tracking" data-click-tracking="rakuten_title 4622 SQL 第2版 ゼロからはじめるデータベース操作 （プログラミング学習シリーズ） [ ミック ]" data-vars-amp-click-id="rakuten_title 4622 SQL 第2版 ゼロからはじめるデータベース操作 （プログラミング学習シリーズ） [ ミック ]" >SQL 第2版 ゼロからはじめるデータベース操作 （プログラミング学習シリーズ） [ ミック ]</a>							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							<span title="" class="price">¥2,068</span>
															<span class="price_at">(2026/04/19 05:25:17時点&nbsp;楽天市場調べ-</span><span title="このサイトで掲載されている情報は当サイトの作成者により運営されています。価格、販売可能情報は、変更される場合があります。購入時に楽天市場店舗（www.rakuten.co.jp）に表示されている価格がその商品の販売に適用されます。">詳細)</span>
																	</div>
						</div>
						<ul class="yyi-rinker-links">
																                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/SQL-%E7%AC%AC2%E7%89%88-%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E3%81%AF%E3%81%98%E3%82%81%E3%82%8B%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E6%93%8D%E4%BD%9C-%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%AD%A6%E7%BF%92%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E3%83%9F%E3%83%83%E3%82%AF/dp/4798144452?dib=eyJ2IjoiMSJ9.Gha92xTl0ZFaee14G892xe4zf0QiceaA4Ew3DsBGK11sQ_-vR-u4Gwd-dnrUsU9Q1UotjJMWYrRD2-WFAaTqC1Q8GJ5nxih0Z2p0EH_nKomAFiY4Iobc0f5SG9l17gRovGsw-VWbda7dpyBLUwXH9i6cwHTeskh66PreykK7oLpaWTUvJW--T49Yt7d6rbzv24yKsDPJaq2MnQpR90EyvJdUOm0AyQqOIhn2vLhCfFSMPXjw1LBDrb04jC6Bmg-4VKPwow794c9gD6ymSqnFqYRBb6Zkb6ZJnh8hWx9HSPw.gqxjtRZ05W9yKQMgHst1pMTMNf76vfQmPDhisrDtpzo&amp;dib_tag=se&amp;keywords=SQL&amp;qid=1723712055&amp;sr=8-3-spons&amp;sp_csd=d2lkZ2V0TmFtZT1zcF9hdGY&amp;psc=1&amp;linkCode=ll1&amp;tag=kekenta03am0b-22&amp;linkId=3af9337baca3e8523638320f05afb991&amp;language=ja_JP&amp;ref_=as_li_ss_tl" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon 4622 SQL 第2版 ゼロからはじめるデータベース操作 （プログラミング学習シリーズ） [ ミック ]"  data-vars-amp-click-id="amazon 4622 SQL 第2版 ゼロからはじめるデータベース操作 （プログラミング学習シリーズ） [ ミック ]">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://hb.afl.rakuten.co.jp/hgc/g00q072g.bdzz22a5.g00q072g.bdzz326e/Rinker_t_20240414220830?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fbook%2F14244722%2F&amp;m=http%3A%2F%2Fm.rakuten.co.jp%2Fbook%2Fi%2F18029096%2F&amp;rafcid=wsc_i_is_1047822029026699702" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="rakuten 4622 SQL 第2版 ゼロからはじめるデータベース操作 （プログラミング学習シリーズ） [ ミック ]"  data-vars-amp-click-id="rakuten 4622 SQL 第2版 ゼロからはじめるデータベース操作 （プログラミング学習シリーズ） [ ミック ]">楽天市場</a>					</li>
								                											</ul>
					</div>
	</div>
</div>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h2 class="wp-block-heading">仕様①｜作成する掲示板アプリ</h2>



<p>話がそれてしまいましたが、ここからは<strong>掲示板アプリの仕様</strong>をご説明していきます。</p>



<p>なお、細かな仕様はこのあとすぐにご説明しますが、今回作成する掲示板アプリは機能をより簡潔にするため</p>



<p class="is-style-bg_stripe"><strong><span class="marker-under">ログイン機能を持っていない匿名掲示板</span></strong></p>



<p>となっています。</p>



<p>ただし、匿名と言いつつも、投稿者のことは、セッションを利用して<strong>一定時間、一意に識別する仕様</strong>としています。</p>



<p>※セッションの解説を加えたかったため、あえてこのような仕様としました。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p><strong>ログイン機能を持つ掲示板</strong>は今後別の記事でご紹介する予定です！</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<h3 class="wp-block-heading">基本仕様</h3>



<p>以下が掲示板アプリの<strong>基本的な仕様</strong>です。</p>



<h4 class="wp-block-heading">基本機能</h4>



<p class="is-style-bg_stripe">データベース操作の基本である<strong>CRUD</strong>をすべて使用できるように、投稿機能だけでなく敢えて<strong>編集・削除機能</strong>も持たせています。</p>



<figure class="wp-block-table is-style-regular"><table><thead><tr><th>機能</th><th>説明</th><th>CRUD対応</th></tr></thead><tbody><tr><td>投稿</td><td>「タイトル」と「投稿内容」の<strong>投稿</strong>が可能</td><td><strong>C</strong>reate</td></tr><tr><td>投稿一覧表示</td><td>投稿されている投稿一覧を<strong>表示</strong></td><td><strong>R</strong>ead</td></tr><tr><td>編集</td><td>投稿後、最短30分間のみ投稿の<strong>編集</strong>が可能</td><td><strong>U</strong>pdate</td></tr><tr><td>削除</td><td>投稿後、最短30分間のみ投稿の<strong>削除</strong>が可能</td><td><strong>D</strong>elete</td></tr></tbody></table><figcaption class="wp-element-caption">掲示板アプリの基本機能</figcaption></figure>



<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h4 class="wp-block-heading">投稿一覧に表示する情報</h4>



<figure class="wp-block-table"><table><thead><tr><th>情報名</th><th>備考</th></tr></thead><tbody><tr><th>投稿ID</th><td>自動連番</td></tr><tr><th>投稿タイトル</th><td>最大30文字まで（以降は切り捨て）</td></tr><tr><th>投稿者ID</th><td>投稿者を一意に識別するためのID（セッションで管理）</td></tr><tr><th>投稿内容</th><td>最大1000文字まで（以降は切り捨て）</td></tr><tr><th>投稿日時</th><td></td></tr><tr><th>投稿更新日時</th><td>「編集」が行われた投稿にのみ表示</td></tr></tbody></table><figcaption class="wp-element-caption">投稿一覧に表示する情報</figcaption></figure>


<div class="wp-block-image is-style-shadow">
<figure class="aligncenter size-full has-custom-border"><img decoding="async" width="776" height="463" src="https://kekenta-it-blog.com/wp-content/uploads/2024/02/9d7a106d8c9e71d482ae17dd8f023eac-1.jpg" alt="掲示板アプリ投稿一覧表示情報" class="wp-image-2782" style="border-width:1px" srcset="https://kekenta-it-blog.com/wp-content/uploads/2024/02/9d7a106d8c9e71d482ae17dd8f023eac-1.jpg 776w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/9d7a106d8c9e71d482ae17dd8f023eac-1-300x179.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/9d7a106d8c9e71d482ae17dd8f023eac-1-768x458.jpg 768w" sizes="(max-width: 776px) 100vw, 776px" /></figure>
</div>


<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h4 class="wp-block-heading">補足機能</h4>



<p>掲示板アプリの基本機能の他に、以下の<strong>補足機能</strong>を実装しています。</p>



<div class="swell-block-capbox cap_box is-style-shadow u-mb-ctrl u-mb-30"><div class="cap_box_ttl"><span><strong>１．タイトルと投稿内容の入力は必須とする</strong></span></div><div class="cap_box_content"><div class="wp-block-image size_s">
<figure class="aligncenter size-full has-custom-border"><img decoding="async" width="732" height="290" src="https://kekenta-it-blog.com/wp-content/uploads/2024/02/image-8.png" alt="未入力のときはエラーメッセージを表示" class="wp-image-2760" style="border-width:1px" srcset="https://kekenta-it-blog.com/wp-content/uploads/2024/02/image-8.png 732w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/image-8-300x119.png 300w" sizes="(max-width: 732px) 100vw, 732px" /><figcaption class="wp-element-caption">未入力のときはエラーメッセージを表示</figcaption></figure>
</div></div></div>



<div class="swell-block-capbox cap_box is-style-shadow"><div class="cap_box_ttl"><span><strong>２．更新した投稿の右下に「更新しました」と表示</strong></span></div><div class="cap_box_content"><div class="wp-block-image size_s">
<figure class="aligncenter size-full has-custom-border"><img decoding="async" width="676" height="460" src="https://kekenta-it-blog.com/wp-content/uploads/2024/02/image-9.png" alt="更新されたら右下にメッセージを表示" class="wp-image-2761" style="border-width:1px" srcset="https://kekenta-it-blog.com/wp-content/uploads/2024/02/image-9.png 676w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/image-9-300x204.png 300w" sizes="(max-width: 676px) 100vw, 676px" /><figcaption class="wp-element-caption">更新されたら右下にメッセージを表示</figcaption></figure>
</div></div></div>



<ul class="wp-block-list is-style-check_list">
<li></li>
</ul>



<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h4 class="wp-block-heading">投稿者の識別方法・関連機能</h4>



<p>先ほど、今回ご紹介する掲示板アプリは<strong><span class="swl-inline-color has-swl-deep-02-color">ログイン機能を持たない匿名掲示板</span></strong>とお伝えをしました。</p>



<p>しかし、ログイン機能を持たない代わりに、セッションを利用して<strong>投稿者を一定時間、一意に識別する仕様</strong>としています。</p>



<p>具体的な仕様は以下のとおりです。</p>



<div class="swell-block-capbox cap_box is-style-shadow"><div class="cap_box_ttl"><span><strong><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGQ9Ik0yNTYgNTEyYzE0MS40IDAgMjU2LTExNC42IDI1Ni0yNTZTMzk3LjQgMCAyNTYgMFMwIDExNC42IDAgMjU2UzExNC42IDUxMiAyNTYgNTEyek0zNjkgMjA5TDI0MSAzMzdjLTkuNCA5LjQtMjQuNiA5LjQtMzMuOSAwbC02NC02NGMtOS40LTkuNC05LjQtMjQuNiAwLTMzLjlzMjQuNi05LjQgMzMuOSAwbDQ3IDQ3TDMzNSAxNzVjOS40LTkuNCAyNC42LTkuNCAzMy45IDBzOS40IDI0LjYgMCAzMy45eiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasCircleCheck" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span> 投稿者の識別方法・関連機能</strong></span></div><div class="cap_box_content">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>投稿者には初アクセス時に<strong>固有ID</strong>を割り振る</li>



<li>固有IDは<strong>セッションで保持</strong></li>



<li>掲示板へアクセスまたは何らからの操作を行ってから<strong>30分間</strong>は同じIDで投稿が可能</li>



<li>投稿したときのIDが有効な間、投稿者は<strong>自身の投稿に対してのみ「編集」、「削除」が行える</strong></li>
</ul>
</div></div>



<p>分かりやすくいうと、ユーザの初アクセス時に<strong><span class="swl-inline-color has-swl-deep-02-color">最短30分間のみ有効なチケット</span></strong>を配るイメージです。</p>



<p>ユーザが初アクセスまたは何らかの操作を行うことで、同じIDのチケットが再度配られます。</p>



<p>一方、ユーザがチケットを受け取ってから30分以上何もしないと<strong>配られたチケットは無効</strong>となり、再度投稿を行う（または掲示板へ再度アクセスする）ことで<strong>別IDが記載されたチケット</strong>が配られます。</p>



<p class="is-style-alert-box has-box-style is-style-icon_info">ここでいっているユーザとは、パソコン利用者本人のことではなく<strong>ブラウザ</strong>のことです。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>イメージが湧きづらい方は、<span class="swl-marker mark_yellow"><strong>掲示板を実装後</strong></span>、試しにchromeの<strong>通常モード</strong>と<strong>シークレットモード</strong>（ctrl + shift + Nで起動）でそれぞれ掲示板へ投稿してみて下さい。<br>30分以内に操作をしても別々のIDで投稿が実行されるはずです。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>

<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h2 class="wp-block-heading">仕様②｜掲示板アプリのデータベース構造・ファイル構成</h2>



<p>以下より、<strong>データベース構造</strong>と<strong>ファイル構成</strong>について解説していきます。</p>



<h3 class="wp-block-heading">データベース構造</h3>



<p>今回、データベースは<strong>MySQL</strong>を使用しています。</p>



<p class="is-style-balloon_box2"><strong>データベース構造</strong></p>



<figure class="wp-block-table"><table><thead><tr><th>データベース名</th><th>作成テーブル</th></tr></thead><tbody><tr><td>board</td><td>board_info</td></tr></tbody></table><figcaption class="wp-element-caption">データベース構造</figcaption></figure>



<p class="is-style-balloon_box2"><strong>board_infoテーブル構造</strong></p>



<figure class="wp-block-table"><table><thead><tr><th>カラム名</th><th>備考</th></tr></thead><tbody><tr><td>id</td><td><strong>投稿ID＝主キー</strong><br>自動連番</td></tr><tr><td>title</td><td><strong>投稿タイトル</strong><br>字数制限：30文字</td></tr><tr><td>comment</td><td><strong>投稿内容</strong><br>字数制限：1000文字</td></tr><tr><td>contributor_id</td><td><strong>投稿者ID</strong><br>字数制限：20文字</td></tr><tr><td>created_at</td><td><strong>投稿日時</strong></td></tr><tr><td>updated_at</td><td><strong>更新日時</strong></td></tr></tbody></table><figcaption class="wp-element-caption">board_infoテーブルの構造</figcaption></figure>



<p class="is-style-balloon_box2"><strong>作成後のテーブル構造画面</strong>（phpMyAdminの画面）</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e3e8ad80fd3&quot;}" data-wp-interactive="core/image" data-wp-key="69e3e8ad80fd3" class="wp-block-image size-large has-custom-border is-style-default wp-lightbox-container"><img decoding="async" width="1024" height="182" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://kekenta-it-blog.com/wp-content/uploads/2024/02/004-1024x182.png" alt="掲示板アプリテーブル構造" class="wp-image-2828" style="border-width:1px" srcset="https://kekenta-it-blog.com/wp-content/uploads/2024/02/004-1024x182.png 1024w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/004-300x53.png 300w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/004-768x137.png 768w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/004.png 1415w" sizes="(max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="拡大する"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<div class="wp-block-group is-style-big_icon_memo"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<ul class="wp-block-list is-style-check_list">
<li><strong>id</strong>……<strong>AUTO_INCREMENT</strong>を設定することで、投稿データが追加される度に自動連番が割り振られる</li>



<li><strong>updated_at</strong>……<strong>ON UPDATE CURRENT_TIMESTAMP()</strong>を設定することで、投稿内容が編集されたとき自動で更新日時が反映される</li>



<li><strong>各字数制限</strong>……必要な字数に制限することで、予期しない操作などによる不具合を防ぐ目的で設定</li>
</ul>
</div></div>



<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h3 class="wp-block-heading">ファイル構成</h3>



<p>以下は<strong>ファイル構成のイメージ図</strong>です。</p>


<div class="wp-block-image size_s is-style-shadow">
<figure class="aligncenter size-full has-custom-border"><img decoding="async" width="678" height="439" src="https://kekenta-it-blog.com/wp-content/uploads/2024/02/file-organization-1.jpg" alt="ファイル構成のイメージ図" class="wp-image-2841" style="border-width:1px" srcset="https://kekenta-it-blog.com/wp-content/uploads/2024/02/file-organization-1.jpg 678w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/file-organization-1-300x194.jpg 300w" sizes="(max-width: 678px) 100vw, 678px" /><figcaption class="wp-element-caption">ファイル構成のイメージ図</figcaption></figure>
</div>


<p class="is-style-icon_pen">今回、解説のためにstyle.cssを設置してCSSも調整していますが、こちらは必須ではないため、見た目を気にされない方は無視していただいて問題ありません。</p>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h2 class="wp-block-heading">掲示板アプリのコード解説</h2>



<p>ここまで、当記事でご紹介する掲示板アプリの仕様をお伝えしてきました。</p>



<p>本章からは、実際のコードをお見せしながら、<strong>機能ごとの解説</strong>をしていきます。</p>



<p class="is-style-icon_pen"><strong>全体のコード</strong>を先に確認しておきたいという方は以下のアコーディオン内をご覧ください。<br>※データベース情報だけご自身の環境に合わせていただければ、以下のコードで掲示板アプリの動作をご確認いただけます。</p>



<div class="swell-block-tab is-style-balloon has-border -border01" data-width-pc="auto" data-width-sp="auto"><ul class="c-tabList" role="tablist"><li class="c-tabList__item" role="presentation"><button role="tab" class="c-tabList__button" aria-selected="true" aria-controls="tab-4b81e146-0" data-onclick="tabControl">掲示板アプリ全体のコード</button></li><li class="c-tabList__item" role="presentation"><button role="tab" class="c-tabList__button" aria-selected="false" aria-controls="tab-4b81e146-1" data-onclick="tabControl">style.css</button></li></ul><div class="c-tabBody">
<div id="tab-4b81e146-0" class="c-tabBody__item" aria-hidden="false">
<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">board.php（掲示板トップ）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * 投稿者ID（20桁）を生成
 */
if (isset($_SESSION[&#39;cont_id&#39;])) {
    $cont_id = $_SESSION[&#39;cont_id&#39;];
} else {
    $_SESSION[&#39;cont_id&#39;] = 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90));
    $cont_id = $_SESSION[&#39;cont_id&#39;];
}
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;
/**
 * 投稿ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;post_btn&#39;])) {
    // 更新操作用の処理
    unset($_SESSION[&#39;id&#39;]);
    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }
    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }
    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;
    /**
     * 必要項目がすべて入力されてたら投稿処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                INSERT INTO
                    board_info (title, comment, contributor_id)
                VALUES
                    (:TITLE, :COMMENT, :CONTRIBUTOR_ID)
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:CONTRIBUTOR_ID&#39;, $cont_id, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿に成功したらセッション変数を破棄
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 投稿一覧取得処理
 */
try {
    /**
     * DB接続処理
     */
    $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
        PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
        PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
    ]);
    $sql = (&#39;
        SELECT * 
        FROM board_info 
        ORDER BY id DESC
    &#39;);
    $stmt = $pdo-&gt;prepare($sql);
    // SQL実行
    $stmt-&gt;execute();
    // 投稿情報を辞書形式ですべて取得
    $post_list = $stmt-&gt;fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    echo &#39;接続失敗&#39; . $e-&gt;getMessage();
    exit();
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;掲示板アプリ&lt;/h1&gt;
    &lt;!-- 投稿フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル（※最大30文字）&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容（※最大1000文字）&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;])) echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;button class=&quot;btn--mg-c&quot; type=&quot;submit&quot; name=&quot;post_btn&quot; value=&quot;post_btn&quot;&gt;投稿&lt;/button&gt;
        &lt;/form&gt;
    &lt;/section&gt;
    &lt;hr&gt;
    &lt;!-- 投稿一覧 --&gt;
    &lt;section class=&quot;post-list&quot;&gt;
        &lt;?php if (count($post_list) === 0) : ?&gt;
            &lt;!-- 投稿が無いときはメッセージを表示する --&gt;
            &lt;p class=&quot;no-post-msg&quot;&gt;現在、投稿はありません。&lt;/p&gt;
        &lt;?php else : ?&gt;
            &lt;ul&gt;
                &lt;!-- 投稿情報の出力 --&gt;
                &lt;?php foreach ($post_list as $post_item) : ?&gt;
                    &lt;li&gt;
                        &lt;form action=&quot;&quot; method=&quot;post&quot;&gt;
                            &lt;!-- 投稿ID --&gt;
                            &lt;span&gt;ID：&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;　&lt;/span&gt;
                            &lt;!-- 投稿タイトル --&gt;
                            &lt;span&gt;&lt;?php echo $post_item[&#39;title&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿者ID --&gt;
                            &lt;span&gt;／投稿者：&lt;?php echo $post_item[&#39;contributor_id&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿内容 --&gt;
                            &lt;p class=&quot;p-pre&quot;&gt;&lt;?php echo $post_item[&#39;comment&#39;]; ?&gt;&lt;/p&gt;
                            &lt;!-- 投稿日時 --&gt;
                            &lt;span class=&quot;post-datetime&quot;&gt;投稿日時：&lt;?php echo $post_item[&#39;created_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 過去に更新されていたら更新日時も表示 --&gt;
                            &lt;?php if ($post_item[&#39;created_at&#39;] &lt; $post_item[&#39;updated_at&#39;]) : ?&gt;
                                &lt;span class=&quot;post-datetime post-datetime__updated&quot;&gt;更新日時：&lt;?php echo $post_item[&#39;updated_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;?php endif; ?&gt;
                        &lt;/form&gt;
                        &lt;!-- 自分の投稿内容かつセッションが有効な間は編集・削除が可能 --&gt;
                        &lt;?php if ($post_item[&#39;contributor_id&#39;] === $cont_id) : ?&gt;
                            &lt;div class=&quot;btn-flex&quot;&gt;
                                &lt;form action=&quot;update-edit.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;update_btn&quot;&gt;編集&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                                &lt;form action=&quot;delete-confirm.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;delete_btn&quot;&gt;削除&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                            &lt;/div&gt;
                        &lt;?php endif; ?&gt;
                        &lt;?php if (isset($_SESSION[&#39;id&#39;]) && ($_SESSION[&#39;id&#39;] == $post_item[&#39;id&#39;])): ?&gt;
                            &lt;p class=&#39;updated-post&#39;&gt;更新しました&lt;/p&gt;
                        &lt;?php endif; ?&gt;
                    &lt;/li&gt;
                &lt;?php endforeach; ?&gt;
            &lt;/ul&gt;
        &lt;?php endif; ?&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>



<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">update-edit.php（編集画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;
/**
 * 編集ボタンで遷移してきたときの処理
 */
if (isset($_POST[&#39;update_btn&#39;])) {
    /**
     * 編集対象の投稿情報を取得
     */
    if (isset($_POST[&#39;post_id&#39;]) && $_POST[&#39;post_id&#39;] != &#39;&#39;) {
        // セッションに投稿IDを保持
        $_SESSION[&#39;id&#39;] = $_POST[&#39;post_id&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容取得処理
             */
            $sql = (&#39;
                SELECT id, title, comment
                FROM board_info 
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿情報の取得
            $post_info = $stmt-&gt;fetch();
            $_SESSION[&#39;title&#39;] = $post_info[&#39;title&#39;];
            $_SESSION[&#39;comment&#39;] = $post_info[&#39;comment&#39;];
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 更新ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;update_submit_btn&#39;])) {
    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }
    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }
    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;
    /**
     * 必要項目がすべて入力されてたら更新処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容更新処理
             */
            $sql = (&#39;
                UPDATE board_info 
                SET title = :TITLE, comment = :COMMENT
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();
            // 更新に成功したらセッション変数を破棄
            // unset($_SESSION[&#39;id&#39;]);  // ※投稿IDは敢えて破棄せず、掲示板ページでID判定をするために情報を保持する★
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
            // 掲示板ページへ戻る
            header(&#39;Location: board.php&#39;);
            exit();
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * キャンセルボタンが押下されたら
 * セッション情報を破棄して
 * 掲示板一覧画面へ戻る
 */
if (isset($_POST[&#39;cancel_btn&#39;])) {
    unset($_SESSION[&#39;id&#39;]);
    unset($_SESSION[&#39;title&#39;]);
    unset($_SESSION[&#39;comment&#39;]);
    header(&#39;Location: board.php&#39;);
    exit();
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;投稿編集画面&lt;/h1&gt;
    &lt;!-- 投稿編集フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;]))  echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;; ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;btn-flex&quot;&gt;
                &lt;button type=&quot;submit&quot; name=&quot;update_submit_btn&quot; value=&quot;update_submit_btn&quot;&gt;更新&lt;/button&gt;
                &lt;button type=&quot;submit&quot; name=&quot;cancel_btn&quot; value=&quot;cancel_btn&quot;&gt;キャンセル&lt;/button&gt;
            &lt;/div&gt;
        &lt;/form&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>



<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">delete-confirm.php（削除確認画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;
/**
 * 削除ボタンで遷移してきたときの処理
 */
if (isset($_POST[&#39;delete_btn&#39;])) {
    /**
     * 編集対象の投稿情報を取得
     */
    if (isset($_POST[&#39;post_id&#39;]) && $_POST[&#39;post_id&#39;] != &#39;&#39;) {
        // セッションに投稿IDを保持
        $_SESSION[&#39;id&#39;] = $_POST[&#39;post_id&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                SELECT id, title, comment
                FROM board_info 
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿情報の取得
            $post_info = $stmt-&gt;fetch();
            $_SESSION[&#39;title&#39;] = $post_info[&#39;title&#39;];
            $_SESSION[&#39;comment&#39;] = $post_info[&#39;comment&#39;];
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 削除ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;delete_submit_btn&#39;])) {
    try {
        /**
         * DB接続処理
         */
        $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
            PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
        ]);
        /**
         * 投稿内容削除処理
         */
        $sql = (&#39;
            DELETE FROM board_info 
            WHERE id = :ID
        &#39;);
        $stmt = $pdo-&gt;prepare($sql);
        // プレースホルダーに値をセット
        $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
        // SQL実行
        $stmt-&gt;execute();
        // 削除に成功したらセッション変数を破棄
        unset($_SESSION[&#39;id&#39;]);
        unset($_SESSION[&#39;title&#39;]);
        unset($_SESSION[&#39;comment&#39;]);
        // 削除成功画面へ遷移
        header(&#39;Location: delete-success.php&#39;);
        exit();
    } catch (PDOException $e) {
        echo &#39;接続失敗&#39; . $e-&gt;getMessage();
        exit();
    }
    // DBとの接続を切る
    $pdo = null;
    $stmt = null;
}
/**
 * キャンセルボタンが押下されたら
 * セッション情報を破棄して
 * 掲示板一覧画面へ戻る
 */
if (isset($_POST[&#39;cancel_btn&#39;])) {
    unset($_SESSION[&#39;id&#39;]);
    unset($_SESSION[&#39;title&#39;]);
    unset($_SESSION[&#39;comment&#39;]);
    header(&#39;Location: board.php&#39;);
    return;
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;削除確認&lt;/h1&gt;
    &lt;p class=&quot;delete-confirm-msg&quot;&gt;以下の投稿を削除します。&lt;/p&gt;
    &lt;!-- 削除確認画面 --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;p&gt;タイトル&lt;/p&gt;
                    &lt;p&gt;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&lt;/p&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;p&gt;投稿内容&lt;/p&gt;
                    &lt;p class=&quot;p-pre&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;]))  echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/p&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;btn-flex&quot;&gt;
                &lt;button type=&quot;submit&quot; name=&quot;delete_submit_btn&quot; value=&quot;delete_submit_btn&quot;&gt;削除&lt;/button&gt;
                &lt;button type=&quot;submit&quot; name=&quot;cancel_btn&quot; value=&quot;cancel_btn&quot;&gt;キャンセル&lt;/button&gt;
            &lt;/div&gt;
        &lt;/form&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>



<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">delete-success.php（削除成功画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * 掲示場TOPへ自動で遷移する処理★
 */
header(&#39;refresh: 3; url=board.php&#39;);
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;削除が完了しました。&lt;/h1&gt;
    &lt;p class=&quot;delete-success-msg&quot;&gt;3秒後に自動で掲示板TOPへ戻ります。&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>
</div>
</div>



<div id="tab-4b81e146-1" class="c-tabBody__item" aria-hidden="true">
<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">style.css（同じ見た目にしたい方用）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-css" data-lang="CSS"><code>body {
    margin: 0 auto;
    width: 700px;
    background-color: rgb(224, 224, 224);
}
hr {
    margin: 40px 0;
    border-color: rgb(137, 137, 137);
}
h1 {
    text-align: center;
}
li {
    list-style: none;
}
p {
    margin: 0;
}
p,
span {
    color: #333;
}
input,
textarea {
    padding: 10px;
    border: 1px solid gray;
    border-radius: 10px;
    width: 100%;
    box-sizing: border-box;
}
textarea {
    line-height: 1.5;
}
button {
    display: block;
    margin-top: 20px;
    padding: 10px 30px;
    color: #fff;
    border-radius: 10px;
    cursor: pointer;
}
button[name=&quot;post_btn&quot;] {
    border: 1px solid rgb(148, 148, 218);
    background-color: rgb(94, 94, 255);
}
button[name=&quot;update_btn&quot;],
button[name=&quot;update_submit_btn&quot;] {
    border: 1px solid rgb(62, 150, 62);
    background-color: rgb(74, 152, 74);
}
button[name=&quot;delete_btn&quot;],
button[name=&quot;delete_submit_btn&quot;] {
    border: 1px solid rgb(255, 31, 31);
    background-color: rgb(255, 48, 48);
}
button[name=&quot;cancel_btn&quot;] {
    border: 1px solid rgb(172, 172, 172);
    background-color: rgb(182, 182, 182);
}
button[name=&quot;post_btn&quot;]:hover {
    background-color: rgb(116, 116, 255);
}
button[name=&quot;update_btn&quot;]:hover,
button[name=&quot;update_submit_btn&quot;]:hover {
    background-color: rgb(83, 169, 83);
}
button[name=&quot;delete_btn&quot;]:hover,
button[name=&quot;delete_submit_btn&quot;]:hover {
    background-color: rgb(255, 82, 82);
}
button[name=&quot;cancel_btn&quot;]:hover {
    background-color: rgb(189, 189, 189);
}
.btn--mg-c {
    margin: 0 auto;
}
.post-list button {
    margin: 30px 0 0 0;
    padding: 8px 20px;
}
.post-list li {
    margin-bottom: 15px;
    padding: 20px 30px;
    background-color: #fff;
    border: 1px solid rgb(188, 188, 188);
    border-radius: 10px;
}
.post-list span {
    display: inline-block;
    margin-bottom: 25px;
}
.post-form__flex {
    display: flex;
    justify-content: center;
    column-gap: 15px;
    margin-bottom: 20px;
}
.post-form__flex&gt;div:first-child {
    width: 250px;
}
.post-form__flex&gt;div:last-child {
    flex: 1;
}
.btn-flex {
    display: flex;
    justify-content: center;
    column-gap: 15px;
}
.post-list li:last-child {
    margin-bottom: 0;
}
.post-datetime {
    display: inline-block;
    margin-top: 25px;
    font-size: 12px;
    color: gray;
}
.post-datetime__updated {
    display: inline-block;
    margin-left: 10px;
}
.updated-post {
    margin-left: auto;
    padding: 2px 5px;
    width: fit-content;
    font-size: 12px;
    border: 1px solid rgb(105, 105, 105);
    border-radius: 5px;
    color: rgb(105, 105, 105);
}
.no-post-msg {
    text-align: center;
}
.delete-confirm-msg {
    text-align: center;
    margin-bottom: 30px;
    color: red;
    font-weight: bold;
}
.delete-success-msg {
    text-align: center;
}
.err {
    color: red;
    font-size: 13px;
}
/* 
改行もそのまま表示するための指定
これが無いと改行が半角スペースに変換されて
表示されてしまう
 */
.p-pre {
    white-space: pre-wrap;
}</code></pre></div>
</div></details>
</div>
</div>



<div id="tab-4b81e146-2" class="c-tabBody__item" aria-hidden="true">
<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">board.php</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php

/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();

/**
 * 投稿者ID（20桁）を生成
 */
if (isset($_SESSION[&#39;cont_id&#39;])) {
    $cont_id = $_SESSION[&#39;cont_id&#39;];
} else {
    $_SESSION[&#39;cont_id&#39;] = 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90));
    $cont_id = $_SESSION[&#39;cont_id&#39;];
}

/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;

/**
 * 投稿ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;post_btn&#39;])) {

    // 更新操作用の処理
    unset($_SESSION[&#39;id&#39;]);

    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }

    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }

    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;

    /**
     * 必要項目がすべて入力されてたら投稿処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];

        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);

            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                INSERT INTO
                    board_info (title, comment, contributor_id)
                VALUES
                    (:TITLE, :COMMENT, :CONTRIBUTOR_ID)
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:CONTRIBUTOR_ID&#39;, $cont_id, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();

            // 投稿に成功したらセッション変数を破棄
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}

/**
 * 投稿一覧取得処理
 */
try {
    /**
     * DB接続処理
     */
    $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
        PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
        PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
    ]);

    $sql = (&#39;
        SELECT * 
        FROM board_info 
        ORDER BY id DESC
    &#39;);
    $stmt = $pdo-&gt;prepare($sql);

    // SQL実行
    $stmt-&gt;execute();

    // 投稿情報を辞書形式ですべて取得
    $post_list = $stmt-&gt;fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    echo &#39;接続失敗&#39; . $e-&gt;getMessage();
    exit();
}

?&gt;

&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;

&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;h1&gt;掲示板アプリ&lt;/h1&gt;

    &lt;!-- 投稿フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル（※最大30文字）&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容（※最大1000文字）&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;])) echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;button class=&quot;btn--mg-c&quot; type=&quot;submit&quot; name=&quot;post_btn&quot; value=&quot;post_btn&quot;&gt;投稿&lt;/button&gt;
        &lt;/form&gt;
    &lt;/section&gt;

    &lt;hr&gt;

    &lt;!-- 投稿一覧 --&gt;
    &lt;section class=&quot;post-list&quot;&gt;
        &lt;?php if (count($post_list) === 0) : ?&gt;
            &lt;!-- 投稿が無いときはメッセージを表示する --&gt;
            &lt;p class=&quot;no-post-msg&quot;&gt;現在、投稿はありません。&lt;/p&gt;
        &lt;?php else : ?&gt;
            &lt;ul&gt;
                &lt;!-- 投稿情報の出力 --&gt;
                &lt;?php foreach ($post_list as $post_item) : ?&gt;
                    &lt;li&gt;
                        &lt;form action=&quot;&quot; method=&quot;post&quot;&gt;
                            &lt;!-- 投稿ID --&gt;
                            &lt;span&gt;ID：&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;　&lt;/span&gt;
                            &lt;!-- 投稿タイトル --&gt;
                            &lt;span&gt;&lt;?php echo $post_item[&#39;title&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿者ID --&gt;
                            &lt;span&gt;／投稿者：&lt;?php echo $post_item[&#39;contributor_id&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿内容 --&gt;
                            &lt;p class=&quot;p-pre&quot;&gt;&lt;?php echo $post_item[&#39;comment&#39;]; ?&gt;&lt;/p&gt;
                            &lt;!-- 投稿日時 --&gt;
                            &lt;span class=&quot;post-datetime&quot;&gt;投稿日時：&lt;?php echo $post_item[&#39;created_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 過去に更新されていたら更新日時も表示 --&gt;
                            &lt;?php if ($post_item[&#39;created_at&#39;] &lt; $post_item[&#39;updated_at&#39;]) : ?&gt;
                                &lt;span class=&quot;post-datetime post-datetime__updated&quot;&gt;更新日時：&lt;?php echo $post_item[&#39;updated_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;?php endif; ?&gt;
                        &lt;/form&gt;
                        &lt;!-- 自分の投稿内容かつセッションが有効な間は編集・削除が可能 --&gt;
                        &lt;?php if ($post_item[&#39;contributor_id&#39;] === $cont_id) : ?&gt;
                            &lt;div class=&quot;btn-flex&quot;&gt;
                                &lt;form action=&quot;update-edit.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;update_btn&quot;&gt;編集&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                                &lt;form action=&quot;delete-confirm.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;delete_btn&quot;&gt;削除&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                            &lt;/div&gt;
                        &lt;?php endif; ?&gt;
                        &lt;?php if (isset($_SESSION[&#39;id&#39;]) && ($_SESSION[&#39;id&#39;] == $post_item[&#39;id&#39;])): ?&gt;
                            &lt;p class=&#39;updated-post&#39;&gt;更新しました&lt;/p&gt;
                        &lt;?php endif; ?&gt;
                    &lt;/li&gt;
                &lt;?php endforeach; ?&gt;
            &lt;/ul&gt;
        &lt;?php endif; ?&gt;
    &lt;/section&gt;
&lt;/body&gt;

&lt;/html&gt;</code></pre></div>
</div></details>
</div>
</div>
</div></div>



<div class="wp-block-group is-style-big_icon_caution"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<p class="is-style-alert-box has-box-style">何度かお伝えしていますが、本記事で紹介しているコードは<strong><span class="swl-inline-color has-swl-deep-01-color"><span class="swl-marker mark_orange">セキュリティリスクを考慮していません。</span></span></strong>本番環境で利用するには、ご紹介するコードに<strong><span class="marker-under-red"><span class="swl-marker mark_orange">セキュリティ対策を施すことが絶対不可欠</span></span></strong>です。</p>



<p class="is-style-alert-box has-box-style u-mb-ctrl u-mb-20"><strong>セキュリティ対策を施したコード</strong>をご覧になりたい場合は以下の記事をご覧ください。</p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">あわせて読みたい</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/eye-catch__php-board-app-secure__3549-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/php-board-app-secure/">【PHP】掲示板アプリの作り方｜正しいセキュリティ対策</a>
						<span class="p-blogCard__excerpt">以前にこちらの記事で掲示板アプリの作成方法を解説しました。 記事内でもお伝えしているように、上の記事で解説している掲示板アプリではセキュリティ対策はしておらず&#8230;</span>					</div>
				</div>
			</div>
		</div></div></div>



<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h3 class="wp-block-heading">機能１　投稿</h3>



<p>改めて、投稿機能のイメージ図です。</p>


<div class="wp-block-image is-style-shadow size_s">
<figure data-wp-context="{&quot;imageId&quot;:&quot;69e3e8ad832e8&quot;}" data-wp-interactive="core/image" data-wp-key="69e3e8ad832e8" class="aligncenter size-large wp-lightbox-container"><img decoding="async" width="1024" height="1008" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://kekenta-it-blog.com/wp-content/uploads/2024/02/8d5c3c671b07078cad80b5eabfc440e3-1024x1008.jpg" alt="掲示板アプリ投稿機能の流れ" class="wp-image-3100" srcset="https://kekenta-it-blog.com/wp-content/uploads/2024/02/8d5c3c671b07078cad80b5eabfc440e3-1024x1008.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/8d5c3c671b07078cad80b5eabfc440e3-300x295.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/8d5c3c671b07078cad80b5eabfc440e3-768x756.jpg 768w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/8d5c3c671b07078cad80b5eabfc440e3-1536x1512.jpg 1536w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/8d5c3c671b07078cad80b5eabfc440e3-2048x2016.jpg 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="拡大する"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>
</div>


<p>上記の処理を実装しているのが<strong><code class="file_name">board.php</code></strong>です。</p>



<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label"><strong>board.php</strong>（<strong>掲示板トップ</strong>）～投稿機能部分～</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-file="board.php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * 投稿者ID（20桁）を生成
 */
if (isset($_SESSION[&#39;cont_id&#39;])) {
    $cont_id = $_SESSION[&#39;cont_id&#39;];
} else {
    $_SESSION[&#39;cont_id&#39;] = 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90));
    $cont_id = $_SESSION[&#39;cont_id&#39;];
}
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;
/**
 * 投稿ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;post_btn&#39;])) {
    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }
    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }
    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;
    /**
     * 必要項目がすべて入力されてたら投稿処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローするみ表示する設定にする
            ]);
            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                INSERT INTO
                    board_info (title, comment, contributor_id)
                VALUES
                    (:TITLE, :COMMENT, :CONTRIBUTOR_ID)
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:CONTRIBUTOR_ID&#39;, $cont_id, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿に成功したらセッション変数を破棄
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 投稿一覧取得処理
 */
try {
    /**
     * DB接続処理
     */
    $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
        PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
        PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
    ]);
    $sql = (&#39;
        SELECT * 
        FROM board_info 
        ORDER BY id DESC
    &#39;);
    $stmt = $pdo-&gt;prepare($sql);
    // SQL実行
    $stmt-&gt;execute();
    // 投稿情報を辞書形式ですべて取得
    $post_list = $stmt-&gt;fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    echo &#39;接続失敗&#39; . $e-&gt;getMessage();
    exit();
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;掲示板アプリ&lt;/h1&gt;
    &lt;!-- 投稿フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル（※最大30文字）&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容（※最大1000文字）&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;])) echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;; ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;button class=&quot;btn--mg-c&quot; type=&quot;submit&quot; name=&quot;post_btn&quot; value=&quot;post_btn&quot;&gt;投稿&lt;/button&gt;
        &lt;/form&gt;
    &lt;/section&gt;
    &lt;hr&gt;
    &lt;!-- 投稿一覧 --&gt;
    &lt;section class=&quot;post-list&quot;&gt;
        &lt;?php if (count($post_list) === 0) : ?&gt;
            &lt;!-- 投稿が無いときはメッセージを表示する --&gt;
            &lt;p class=&quot;no-post-msg&quot;&gt;現在、投稿はありません。&lt;/p&gt;
        &lt;?php else : ?&gt;
            &lt;ul&gt;
                &lt;!-- 投稿情報の出力 --&gt;
                &lt;?php foreach ($post_list as $post_item) : ?&gt;
                    &lt;li&gt;
                        &lt;form action=&quot;&quot; method=&quot;post&quot;&gt;
                            &lt;!-- 投稿ID --&gt;
                            &lt;span&gt;ID：&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;　&lt;/span&gt;
                            &lt;!-- 投稿タイトル --&gt;
                            &lt;span&gt;&lt;?php echo $post_item[&#39;title&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿者ID --&gt;
                            &lt;span&gt;／投稿者：&lt;?php echo $post_item[&#39;contributor_id&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿内容 --&gt;
                            &lt;p class=&quot;p-pre&quot;&gt;&lt;?php echo $post_item[&#39;comment&#39;]; ?&gt;&lt;/p&gt;
                            &lt;!-- 投稿日時 --&gt;
                            &lt;span class=&quot;post-datetime&quot;&gt;投稿日時：&lt;?php echo $post_item[&#39;created_at&#39;]; ?&gt;&lt;/span&gt;
                        &lt;/form&gt;
                    &lt;/li&gt;
                &lt;?php endforeach; ?&gt;
            &lt;/ul&gt;
        &lt;?php endif; ?&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>
</div>



<p><code class="file_name">board.php</code>内で行なっている処理を整理すると以下のようになります。</p>



<div class="swell-block-capbox cap_box is-style-shadow"><div class="cap_box_ttl"><span><span data-icon="FasCircleCheck" data-id="0" style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGQ9Ik0yNTYgNTEyYzE0MS40IDAgMjU2LTExNC42IDI1Ni0yNTZTMzk3LjQgMCAyNTYgMFMwIDExNC42IDAgMjU2UzExNC42IDUxMiAyNTYgNTEyek0zNjkgMjA5TDI0MSAzMzdjLTkuNCA5LjQtMjQuNiA5LjQtMzMuOSAwbC02NC02NGMtOS40LTkuNC05LjQtMjQuNiAwLTMzLjlzMjQuNi05LjQgMzMuOSAwbDQ3IDQ3TDMzNSAxNzVjOS40LTkuNCAyNC42LTkuNCAzMy45IDBzOS40IDI0LjYgMCAzMy45eiI+PC9wYXRoPjwvc3ZnPg==)" aria-hidden="true" class="swl-inline-icon"> </span><strong> board.phpの処理</strong></span></div><div class="cap_box_content">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>セッションの設定・開始</li>



<li>投稿者IDの生成・セッション変数への格納</li>



<li>投稿処理</li>



<li>エラーメッセージの格納（未入力項目があった場合のみ）</li>



<li>投稿一覧取得処理</li>
</ul>
</div></div>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>上から順番に解説をしていきます。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h4 class="wp-block-heading">セッションの設定・開始</h4>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();</code></pre></div>



<p>この部分で<strong>セッションの有効期限を1800秒＝30分</strong>にし、<strong>session.gc_divisor</strong>に１を設定することでセッションが確実に破棄されるようにしています。</p>



<p class="is-style-icon_info">デフォルトだとセッションは<strong>100分の1の確率で破棄される設定</strong>になっています。</p>



<p>本掲示板アプリで実装している「最短30分間のみ有効な投稿者ID」の<strong>30分間</strong>の部分は、上記の<code>session.gc_maxlifetime</code>で実現しています。もし30分以外の時間にしたいときは、ここの秒数を変更すればOKです。</p>



<p>ちなみに上記の秒数と確率は<code class="file_name">php.ini</code>を直接編集して設定することも可能です。</p>



<p class="is-style-icon_pen"><code>session_start()</code>はセッションを使用する際は<strong>必ず必要</strong>になる記述です。</p>



<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h4 class="wp-block-heading">投稿者IDの生成・セッション変数への格納</h4>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>/**
 * 投稿者ID（20桁）を生成
 */
if (isset($_SESSION[&#39;cont_id&#39;])) {
    $cont_id = $_SESSION[&#39;cont_id&#39;];
} else {
    $_SESSION[&#39;cont_id&#39;] = 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90));
    $cont_id = $_SESSION[&#39;cont_id&#39;];
}
</code></pre></div>



<p>この処理では<strong>ランダムな20桁の文字列</strong>を生成し、それを投稿者IDとして割り振っています。</p>



<p>また、投稿者IDを割り振るかどうかについては</p>



<p class="is-style-bg_stripe">過去に投稿者IDが割り振られている＝セッション変数（$_SESSION[&#8216;cont_id&#8217;]）に投稿者IDが格納されているかどうか</p>



<p>という条件を元に判定しています。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>このあと解説する<strong>編集・削除機能</strong>では、この投稿者IDを元に機能の有効・無効化を行っています。<br><br>ログイン機能を持たない本掲示板アプリにおいては、この処理が<strong>ユーザの操作権限制御</strong>を担っているというわけです。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h4 class="wp-block-heading">投稿処理</h4>



<p>続いてメインとなる<strong>投稿処理</strong>です。</p>



<p class="is-style-balloon_box2"><strong>データベース接続に必要な情報の定義</strong></p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;</code></pre></div>



<p class="is-style-balloon_box2"><strong>投稿処理</strong></p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>/**
 * 投稿ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;post_btn&#39;])) {


    ～　エラーメッセージ関係の処理は中略　～


    /**
     * 必要項目がすべて入力されてたら投稿処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];

        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);

            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                INSERT INTO
                    board_info (title, comment, contributor_id)
                VALUES
                    (:TITLE, :COMMENT, :CONTRIBUTOR_ID)
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:CONTRIBUTOR_ID&#39;, $cont_id, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();


            ～　エラーメッセージ関係の処理は中略　～


        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}</code></pre></div>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>ここでの処理の流れは以下の通りです。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<div class="swell-block-capbox cap_box is-style-shadow"><div class="cap_box_ttl"><span><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGQ9Ik0yNTYgNTEyYzE0MS40IDAgMjU2LTExNC42IDI1Ni0yNTZTMzk3LjQgMCAyNTYgMFMwIDExNC42IDAgMjU2UzExNC42IDUxMiAyNTYgNTEyek0zNjkgMjA5TDI0MSAzMzdjLTkuNCA5LjQtMjQuNiA5LjQtMzMuOSAwbC02NC02NGMtOS40LTkuNC05LjQtMjQuNiAwLTMzLjlzMjQuNi05LjQgMzMuOSAwbDQ3IDQ3TDMzNSAxNzVjOS40LTkuNCAyNC42LTkuNCAzMy45IDBzOS40IDI0LjYgMCAzMy45eiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasCircleCheck" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span><strong> 投稿処理の流れ</strong></span></div><div class="cap_box_content">
<ul start="1" class="wp-block-list -list-under-dashed is-style-num_circle">
<li><strong>投稿ボタン（name=post_btnのボタン）</strong>が押されたら……</li>



<li>「タイトル」と「投稿内容」が入力されているか判定</li>



<li>「タイトル」と「投稿内容」が両方とも入力されていたらデータベース接続を実行</li>



<li>データ登録するためのSQL文を発行（INSERT文を使用）</li>



<li>プレースホルダーへ値をセット</li>



<li>SQL文を実行（データの登録）</li>



<li>DBとの接続を切る</li>
</ul>
</div></div>



<p class="is-style-big_icon_check">この中で最も重要なのが、<strong>PDOを利用して投稿内容をデータベースへ登録</strong>している以下の処理です。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>/**
 * DB接続処理
 */
$pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
    PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
]);

/**
 * 投稿内容登録処理
 */
$sql = (&#39;
    INSERT INTO
        board_info (title, comment, contributor_id)
    VALUES
        (:TITLE, :COMMENT, :CONTRIBUTOR_ID)
&#39;);
$stmt = $pdo-&gt;prepare($sql);
// プレースホルダーに値をセット
$stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
$stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
$stmt-&gt;bindValue(&#39;:CONTRIBUTOR_ID&#39;, $cont_id, PDO::PARAM_STR);
// SQL実行
$stmt-&gt;execute();</code></pre></div>



<p>PDOを利用する場合、文法的な構造は基本的にこのような形・流れになります。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>上記で<strong>コメントが記述されている部分</strong>が処理１つ１つの区切りと思って頂くとイメージしやすいかと思います。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p class="u-mb-ctrl u-mb-30">また、<strong>プレースホルダー</strong>というキーワードが登場していますが、こちらは簡単に言ってしまうと「後から任意の値をセットするための仮のスペース」です。<br><br>詳しくは以下の<strong>SQLインジェクション</strong>の記事で解説しています。ご興味のある方はこちらをご覧ください。</p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">あわせて読みたい</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2024/04/eye-catch__sql-inj-php__1106-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/sql-inj-php/">【PHP】SQLインジェクションの原因や攻撃手法【対策コード付き】</a>
						<span class="p-blogCard__excerpt">この記事ではセキュリティ攻撃の１つであるSQLインジェクションについて、その対策方法も含めて解説をしていきます。  この記事で分かること SQLインジェクション攻撃の&#8230;</span>					</div>
				</div>
			</div>
		</div>


<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h4 class="wp-block-heading">エラーメッセージの格納（未入力項目があった場合のみ）</h4>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>/**
 * 投稿ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;post_btn&#39;])) {

    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }

    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }

    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;


    ～　投稿処理は中略　～


}</code></pre></div>



<p>ここで行っている処理は以下の２つです。</p>



<div class="wp-block-group has-border -border01"><div class="wp-block-group__inner-container">
<ul class="wp-block-list -list-under-dashed is-style-num_circle">
<li>タイトルもしくは投稿内容のいずれかのみが入力されていた場合は、その入力内容をセッション変数（$_SESSION[&#8216;title&#8217;]、$_SESSION[&#8216;comment&#8217;]）に保持する</li>



<li>タイトルもしくは投稿内容のいずれか、または両方が未入力ならエラーメッセージを変数へ格納する</li>
</ul>
</div></div>



<p>特に、①は必須ではないものの、この処理がないと</p>



<p>「タイトルまたは本文の一方だけを入力して投稿ボタンを押した場合、入力されていた内容が消え、同じ内容を再入力する手間が増える」</p>



<p>という状態になってしまい<strong>ユーザビリティが低下</strong>してしまいます。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>イメージが湧きづらい方は、実際にこちらの処理をコメントアウトしていただくと、「こういうことか」とすぐにご理解いただけるかと思います。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>また、②の<strong>エラーメッセージ</strong>については、ここで変数に格納された場合、以下の「投稿フォーム」に関するHTML部分で出力する実装になっています。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP" data-line="9-12,19-22"><code>    &lt;!-- 投稿フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル（※最大30文字）&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容（※最大1000文字）&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;])) echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;button class=&quot;btn--mg-c&quot; type=&quot;submit&quot; name=&quot;post_btn&quot; value=&quot;post_btn&quot;&gt;投稿&lt;/button&gt;
        &lt;/form&gt;
    &lt;/section&gt;</code></pre></div>



<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h4 class="wp-block-heading">投稿一覧取得処理</h4>



<p>投稿一覧取得処理については、<strong>①投稿データの取得</strong>と<strong>②取得した投稿データの表示</strong>に切り分けてご説明します。</p>



<p class="is-style-balloon_box2">①投稿データの取得</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP" data-line="[8,9,22,23,24]"><code>/**
 * 投稿一覧取得処理
 */
try {
    /**
     * DB接続処理
     */
    $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
        PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
        PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする     
    ]);

    $sql = (&#39;
        SELECT * 
        FROM board_info 
        ORDER BY id DESC
    &#39;);
    $stmt = $pdo-&gt;prepare($sql);
    // SQL実行
    $stmt-&gt;execute();

    // 投稿情報を辞書形式ですべて取得
    $post_list = $stmt-&gt;fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    echo &#39;接続失敗&#39; . $e-&gt;getMessage();
    exit();
}

?&gt;</code></pre></div>



<p><strong>①投稿データの取得</strong>での流れは、SQL文でSELECTを使用している点を除けば基本的に<strong>投稿処理</strong>と同じです。</p>



<p>注目していただきたいのが、<strong>ハイライトされている2か所</strong>の記述です。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する</code></pre></div>



<p>上記の一文では、取得するデータ形式を「DBテーブルのカラム名をキーとした<strong>連想配列</strong>」に指定しています。これは次節で解説する表示部分に直接関係してくる設定記述です。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>// 投稿情報を辞書形式ですべて取得
$post_list = $stmt-&gt;fetchAll(PDO::FETCH_ASSOC);</code></pre></div>



<p>また、後者のハイライト箇所によって、データベース上に登録されている<strong>投稿情報すべてを辞書形式で$post_listに格納</strong>しています。</p>



<p>上記２つの処理により、投稿情報を出力する際、データベースに設定してあるキー名を指定することで簡単に目的の情報を指定できます。</p>



<p>例えば、<strong>タイトル情報</strong>を出力したい場合は<strong><code>$post_list['title']</code></strong>と記述すればOKということです。（以下、テーブル構造の再掲）</p>



<figure class="wp-block-image size-large has-custom-border is-style-shadow"><img decoding="async" width="1179" height="210" src="https://kekenta-it-blog.com/wp-content/uploads/2024/02/004-edited.png" alt="掲示板アプリテーブル構造" class="wp-image-2940" style="border-width:1px" srcset="https://kekenta-it-blog.com/wp-content/uploads/2024/02/004-edited.png 1179w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/004-edited-300x53.png 300w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/004-edited-1024x182.png 1024w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/004-edited-768x137.png 768w" sizes="(max-width: 1179px) 100vw, 1179px" /><figcaption class="wp-element-caption">掲示板アプリテーブル構造</figcaption></figure>



<p class="is-style-balloon_box2">②取得した投稿データの表示</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP" data-line="[26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44]"><code>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;

&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;h1&gt;掲示板アプリ&lt;/h1&gt;

    &lt;!-- 投稿フォーム --&gt;


　　～　中略　～


    &lt;!-- 投稿一覧 --&gt;
    &lt;section class=&quot;post-list&quot;&gt;
        &lt;?php if (count($post_list) === 0) : ?&gt;
            &lt;!-- 投稿が無いときはメッセージを表示する --&gt;
            &lt;p class=&quot;no-post-msg&quot;&gt;現在、投稿はありません。&lt;/p&gt;
        &lt;?php else : ?&gt;
            &lt;ul&gt;
                &lt;!-- 投稿情報の出力 --&gt;
                &lt;?php foreach ($post_list as $post_item) : ?&gt;
                    &lt;li&gt;
                        &lt;form action=&quot;&quot; method=&quot;post&quot;&gt;
                            &lt;!-- 投稿ID --&gt;
                            &lt;span&gt;ID：&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;　&lt;/span&gt;
                            &lt;!-- 投稿タイトル --&gt;
                            &lt;span&gt;&lt;?php echo $post_item[&#39;title&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿者ID --&gt;
                            &lt;span&gt;／投稿者：&lt;?php echo $post_item[&#39;contributor_id&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿内容 --&gt;
                            &lt;p class=&quot;p-pre&quot;&gt;&lt;?php echo $post_item[&#39;comment&#39;]; ?&gt;&lt;/p&gt;
                            &lt;!-- 投稿日時 --&gt;
                            &lt;span class=&quot;post-datetime&quot;&gt;投稿日時：&lt;?php echo $post_item[&#39;created_at&#39;]; ?&gt;&lt;/span&gt;
                        &lt;/form&gt;
                    &lt;/li&gt;
                &lt;?php endforeach; ?&gt;
            &lt;/ul&gt;
        &lt;?php endif; ?&gt;
    &lt;/section&gt;
&lt;/body&gt;

&lt;/html&gt;</code></pre></div>



<p>上記のハイライトされている箇所が<strong>投稿一覧を出力するための処理</strong>です。</p>



<p>ご覧いただいている通り、先ほど取得した<strong>投稿データ（$post_list）</strong>をforeachで回し、HTMLタグ内にテキストとして埋め込んでいます。</p>



<p class="is-style-big_icon_point">先ほどの<strong>①投稿データの取得処理</strong>の中で、<br><strong>PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC</strong><br>という記述をご紹介しました。<br>これにより、$post_listに格納されているデータは連想配列になっているのでした。<br><br>そのため、HTML内ではテーブルのカラム名をキーにすることで目的の値を出力しています。</p>



<p>なお、プログラム内のコメントをご覧いただくとお分かりになるかと思いますが、<strong>投稿が無い＝取得データ（$post_list）が0個のとき</strong>は「現在、投稿はありません」と表示する実装になっています。</p>


<div class="wp-block-image is-style-shadow">
<figure class="aligncenter size-full is-resized has-custom-border"><img decoding="async" width="752" height="553" src="https://kekenta-it-blog.com/wp-content/uploads/2024/02/image-10.png" alt="掲示板アプリ投稿が無いときの表示" class="wp-image-2947" style="border-width:1px;width:583px;height:auto" srcset="https://kekenta-it-blog.com/wp-content/uploads/2024/02/image-10.png 752w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/image-10-300x221.png 300w" sizes="(max-width: 752px) 100vw, 752px" /><figcaption class="wp-element-caption">「現在、投稿はありません」表示</figcaption></figure>
</div>

<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>ここまでが<strong>投稿機能</strong>の解説でした！<br>続いて<strong>編集機能</strong>についてご説明していきます。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>

<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h3 class="wp-block-heading">機能２　編集</h3>



<p>繰り返しになりますが、本掲示板アプリでは<strong><span class="marker-under"><span class="swl-marker mark_yellow">現在の投稿者IDと同じIDを持つ投稿のみ「編集可能」</span></span></strong>です。</p>



<p><strong>投稿機能</strong>の章では割愛しましたが、実はコード説明の冒頭で提示した全体コードの<strong>board.php</strong>内のフォームには、以下のハイライト部分の記述がありました。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP" data-line="12-24"><code>    &lt;!-- 投稿一覧 --&gt;
    &lt;section class=&quot;post-list&quot;&gt;

　　　　　　～　中略　～

            &lt;ul&gt;
                &lt;!-- 投稿情報の出力 --&gt;
                &lt;?php foreach ($post_list as $post_item) : ?&gt;

　　　　　　　　　　　　　～　投稿一覧表示処理　中略　～

                        &lt;!-- 自分の投稿内容かつセッションが有効な間は編集・削除が可能 --&gt;
                        &lt;?php if ($post_item[&#39;contributor_id&#39;] === $cont_id) : ?&gt;
                            &lt;div class=&quot;btn-flex&quot;&gt;
                                &lt;form action=&quot;update-edit.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;update_btn&quot;&gt;編集&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                                &lt;form action=&quot;delete-confirm.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;delete_btn&quot;&gt;削除&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                            &lt;/div&gt;
                        &lt;?php endif; ?&gt;
                        &lt;?php if (isset($_SESSION[&#39;id&#39;]) && ($_SESSION[&#39;id&#39;] == $post_item[&#39;id&#39;])): ?&gt;
                            &lt;p class=&#39;updated-post&#39;&gt;更新しました&lt;/p&gt;
                        &lt;?php endif; ?&gt;
                    &lt;/li&gt;
                &lt;?php endforeach; ?&gt;
            &lt;/ul&gt;
        &lt;?php endif; ?&gt;
    &lt;/section&gt;</code></pre></div>



<p>編集（または削除）機能が使用できるかどうかは、実はこの部分で制御をしています。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p><strong>$post_item[&#8216;contributor_id&#8217;] === $cont_id</strong>の部分で「投稿の投稿者ID」と「現在の投稿者ID」が同じかどうかを判定しています。もし異なれば、<strong>編集・削除ボタンは非表示</strong>、つまり<strong>編集・削除機能は使用不可</strong>ということです。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>本章では編集機能をご紹介しますが、本機能を使用できる背景にはこうした処理があることをまずはご説明させていただきました。</p>



<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<p>それでは、以下より<strong><span class="swl-marker mark_yellow">編集機能の解説</span></strong>を進めていきます。</p>



<p class="is-style-bg_stripe">本掲示板アプリにおける投稿編集は<strong>投稿編集画面</strong>で行います。</p>



<p>「投稿編集画面」ページへアクセスするには、投稿に表示される「編集ボタン」を押下する必要があります。</p>



<p>そして、「編集ボタン」が押下されると直接「投稿編集画面」へ遷移し、その先は<code class="file_name">update-edit.php</code>の処理が実行されるという流れになります。</p>



<p class="has-text-align-center is-style-balloon_box">編集機能の流れ</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e3e8ad86e7a&quot;}" data-wp-interactive="core/image" data-wp-key="69e3e8ad86e7a" class="wp-block-image size-large is-style-shadow size_s wp-lightbox-container"><img decoding="async" width="1024" height="809" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://kekenta-it-blog.com/wp-content/uploads/2024/02/8ba6d47fc77f50f3162e15c0a8d4dc19-1024x809.jpg" alt="掲示板アプリ投稿編集機能の流れ" class="wp-image-3052" srcset="https://kekenta-it-blog.com/wp-content/uploads/2024/02/8ba6d47fc77f50f3162e15c0a8d4dc19-1024x809.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/8ba6d47fc77f50f3162e15c0a8d4dc19-300x237.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/8ba6d47fc77f50f3162e15c0a8d4dc19-768x607.jpg 768w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/8ba6d47fc77f50f3162e15c0a8d4dc19-1536x1213.jpg 1536w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/8ba6d47fc77f50f3162e15c0a8d4dc19-2048x1617.jpg 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="拡大する"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<p class="is-style-big_icon_point">今回はボタンを押下した時点で<code class="file_name">update-edit.php</code>（投稿編集画面）へ直接アクセスする実装になっています。しかし、その他の方法として、<code class="file_name">board.php</code><strong>内で投稿者IDの照合を行い、本当に一致していたときだけ</strong><code class="file_name">update-edit.php</code><strong>へ遷移する</strong>といったことも可能です。（セキュリティ面などを考えるとこの方法の方が望ましいですが、今回は簡略化のために省略しています。）</p>



<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label"><strong>update-edit.php</strong>（編集画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-file="update-edit.php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;
/**
 * 編集ボタンで遷移してきたときの処理
 */
if (isset($_POST[&#39;update_btn&#39;])) {
    /**
     * 編集対象の投稿情報を取得
     */
    if (isset($_POST[&#39;post_id&#39;]) && $_POST[&#39;post_id&#39;] != &#39;&#39;) {
        // ★セッションに投稿IDを保持
        $_SESSION[&#39;id&#39;] = $_POST[&#39;post_id&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容取得処理
             */
            $sql = (&#39;
                SELECT id, title, comment
                FROM board_info 
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            // SQL実行
            $stmt-&gt;execute();
            // ★投稿情報の取得
            $post_info = $stmt-&gt;fetch();
            $_SESSION[&#39;title&#39;] = $post_info[&#39;title&#39;];
            $_SESSION[&#39;comment&#39;] = $post_info[&#39;comment&#39;];
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 更新ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;update_submit_btn&#39;])) {
    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }
    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }
    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;
    /**
     * 必要項目がすべて入力されてたら更新処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容更新処理
             */
            $sql = (&#39;
                UPDATE board_info 
                SET title = :TITLE, comment = :COMMENT
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();
            // 更新に成功したらセッション変数を破棄
            // unset($_SESSION[&#39;id&#39;]);  // ★※投稿IDは敢えて破棄せず、掲示板ページでID判定をするために情報を保持する
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
            // ★掲示板ページへ戻る
            header(&#39;Location: board.php&#39;);
            exit();
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**★
 * キャンセルボタンが押下されたら
 * セッション情報を破棄して
 * 掲示板一覧画面へ戻る
 */
if (isset($_POST[&#39;cancel_btn&#39;])) {
    unset($_SESSION[&#39;id&#39;]);
    unset($_SESSION[&#39;title&#39;]);
    unset($_SESSION[&#39;comment&#39;]);
    header(&#39;Location: board.php&#39;);
    exit();
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;投稿編集画面&lt;/h1&gt;
    &lt;!-- 投稿編集フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;]))  echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;; ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;btn-flex&quot;&gt;
                &lt;button type=&quot;submit&quot; name=&quot;update_submit_btn&quot; value=&quot;update_submit_btn&quot;&gt;更新&lt;/button&gt;
                &lt;button type=&quot;submit&quot; name=&quot;cancel_btn&quot; value=&quot;cancel_btn&quot;&gt;キャンセル&lt;/button&gt;
            &lt;/div&gt;
        &lt;/form&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>
</div>



<p><code class="file_name">uppdate-edit.php</code>内で行われている処理は大きく<strong>３つ</strong>に分けられます。</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>投稿編集画面へ遷移してきたときの処理</li>



<li>「更新ボタン」が押下されたときの処理</li>



<li>「キャンセルボタン」が押下されたときの処理</li>
</ul>
</div></div>



<p>基本的には<strong>投稿機能</strong>の解説が理解できていれば、上記のコードもある程度は流れを追えるようになっているはずです。</p>



<p>しかし、いくつか<span class="swl-marker mark_yellow"><strong>投稿編集機能ならではの処理</strong>（★が付いている処理）</span>があるため、そちらについて詳しくご説明します。</p>



<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h4 class="wp-block-heading">投稿編集画面へ遷移してきたときの処理</h4>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP" data-line="[9,10,11,36,37,38,39,40]"><code>/**
 * 編集ボタンで遷移してきたときの処理
 */
if (isset($_POST[&#39;update_btn&#39;])) {
    /**
     * 編集対象の投稿情報を取得
     */
    if (isset($_POST[&#39;post_id&#39;]) && $_POST[&#39;post_id&#39;] != &#39;&#39;) {

        // ★セッションに投稿IDを保持
        $_SESSION[&#39;id&#39;] = $_POST[&#39;post_id&#39;];

        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);

            /**
             * 投稿内容取得処理
             */
            $sql = (&#39;
                SELECT id, title, comment
                FROM board_info 
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            // SQL実行
            $stmt-&gt;execute();

            // ★投稿情報の取得
            $post_info = $stmt-&gt;fetch();
            $_SESSION[&#39;title&#39;] = $post_info[&#39;title&#39;];
            $_SESSION[&#39;comment&#39;] = $post_info[&#39;comment&#39;];
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}</code></pre></div>



<p>上記のハイライト部分について順番に解説します。</p>



<p>まず、以下のコードでは<strong>セッション変数に編集対象の投稿IDを保存</strong>しています。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code> // ★セッションに投稿IDを保持
 $_SESSION[&#39;id&#39;] = $_POST[&#39;post_id&#39;];</code></pre></div>



<p>ここで、<strong><span class="swl-marker mark_yellow">投稿編集画面内の処理で投稿IDを利用する目的</span></strong>は２つあります。</p>



<div class="wp-block-group is-style-big_icon_good"><div class="wp-block-group__inner-container">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>投稿IDを元にデータベースから現在の投稿内容を取得するため</li>



<li>投稿IDをキーとして投稿内容を上書き（UPDATE）するため</li>
</ul>
</div></div>



<p>実は、セッションを利用せずとも、POSTで受け取った情報をそのまま使用して、データベースから投稿内容を取得することは可能です。もちろんPOSTで受け取った情報をキーとしてそのまま使用することも可能です。</p>



<p>それなのにどうして<strong>わざわざセッション変数に保持するのか</strong>というと</p>



<p class="is-style-icon_pen">POSTやGETなどのHTTPリクエストで送信された情報は、<strong>そのページ上で何らかの操作が行われてしまった時点で消滅してしまうため</strong></p>



<p>です。</p>



<p>今回の投稿編集機能にも、未入力ならエラーメッセージを返す処理を持たせています。</p>



<p>もしもユーザが投稿内容をまっさらにして「更新ボタン」を押下したとすると、その時点でPOST送信されてきた投稿ID情報は消滅してしまい、投稿内容を上書きする際に必要な情報（投稿ID）が不足してしまうのです。</p>



<p>そのため、<strong>投稿編集画面へ遷移してきた時点でセッション変数に投稿IDを保持して、ユーザの操作内容によって必要な情報が消滅してしまうのを防ぐ</strong>ようにしています。</p>



<p class="is-style-big_icon_point">アプリ開発では<strong>データの生存期間</strong>を理解することが大切です。</p>



<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<p>続いて以下の<strong>投稿情報の取得処理</strong>についてです。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>// ★投稿情報の取得
$post_info = $stmt-&gt;fetch();
$_SESSION[&#39;title&#39;] = $post_info[&#39;title&#39;];
$_SESSION[&#39;comment&#39;] = $post_info[&#39;comment&#39;];</code></pre></div>



<p>こちらも前述の処理と目的は同じで、<strong>データベースから取得した投稿内容データの生存期間を伸ばすため</strong>のものです。</p>



<p>想定しているシチュエーションは、「投稿編集画面でページ更新が行われたとき」です。</p>



<p>ページ更新が行われてしまうとPOST送信された情報は消滅してしまい、編集フォームから元々の投稿内容が消えてしまうのです。そこで、セッション変数に保持することでページ更新が行われたとしても確実に元々の投稿内容を出力できるようにしています。</p>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h4 class="wp-block-heading">「更新ボタン」が押下されたときの処理</h4>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP" data-line="[62,63,64,65,66,68,69,70,71]"><code>/**
 * 更新ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;update_submit_btn&#39;])) {
    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }

    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }

    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;

    /**
     * 必要項目がすべて入力されてたら更新処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];

        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);

            /**
             * 投稿内容更新処理
             */
            $sql = (&#39;
                UPDATE board_info 
                SET title = :TITLE, comment = :COMMENT
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();

            // 更新に成功したらセッション変数を破棄
            // unset($_SESSION[&#39;id&#39;]);  // ★※投稿IDは敢えて破棄せず、掲示板ページでID判定をするために情報を保持する
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);

            // ★掲示板ページへ戻る
            header(&#39;Location: board.php&#39;);
            exit();
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}</code></pre></div>



<p>「更新ボタンが押下されたときの処理」では<strong>2か所</strong>についてご説明します。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP" data-line="[1,2,3]"><code>// 更新に成功したらセッション変数を破棄
// unset($_SESSION[&#39;id&#39;]);  // ★※投稿IDは敢えて破棄せず、掲示板ページでID判定をするために情報を保持する
unset($_SESSION[&#39;title&#39;]);
unset($_SESSION[&#39;comment&#39;]);</code></pre></div>



<p>このコードでは<strong><span class="swl-marker mark_yellow">更新が成功した時点でセッション変数の情報をまっさらにしています。</span></strong></p>



<p>しかし、ハイライト箇所、つまり投稿IDについては、<strong>あえてセッション変数から削除せずに情報を残しています。</strong></p>



<p>その理由は</p>



<p class="is-style-bg_stripe">編集が完了し、掲示板トップへ戻った際に「更新しました」のテキストを出力するため</p>



<p>です。</p>



<p>それにより、どの投稿が編集されたかを分かりやすくしています。</p>


<div class="wp-block-image is-style-shadow">
<figure class="aligncenter size-full has-custom-border"><img decoding="async" width="676" height="460" src="https://kekenta-it-blog.com/wp-content/uploads/2024/02/image-9.png" alt="掲示板アプリ投稿編集時の「更新しました」表示" class="wp-image-2761" style="border-width:1px" srcset="https://kekenta-it-blog.com/wp-content/uploads/2024/02/image-9.png 676w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/image-9-300x204.png 300w" sizes="(max-width: 676px) 100vw, 676px" /></figure>
</div>


<p>ちなみにこの仕組みの理屈は、「投稿がセッション変数に保持している投稿IDと同じ投稿IDを持っていたら『更新しました』を表示する」となります。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>該当する処理は<code class="file_name">board.php</code>の以下の部分です。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP" data-line="[18,19,20]"><code>    &lt;!-- 投稿一覧 --&gt;
    &lt;section class=&quot;post-list&quot;&gt;
        &lt;?php if (count($post_list) === 0) : ?&gt;


　　　　　　　　　　　　　～　中略　～


        &lt;?php else : ?&gt;
            &lt;ul&gt;
                &lt;!-- 投稿情報の出力 --&gt;
                &lt;?php foreach ($post_list as $post_item) : ?&gt;
                    &lt;li&gt;


　　　　　　　　　　　　　～　中略　～


                        &lt;?php if (isset($_SESSION[&#39;id&#39;]) && ($_SESSION[&#39;id&#39;] == $post_item[&#39;id&#39;])) echo &quot;&lt;p class=&#39;updated-post&#39;&gt;更新しました&lt;/p&gt;&quot; ?&gt;
                    &lt;/li&gt;
                &lt;?php endforeach; ?&gt;
            &lt;/ul&gt;
        &lt;?php endif; ?&gt;
    &lt;/section&gt;</code></pre></div>



<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<p>続いて<strong>掲示板ページへ戻る処理の解説</strong>です。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain"><code>// ★掲示板ページへ戻る
header(&#39;Location: board.php&#39;);
exit();</code></pre></div>



<p class="is-style-icon_pen"><code>header()</code>関数はHTTPリクエストの<strong>ヘッダー情報を指定するための関数</strong>です。</p>



<p><code>header('Location: 遷移先のパス')</code>と記述することで、ページの遷移先を指定可能です。</p>



<p>上記のコードでは遷移先としてboard.php（掲示板トップ）を指定しています。</p>



<p>ちなみに<code>exit()</code>関数は「処理を終了する」という意味で、<strong>それ以降の行に記述されているコードが実行されてしまわないようにするための処理</strong>になります。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>上記ソースコードのような処理は、アプリ開発で使用頻度が高めなのでしっかり理解しておきましょう。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h4 class="wp-block-heading">「キャンセルボタン」が押下されたときの処理</h4>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>/**★
 * キャンセルボタンが押下されたら
 * セッション情報を破棄して
 * 掲示板一覧画面へ戻る
 */
if (isset($_POST[&#39;cancel_btn&#39;])) {
    unset($_SESSION[&#39;id&#39;]);
    unset($_SESSION[&#39;title&#39;]);
    unset($_SESSION[&#39;comment&#39;]);

    header(&#39;Location: board.php&#39;);
    exit();
}</code></pre></div>



<p>こちらの処理はいたってシンプルで、<strong><span class="swl-marker mark_yellow">掲示板トップへ戻る前にセッション情報を削除</span></strong>しているだけです。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>ちなみに<code class="file_name">board.php</code>（トップページ）でも、編集処理で使用しているものと同じセッション変数を扱っています。<br><br>そのため、掲示板トップへ遷移する前にきちんとセッション情報を削除しておかないと、<strong>掲示板トップへ遷移したとき入力フォームに<span class="swl-marker mark_yellow">編集対象の投稿内容情報が表示されてしまう</span></strong>というおかしな状況になってしまいます。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>編集機能における仕組みのポイントは<strong><span class="swl-marker mark_yellow">データの生存期間</span></strong>です。</p>



<p>はじめの内は「データがいつまで生きているのか」をイメージするのは慣れないかもしれませんが、実践を繰り返すことで確実に身に付く感覚です。</p>



<p>以上が「編集機能の解説」でした。</p>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h3 class="wp-block-heading">機能３　削除</h3>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>最後、3つ目の機能である<strong><span class="swl-marker mark_yellow">削除機能</span></strong>について解説をしていきます。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label"><strong>delete-confirm.php</strong>（削除確認画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-file="delete-confirm.php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;
/**
 * 削除ボタンで遷移してきたときの処理
 */
if (isset($_POST[&#39;delete_btn&#39;])) {
    /**
     * 編集対象の投稿情報を取得
     */
    if (isset($_POST[&#39;post_id&#39;]) && $_POST[&#39;post_id&#39;] != &#39;&#39;) {
        // セッションに投稿IDを保持
        $_SESSION[&#39;id&#39;] = $_POST[&#39;post_id&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                SELECT id, title, comment
                FROM board_info 
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿情報の取得
            $post_info = $stmt-&gt;fetch();
            $_SESSION[&#39;title&#39;] = $post_info[&#39;title&#39;];
            $_SESSION[&#39;comment&#39;] = $post_info[&#39;comment&#39;];
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 削除ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;delete_submit_btn&#39;])) {
    try {
        /**
         * DB接続処理
         */
        $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
            PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
        ]);
        /**
         * 投稿内容削除処理
         */
        $sql = (&#39;
            DELETE FROM board_info 
            WHERE id = :ID
        &#39;);
        $stmt = $pdo-&gt;prepare($sql);
        // プレースホルダーに値をセット
        $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
        // SQL実行
        $stmt-&gt;execute();
        // 削除に成功したらセッション変数を破棄
        unset($_SESSION[&#39;id&#39;]);
        unset($_SESSION[&#39;title&#39;]);
        unset($_SESSION[&#39;comment&#39;]);
        // 削除成功画面へ遷移
        header(&#39;Location: delete-success.php&#39;);
        exit();
    } catch (PDOException $e) {
        echo &#39;接続失敗&#39; . $e-&gt;getMessage();
        exit();
    }
    // DBとの接続を切る
    $pdo = null;
    $stmt = null;
}
/**
 * キャンセルボタンが押下されたら
 * セッション情報を破棄して
 * 掲示板一覧画面へ戻る
 */
if (isset($_POST[&#39;cancel_btn&#39;])) {
    unset($_SESSION[&#39;id&#39;]);
    unset($_SESSION[&#39;title&#39;]);
    unset($_SESSION[&#39;comment&#39;]);
    header(&#39;Location: board.php&#39;);
    return;
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;削除確認&lt;/h1&gt;
    &lt;p class=&quot;delete-confirm-msg&quot;&gt;以下の投稿を削除します。&lt;/p&gt;
    &lt;!-- 削除確認画面 --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;p&gt;タイトル&lt;/p&gt;
                    &lt;p&gt;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&lt;/p&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;p&gt;投稿内容&lt;/p&gt;
                    &lt;p class=&quot;p-pre&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;]))  echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/p&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;btn-flex&quot;&gt;
                &lt;button type=&quot;submit&quot; name=&quot;delete_submit_btn&quot; value=&quot;delete_submit_btn&quot;&gt;削除&lt;/button&gt;
                &lt;button type=&quot;submit&quot; name=&quot;cancel_btn&quot; value=&quot;cancel_btn&quot;&gt;キャンセル&lt;/button&gt;
            &lt;/div&gt;
        &lt;/form&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>
</div>



<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label"><strong>delete-success.php</strong>（削除成功画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-file="delete-success.php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * ★掲示場TOPへ自動で遷移する処理
 */
header(&#39;refresh: 3; url=board.php&#39;);
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;削除が完了しました。&lt;/h1&gt;
    &lt;p class=&quot;delete-success-msg&quot;&gt;3秒後に自動で掲示板TOPへ戻ります。&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>
</div>



<p class="has-text-align-center is-style-balloon_box"><strong>削除機能</strong>の流れ</p>


<div class="wp-block-image is-style-shadow size_s">
<figure data-wp-context="{&quot;imageId&quot;:&quot;69e3e8ad89ba4&quot;}" data-wp-interactive="core/image" data-wp-key="69e3e8ad89ba4" class="aligncenter size-large wp-lightbox-container"><img decoding="async" width="1024" height="646" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://kekenta-it-blog.com/wp-content/uploads/2024/02/98ba59fab650b7da59c78996601fbefd-1024x646.jpg" alt="" class="wp-image-3064" srcset="https://kekenta-it-blog.com/wp-content/uploads/2024/02/98ba59fab650b7da59c78996601fbefd-1024x646.jpg 1024w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/98ba59fab650b7da59c78996601fbefd-300x189.jpg 300w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/98ba59fab650b7da59c78996601fbefd-768x485.jpg 768w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/98ba59fab650b7da59c78996601fbefd-1536x969.jpg 1536w, https://kekenta-it-blog.com/wp-content/uploads/2024/02/98ba59fab650b7da59c78996601fbefd-2048x1293.jpg 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="拡大する"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>
</div>


<div class="swell-block-capbox cap_box is-style-shadow" data-colset="col3"><div class="cap_box_ttl"><span><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGQ9Ik0yNTYgNTEyYzE0MS40IDAgMjU2LTExNC42IDI1Ni0yNTZTMzk3LjQgMCAyNTYgMFMwIDExNC42IDAgMjU2UzExNC42IDUxMiAyNTYgNTEyek0zNjkgMjA5TDI0MSAzMzdjLTkuNCA5LjQtMjQuNiA5LjQtMzMuOSAwbC02NC02NGMtOS40LTkuNC05LjQtMjQuNiAwLTMzLjlzMjQuNi05LjQgMzMuOSAwbDQ3IDQ3TDMzNSAxNzVjOS40LTkuNCAyNC42LTkuNCAzMy45IDBzOS40IDI0LjYgMCAzMy45eiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasCircleCheck" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span><strong> 削除機能の流れ</strong></span></div><div class="cap_box_content">
<ul class="wp-block-list is-style-num_circle -list-under-dashed">
<li>削除したい投稿の「削除ボタン」を押下する</li>



<li>削除確認画面へ遷移する</li>



<li>「削除ボタン」を押下する</li>



<li>削除を実行し、削除完了画面へ遷移する</li>



<li>3秒後に自動で掲示板トップへ遷移する</li>
</ul>
</div></div>



<p>実は、削除機能で解説することはそれほど多くありません。</p>



<p><code class="file_name">delete-confirm.php</code>（削除確認画面）のコードこそ長いですが、<strong>処理の流れや構造は以下のとおり</strong>で、<span class="marker-under"><code class="file_name">update-edit.php</code>（投稿編集画面）のときとほとんど同じ</span>です。</p>



<div class="wp-block-group has-border -border01"><div class="wp-block-group__inner-container">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>削除確認画面へ遷移してきたときの処理</li>



<li>「削除ボタン」が押下されたときの処理</li>



<li>「キャンセルボタン」が押下されたときの処理</li>
</ul>
</div></div>



<p>異なるのはザックリ以下の<strong>3点</strong>のみです。</p>



<p class="is-style-balloon_box"><strong>編集機能と異なる点</strong></p>



<ul class="wp-block-list -list-under-dashed is-style-check_list">
<li>「更新ボタン」が「削除ボタン」になっている</li>



<li>編集画面では入力フォーム（input、textareaタグ）だった部分が、単なるテキスト（pタグ）になっている</li>



<li>「削除ボタン」押下後に「削除成功画面へ」遷移する</li>
</ul>



<p>しかも、最初の２つについてはPHPの処理ではなくHTMLでの表示に関係することのため、特筆する部分もありません。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>したがって、本章での解説は「削除ボタン」押下後の<code class="file_name">delete-success.php</code><strong>（削除成功画面）</strong>、しかもその内の１ヵ所のみとなります。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<h4 class="wp-block-heading">掲示場TOPへ自動で遷移する処理</h4>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>/**
 * ★掲示場TOPへ自動で遷移する処理
 */
header(&#39;refresh: 3; url=board.php&#39;);</code></pre></div>



<p>これは、削除機能の流れの最後にあたる「3秒後に自動で掲示板トップへ遷移する」を実現している処理です。</p>



<p>編集機能でも登場した<code>header()</code>関数を利用しており、このように記述をすると</p>



<p class="is-style-bg_stripe">削除完了画面へ遷移してから3秒後にboard.phpへリダイレクトする</p>



<p>という処理が実行されます。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>編集機能のときは、どの投稿を編集したのかが分かるように「更新しました」を表示する仕様としました。<br>一方、削除のときは、ユーザに<strong>しっかりと「削除した」ことを伝えるため</strong>に削除完了画面へ遷移させ、その後は操作不要で自動的に掲示板トップへ遷移する実装にする実装としています。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>※もちろん「トップへ戻る」というリンクを設置する形でも問題ありません。</p>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<p class="has-text-align-center"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik0yMDEuNCAzNzQuNmMxMi41IDEyLjUgMzIuOCAxMi41IDQ1LjMgMGwxNjAtMTYwYzEyLjUtMTIuNSAxMi41LTMyLjggMC00NS4zcy0zMi44LTEyLjUtNDUuMyAwTDIyNCAzMDYuNyA4Ni42IDE2OS40Yy0xMi41LTEyLjUtMzIuOC0xMi41LTQ1LjMgMHMtMTIuNSAzMi44IDAgNDUuM2wxNjAgMTYweiI+PC9wYXRoPjwvc3ZnPg==)" data-icon="FasAngleDown" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span></p>



<h2 class="wp-block-heading">最初は難しく感じても、実践を繰り返せば必ずできるようになる！</h2>



<p>以上、<strong><span class="swl-marker mark_yellow">PHPで掲示板アプリを作成する方法</span></strong>について解説をしてきました。</p>



<p>簡単な振り返りとして、当記事でご紹介した掲示板アプリのポイントは以下の通りです。</p>



<div class="swell-block-capbox cap_box is-style-shadow"><div class="cap_box_ttl"><span><span data-icon="LsLightbulb" data-id="0" style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" aria-hidden="true" class="swl-inline-icon"> </span><strong>掲示板アプリのポイント</strong></span></div><div class="cap_box_content">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>基本機能は３つ（投稿・編集・削除）</li>



<li>ログイン機能は持たないが、セッションを活用し投稿者IDでユーザを識別</li>



<li>編集・削除後にユーザへ完了内容を適切に伝達</li>



<li>空白投稿は拒否（エラーメッセージの出力）</li>
</ul>
</div></div>



<p>正直、初めてWebアプリを作成される方にとっては非常に難しい内容だったかと思います。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/困った顔-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/困った顔-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>こんなことまで考えて作れないよ……</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>と思われた方もいらっしゃるのではないかと想像しています。</p>



<p>しかし、実際に自分の手でアプリ開発をしてみると分かりますが、少なくとも慣れない内はいわゆる「一発書き」は難しいです。</p>



<p>実装するべきことを整理し、それらを少しずつプログラミングしていく途中途中で</p>



<p>「ここはこうした方が良いな」</p>



<p>ということに気が付き、改良を重ねていくという流れになることが多いです。</p>



<p>その道のりを超えると、当記事でご紹介したようなコードが出来上がります。</p>



<p>僕も経験がありますが、もしかしたら後からコードを振り返ったとき</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/真顔-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/真顔-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>（自分、よくこんな風にプログラミングできたな……）</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p>と感じることもあるかもしれません。</p>



<p>プログラミングは意外とそんなもので、やっているときとそれを客観視したときとで、体感するレベル感にギャップが生まれがちです。</p>



<p>それを埋めていくためには、やはり実践しかありません。</p>



<p>プログラミングを自力でできるようになる＝習得するためには多くの時間と労力がかかりますが、勉強を継続することで必ず身に付けることが可能です。</p>



<p>この記事がプログラミング初心者の方にとって役に立ったなら何よりです。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>セキュリティ対策実装verについては以下の記事をご覧下さい！</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>

<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">あわせて読みたい</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/eye-catch__php-board-app-secure__3549-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/php-board-app-secure/">【PHP】掲示板アプリの作り方｜正しいセキュリティ対策</a>
						<span class="p-blogCard__excerpt">以前にこちらの記事で掲示板アプリの作成方法を解説しました。 記事内でもお伝えしているように、上の記事で解説している掲示板アプリではセキュリティ対策はしておらず&#8230;</span>					</div>
				</div>
			</div>
		</div>


<p>最後までご覧いただきありがとうございました。</p>



<p>また別の記事でお会いできたら光栄です。</p>



<p class="is-style-bg_stripe">ご自身でセキュリティ対策についてきちんと勉強したいという方には以下の書籍がおすすめです。<br>（<strong>通称：徳丸本</strong>と呼ばれる「Webアプリ開発者必読」とまで言われている書籍です）<br><br><a href="https://www.amazon.co.jp/%E4%BD%93%E7%B3%BB%E7%9A%84%E3%81%AB%E5%AD%A6%E3%81%B6-%E5%AE%89%E5%85%A8%E3%81%AAWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-%E7%AC%AC2%E7%89%88-%E8%84%86%E5%BC%B1%E6%80%A7%E3%81%8C%E7%94%9F%E3%81%BE%E3%82%8C%E3%82%8B%E5%8E%9F%E7%90%86%E3%81%A8%E5%AF%BE%E7%AD%96%E3%81%AE%E5%AE%9F%E8%B7%B5-%E5%BE%B3%E4%B8%B8/dp/4797393165?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&amp;crid=1FQAOXKEGI9HT&amp;dib=eyJ2IjoiMSJ9.ksxMxdA4KTXnYLFgVxMFis4f3XHMUvarmNijcsU4Nmvl3Tud_nU0g7agEl3ercb-Os7uj_I-9w5xejzyw_JwMcs7FC4uVP9jc3sHC7c9ZuDT_gwuJFliueZNV3zuXq4731v-JAlEh4pR64KI-_puhFly0i_zkfDlsH2xTLQWoeNNIM9FkS584d43eeD8-mNtPjbtKK1lmvjecUb-VALfXImg-mACYpqlPWhTawzlYmnCmT85BL5k4gVzrtlErnyRPeFE4qCXwaN884rSGk9l6PGCfVcIoDQOg1lp8Ia-RWA.i4wIGc7KFczkxeNgrmVo03tuk6Fod-K6t-LEHGJtLtE&amp;dib_tag=se&amp;keywords=Web%E3%82%A2%E3%83%97%E3%83%AA+%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3&amp;qid=1718235109&amp;sprefix=web%E3%82%A2%E3%83%97%E3%83%AA+%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%2Caps%2C186&amp;sr=8-1&amp;linkCode=ll1&amp;tag=kekenta03amaz-22&amp;linkId=dc5df2a77d4a028f4519e6b2a07ffb84&amp;language=ja_JP&amp;ref_=as_li_ss_tl"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNNDQgMkgzMGMtMS4xIDAtMiAuOS0yIDJzLjkgMiAyIDJoOS4yTDI0IDIxLjJjLS44LjgtLjggMiAwIDIuOHMyIC44IDIuOCAwTDQyIDguOFYxOGMwIDEuMS45IDIgMiAyczItLjkgMi0yVjRjMC0xLjEtLjktMi0yLTJ6Ij48L3BhdGg+PHBhdGggZD0iTTQxIDI3Yy0xLjEgMC0yIC45LTIgMnYxMGMwIDEuMS0uOSAyLTIgMkg5Yy0xLjEgMC0yLS45LTItMlYxMWMwLTEuMS45LTIgMi0yaDEwYzEuMSAwIDItLjkgMi0ycy0uOS0yLTItMkg5Yy0zLjMgMC02IDIuNy02IDZ2MjhjMCAzLjMgMi43IDYgNiA2aDI4YzMuMyAwIDYtMi43IDYtNlYyOWMwLTEuMS0uOS0yLTItMnoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsExternalLink" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span>体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 脆弱性が生まれる原理と対策の実践</a><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMTEuNyAxLjQgNi44IDVjLS41LjQtLjggMS0uOCAxLjZ2MjguN2MwIC44LjUgMS41IDEuMiAxLjhsMjQgMTAuM2MxLjMuNiAyLjgtLjQgMi44LTEuOFYxOWMwLS44LS41LTEuNS0xLjItMS44TDEwLjIgNy41bDIuOS0yLjJjLjktLjYgMi0uOCAzLS40bDIwLjYgOC44Yy43LjMgMS4yIDEgMS4yIDEuOFY0Mi45YzAgLjkgMSAxLjMgMS43LjhsMS43LTEuNWMuNC0uNC43LS45LjctMS41VjEzYzAtLjgtLjUtMS41LTEuMi0xLjhMMTYuNy44Yy0xLjctLjctMy42LS41LTUgLjZ6Ij48L3BhdGg+PC9zdmc+)" data-icon="LsBook" data-id="47" aria-hidden="true" class="swl-inline-icon"> </span><br>徳丸 浩／著　SBクリエイティブ／出版│<a href="https://www.amazon.co.jp/%E4%BD%93%E7%B3%BB%E7%9A%84%E3%81%AB%E5%AD%A6%E3%81%B6-%E5%AE%89%E5%85%A8%E3%81%AAWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-%E7%AC%AC2%E7%89%88-%E8%84%86%E5%BC%B1%E6%80%A7%E3%81%8C%E7%94%9F%E3%81%BE%E3%82%8C%E3%82%8B%E5%8E%9F%E7%90%86%E3%81%A8%E5%AF%BE%E7%AD%96%E3%81%AE%E5%AE%9F%E8%B7%B5-%E5%BE%B3%E4%B8%B8/dp/4797393165?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&amp;crid=1FQAOXKEGI9HT&amp;dib=eyJ2IjoiMSJ9.ksxMxdA4KTXnYLFgVxMFis4f3XHMUvarmNijcsU4Nmvl3Tud_nU0g7agEl3ercb-Os7uj_I-9w5xejzyw_JwMcs7FC4uVP9jc3sHC7c9ZuDT_gwuJFliueZNV3zuXq4731v-JAlEh4pR64KI-_puhFly0i_zkfDlsH2xTLQWoeNNIM9FkS584d43eeD8-mNtPjbtKK1lmvjecUb-VALfXImg-mACYpqlPWhTawzlYmnCmT85BL5k4gVzrtlErnyRPeFE4qCXwaN884rSGk9l6PGCfVcIoDQOg1lp8Ia-RWA.i4wIGc7KFczkxeNgrmVo03tuk6Fod-K6t-LEHGJtLtE&amp;dib_tag=se&amp;keywords=Web%E3%82%A2%E3%83%97%E3%83%AA+%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3&amp;qid=1718235109&amp;sprefix=web%E3%82%A2%E3%83%97%E3%83%AA+%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%2Caps%2C186&amp;sr=8-1&amp;linkCode=ll1&amp;tag=kekenta03amaz-22&amp;linkId=dc5df2a77d4a028f4519e6b2a07ffb84&amp;language=ja_JP&amp;ref_=as_li_ss_tl">Amazon</a></p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
