カテゴリーアーカイブ PHP

村上 著者:村上

【PHP】「Parse error: syntax error」の対処法

学生さんが書いたプログラムを修正する機会があり、その時に遭遇したエラーです。
分かってみればとても初歩的なミスだったのですが、その時は気が付くのに時間がかかってしまいました。

参考にさせていただいたサイトはこちらから。

「Parse error: syntax error」とは? \ PHPプログラミングの教科書 [php1st.com]
https://php1st.com/1263/

 

さて、今回のエラー「Parse error: syntax error」ですが、こちらは構文エラーが原因です。
入力ミスなどで、PHPの解釈(分析・翻訳)がうまくいかなかったときに発生します。

なお、今回のエラーは全角スペースが含まれていることが原因でした。
使用しているエディタが全角スペースと半角スペースが少しわかりにくい表示だったので、気が付くのが遅くなってしまいました…。
半角スペースに直したところ、無事問題なく実行できました。

で、このエラーですが、エラー文の最後に行数が表示されるのですが、この行数は、必ずしもエラーが発生した行の位置を示しているとは限らないとのこと。
私の遭遇した状況では、エラー文で示された行数と、実際ミスをしていた行数が一致していましたが、場合によっては、表示されている行数よりも上でエラーが発生していることもあるようです。
なので、エラー文の行数はあまり信用しないほうがよさそうです。

 

以上、初心者がやらかしがちなPHPのエラーでした。
今回の状況も踏まえまして、特に初心者の皆さんは今使っているエディターの半角スペースや全角スペースをきちんと可視化しておくことをおすすめします。

  • この記事いいね! (0)
asaba 著者:asaba

おすすめの書籍

これからプログラミングを始めたい人が最初に考えがちなのが、どういった学習をしていけばいいかということだと思います。

自分は、この「気づけばプロ並みPHP」という書籍を使ってプログラミングの動きを体系的に学びました。

この書籍の良い所は、プログラミングの基礎だけでなく、サーバーやデータベースも業務で使われているシステムに限りなく近いスタンスで触ることができることです。

また、章ごとにコンポーネントを作っていくので、一つ一つ完成させてゴールを目指すことでモチベーションを保つことができるという点では大きいです。

(さすがにどこでエラーになったかはブラウザで自分でデバッグしなければいけませんけどね。)

キャラクターも可愛いのでとっつきやすいと思います。

また、PHPはブラウザだけでも動かすことができるので、これからプログラミングを始めたい人やコードの動きを改めて見直したいなって思う人には向いていると思いました。(swiftとかjavaだと環境設定も手間かかるし対応するOSも変わってきますしね)

自分が今まで読んできた書籍は、厚くはないものの記載されているコードがどういう時に使われるのかどう応用されるのか説明がないまま漠然とコードを書かされているような感じにさせられるものばかりだったので、これならネットで落ちているソースコードを真似てミニアプリでも作ったほうが身になるなって感じで途中でやめていました。

自分もまだ駆け出しの身で、作りたいものがあっても辞書引きしながらでないとうまく作れないので今でもたまに初心にかえってQiita見たり色々読み返したりしています。

一番大事なのは、つくりたいものが明確にあることですが、自分にあった書籍に出会うことも大事なのかなって感じます。

以上です。

  • この記事いいね! (0)
takahashi 著者:takahashi

Cookieの罠。PHP(サーバー側)からCookieを取得・設定すると遅延する!?

今回、盛大にハマったので記事にします。

詳細はいろいろな事情があって公開できないので、それっぽいコードで説明します。
いま、PHPを使ったWebアプリを開発しているのですが、このアプリはいろいろな事情からCookieを多用する設計になっています。

そしてこのCookieは基本的にPHP側(サーバーサイド)で書き込みを行うようにしています。PHPで書いた方が処理が簡単だったからです。

フレームワークとしてFuelPHPを使用しているので、下記の関数でCookieの操作ができます。

//Cookieの設定
Cookie::set(クッキーのキー, クッキーに格納する値, 有効期限, cookieを有効にするWebページのパス, cookieを有効にするドメイン, $secure = セキュアな接続の時のみ cookie を送信するか否か。, http経由での接続でのみ有効にするか否か);

//Cookieの呼び出し
Cookie::get(クッキーのキー, クッキーが取得できなかった時に返す値);

詳しくはこちらを参照してください。
Cookie クラス – FuelPHP 日本語マニュアル

で、例えば下記のようなコードを書いたとします。

$a="hoge"
$result = Cookie::set("testkey",$a); //Cookieの送信に成功すればtrueを返す。
$b = Cookie::get("testkey",""); //書き込んだCookieを取得。

echo $result;
var_dump($a); //①
var_dump($b); //②

としたときに、$resultが”true”になっていれば、①と②の出力結果は同一のものになる、のが期待する動作なのですが、場合によって、②の時点での$bの値が”hoge”ではなく””になってしまうという事態が今回発生しました。

そんな馬鹿なと何度も確認したり、Cookie::setする前に対象のキーを削除したりいろいろ試したのですが、解決せず。

ここでふと、Google Chromeに、自分が保持しているクッキーの一覧が表示できる機能があったことを思い出し、こちら側でも確認してみました。

調査したいページを開いた状態でChromeの開発者ツール内のApplicationタブを開き、左側カラムの

Storage->Cookies->対象のサイトのURL

と辿っていくと、そのURLで保存されているCookieの一覧を見ることができます。

PHPがわの表示といっしょに、こちらの値の変化も確認していたところ、ブラウザ側で見たCookie”testkey”の値にはちゃんと期待した値の”hoge”という文字列が見えていました。

サーバーサイドからブラウザにCookieを渡す場合、実際にはHTTPのレスポンスヘッダに値を入れてブラウザに渡しています。
ブラウザからWebサーバーに対して接続した際に、基本的に応答が返ってくるまでに少し時間がかかります。

よくよく考えれば、サーバーに対しての通信で多少の遅延が発生するのなら、ブラウザへ値を保存する際に遅延が発生しても不思議ではないですよね。

今回はこの遅延が原因で、サーバーサイドで値がうまく取れなかったのではないか、と結論付けました。

…ということで、Cookieの値を保存・取得する際は、多少遅延が発生する可能性があるのでCookieを扱う際は注意が必要かも…というお話でした(;´∀`)

  • この記事いいね! (0)
著者:杉浦

読むのが早いソースコード

 ソースコードは早く理解されるコードであることが要求されます。早く理解されるためには、書かれている文字が何なのか読み取られるという方法があります。同じ動作を関数化することはよく使われる手法です。

function natcmp_name($a, $b) {
	if (empty($a['nickname']) || $a['nickname'] == "") {
		$a['nickname'] = $a['fullname'];
	}
	if (empty($b['nickname']) || $b['nickname'] == "") {
		$b['nickname'] = $b['fullname'];
	}
}

 これは連想配列aと連想配列bを比較する関数です。比較の方法はニックネームの自然な辞書順の比較、もしニックネームがなければ代わりにフルネームを使う、です。この関数はabならば>0を返します。自然な辞書順というのは主に数字に関連した部分です。単純な辞書順では一文字ずつ文字を読み取り、違いが出た時点で順序を決定します。この単純な辞書順において’1abc’という文字列は’10abc’という文字列よりも後に並びます。これは2文字目のaと0の比較で0の方が辞書順で前に来るのが適当であるためです。自然な辞書順において’1abc’という文字列は’10abc’という文字列よりも後に並びます。
 この関数を用いてある3人の名前の並び順を決定する。コードを書くと次の様になります。

function natcmp_name($a, $b) {
	if (empty($a['nickname']) || $a['nickname'] == "") {
		$a['nickname'] = $a['fullname'];
	}
	if (empty($b['nickname']) || $b['nickname'] == "") {
		$b['nickname'] = $b['fullname'];
	}
	strnatcmp($a["nickname"], $b["nickname"]);
}
natcmp_name($person[1],$parson[2]);
natcmp_name($person[2],$parson[3]);
natcmp_name($person[3],$parson[1]);

 3回の比較が12行程度で記述できました。これを関数抜きで記述した場合、次のようになります

if (empty($person[1]['nickname']) || $person[1]['nickname'] == "") {
	$person[1]['nickname'] = $person[1]['fullname'];
}
if (empty($person[2]['nickname']) || $person[2]['nickname'] == "") {
	$person[2]['nickname'] = $person[2]['fullname'];
}
strnatcmp($person[1]["nickname"], $person[2]["nickname"]);
if (empty($person[2]['nickname']) || $person[2]['nickname'] == "") {
	$person[2]['nickname'] = $person[2]['fullname'];
}
if (empty($person[3]['nickname']) || $person[3]['nickname'] == "") {
	$person[3]['nickname'] = $person[3]['fullname'];
}
strnatcmp($person[2]["nickname"], $person[3]["nickname"]);
if (empty($person[3]['nickname']) || $person[3]['nickname'] == "") {
	$person[3]['nickname'] = $person[3]['fullname'];
}
if (empty($person[1]['nickname']) || $person[1]['nickname'] == "") {
	$person[1]['nickname'] = $person[1]['fullname'];
}
strnatcmp($person[3]["nickname"], $person[1]["nickname"]);

 21行であり、比較回数が増えればもっともっと増えます。これに目を通すのは前の例より時間がかかります。さらに置換ミスやタイプミスによる想定外の動作に気づきにくいという問題もあります。
 もっとも、一番読むのが早いのは何も書かれていないコードです。上に並べたコードは比較をしましたが比較から何も返ってきません、データを参照して、操作しているだけです。最後のコードに至ってはデータを上書きで壊すバグの元ですらあります。再利用の可能性のある場合でもコメントアウト、再利用の可能性のない場合は完全に消去。読む必要のある部分は0行になります。

  • この記事いいね! (0)
村上 著者:村上

【PHP】文字列を全角←→半角に変換するmb_convert_kana()関数

覚えておくと意外と便利なので、備忘録としてまとめ。
PHPで全角を半角に、もしくはその逆を行う方法です。

今回使う関数は、mb_convert_kana()です。
参考にさせていただいたページはこちら。

PHP関数 – 半角 ⇔ 全角 変換 – mb_convert_kana() – PHP入門のカルマ
https://webkaru.net/php/function-mb-convert-kana/

 

使い方はこちら。

$result = mb_convert_kana([変換したい文字列], [変換方法]);

上記のように指定します。
なお、変換方法は省略が可能で、省略した場合は、KV(=「半角カタカナ」を「全角カタカナ」にし、濁点付きの文字を一文字に変換)になります。
変換方法の一覧は下記のとおりです。

 

オプション 変換内容
r 「全角」英字を「半角」に変換
R 「半角」英字を「全角」に変換
n 「全角」数字を「半角」に変換
N 「半角」数字を「全角」に変換
a 「全角」英数字を「半角」に変換
A 「半角」英数字を「全角」に変換
s 「全角」スペースを「半角」に変換
S 「半角」スペースを「全角」に変換
k 「全角カタカナ」を「半角カタカナ」に変換
K 「半角カタカナ」を「全角カタカナ」に変換
h 「全角ひらがな」を「半角カタカナ」に変換
H 「半角カタカナ」を「全角ひらがな」に変換
c 「全角カタカナ」を「全角ひらがな」に変換
C 「全角ひらがな」を「全角カタカナ」に変換
V 濁点付きの文字を一文字に変換。K、Hと共に使用

よく使いそうなのは、「as」かな?
このオプションでは、英数字とスペースを半角にします。
なお、オプションは複数指定できます。

 

以上、文字列を全角←→半角に変換する方法でした。
全角が入力されては困る項目などでは、少なくとも「askh」あたりを指定しておけば、ある程度は対応できるかと思います。
是非、ご活用ください。

  • この記事いいね! (0)
takahashi 著者:takahashi

FuelPHP初期設定時に”It is not safe to rely on the system’s timezone settings.”エラーが出た時の対処法

先日、自分用にFuelPHPのテスト環境を作成していた時のこと。
ファイルやウェブサーバー周りの設定が終わって、テストでFuelPHPを動作させたところ…

Fuel\Core\PhpErrorException [ Error ]:
date_default_timezone_get(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone.

初めて見るエラー(汗
前回別の環境でセットアップした時はこんなエラーは出たことがなく、原因がわからなかったのでちょっと焦りました。

困っていろいろ調べていたら、こちらのサイトを発見。

[PHP]php.iniのtimezoneを設定する – Qiita

どうやら、PHP自身にデフォルトタイムゾーンを指定しないとダメ見たいです。

今回はCentOS7を使っていたので、php.iniは
/etc/php.ini
にありました。

php.ini内の

[date]セクションの部分に、赤枠のように記入します。

date.timezone = "Asia/Tokyo"

これでphp.iniを保存し、Apacheを再起動。

再度実行してみると

無事スタートページが表示されました。

  • この記事いいね! (0)
村上 著者:村上

【PHP】正規表現をチェックできる「正規表現チェッカーPHP: preg_match() / JavaScript: match()」【JavaScript】

今回は、正規表現を扱うときによく利用するサイトを紹介。
といっても、知ってる人も多いかと思います。

正規表現チェッカー PHP: preg_match() / JavaScript: match()
http://okumocchi.jp/php/re.php

正規表現が正しいかどうかをチェックしてくれるサイトです。
他にもいくつかありますが、私はもっぱらこのサイトを使っています。
検索結果の一番上に来ることが多いので、それも理由の一つですね。

 

サイトはこのようなレイアウトです。

上のテキストボックスにチェックしたい正規表現を入力し、下のテキストエリアにチェックしたい文字列を入力して、チェック!のボタンを押します。
すると、結果が下のエリアに表示されます。
検索結果の配列まで表示されるので、特に重宝しましたね。

また、下にリファレンスが載っているので、それを見ながら正規表現を組み立てることができます。
最近はよく使うものについては覚えられるようになってきましたが…最初のころはチンプンカンプンだったので、これにかなり助けられました…。
郵便番号やメールアドレスをチェックするためのサンプルもいくつか掲載しており、これにも非常に助けられました。

そして、このサイトでは、PHPだけでなく、JavaScriptでの結果も同時に確認できます。
まあ、結果はPHPとほぼ同じですが…。

 

以上、PHPやJavaScriptの正規表現をチェックする方法でした。
正規表現って苦手な方も多そうですし、私もその一人でしたが…覚えるとかなり便利なので、こういったサイトを活用して頑張りましょう

  • この記事いいね! (0)
村上 著者:村上

【PHP】文字列の置換を行うstr_replace()、preg_replace()の違い

今回はPHPで文字列を置換する方法について。
が、文字列の置換でも、関数は2種類あるので、その違いについて。
どちらかというと、自分のためのまとめですね。

置換を扱う関数は、str_replace()preg_replace() があります。
PHPマニュアルは下記からご確認ください。

str_replace():http://php.net/manual/ja/function.str-replace.php
preg_replace():http://php.net/manual/ja/function.preg-replace.php

 

使い方は下記のとおりです。

$text = "ABCDEF";  // 置換前の文字

$result1 = str_replace("A", "Z", $text);
$result2 = preg_replace("/^A/", "Z", $text);

結果はどちらも「ZBCDEF」になります。

例を見てわかる通り、str_replace() は A を B に置き換えるなど、単なる文字列の置換に向いています。
マニュアルにも、「正規表現のような技巧的な置換を必要としない場合、preg_replace() の代わりにこの関数を常用するべき」とありました。
対して、preg_replace() は正規表現を利用する、少し複雑な検索と置換を扱うときに使用します。

なお、今回は書きませんでしたが、どちらの関数でも置換した回数を取得することができます。
str_replace()の時は、第4引数に、preg_replace()の時は、第5引数に、$count などの変数を指定しておくと、指定した変数の中に、置換回数が格納されます。

 

以上、PHPで文字列を置換する方法でした。
単純な置換の場合は str_replace()を、正規表現を使った置換の場合は preg_replace()を使うように心がけましょう。

  • この記事いいね! (0)
村上 著者:村上

【PHP】指定した幅で文字列を丸める関数「mb_strimwidth()」

本日は、他の人が書いたソースコードを読んでいて発見したPHPの関数「mb_strimwidth()」について。
「この関数見たことないな?何だろう?」と調べたところ、指定した幅で文字列を丸めてくれるとのことで…とっても便利そうな関数でした。
もう少し早くに出会いたかった…!

PHPマニュアルの mb_strimwidth()関数についてのページはこちらから。

PHP: mb_strimwidth-Manual
http://php.net/manual/ja/function.mb-strimwidth.php

 

さて、具体的な使い方は、下記のとおりです。

$text = mb_strimwidth("丸めたいテキストを指定", 0, 20, "....", "UTF-8");

上のコードを実行すると、「丸めたいテキスト….」という結果になります。
どうやら第3引数の丸めた後のテキスト幅は、第4引数の文字数を丸めた後に追加する文字列まで含めた数で、かつ半角でカウントした場合のようです。
なお、第5引数の文字コードは指定しておくと、文字化けしなくなるとのことなので、出来る限り指定したほうがよさそうです。
こちらについては、下記のサイトが分かりやすかったです。

指定した文字数で文字列をまるめるPHPの関数 mb_strimwidth で、第4引数に「文字列をまるめた後に付加する文字列を指定」する際、色々気を付けないと文字化けるよ、というお話。|ITキヲスク
http://smkn.xsrv.jp/blog/2013/03/mb_strimwidth-function-tips/

 

以上、mb_strimwidth() で文字列を丸める方法でした。
以前の記事で、JavaScriptで文字列を丸める方法についても紹介しましたが、こちらの方が便利そうですね。
今後はこちらを積極的に使うようにしたいと思います。

  • この記事いいね! (0)
村上 著者:村上

【PHP】画像URLから画像をBase64にエンコードする方法

昨日の記事に引き続き、本日もPHPについて。
今回は、画像URLを Base64 にエンコードする方法です。
…需要があるかは分かりません。

Webページの読み込み時に、画像の表示があまりに遅かったり、そもそも表示できないものがあったので、Base64に変換してしまえば何とかなるのでは?と試してみました。

 

コードはこちらから。

$image_url = [変換したい画像のURL]; 
$entry_image = "";  // Base64に変換後のデータ
if(!empty($image_url) && @file_get_contents($image_url, NULL, NULL, 0, 1)) {
    switch (true) {
        case preg_match('/(\.jpg)$|(\.jpeg)$|(\.JPEG)$|(\.JPG)$/', $image_url):
            $image_type = "image/jpeg";
            break;
        case preg_match('/(\.png)$|(\.PNG)$/', $image_url):
            $image_type = "image/png";
            break;
        case preg_match('/(\.gif)$|(\.GIF)$/', $image_url):
            $image_type = "image/gif";
            break;
        case preg_match('/(\.bmp)$|(\.BMP)$/', $image_url):
            $image_type = "image/bmp";
            break;
        default:
            $image_type = "";
            break;
    }
    if($image_type != ""){
        $img_base64 = base64_encode(file_get_contents($image_url));
        $entry_image = "data:".$image_type.";base64,".$img_base64;
    }
}

3行目で、file_get_contents 関数を使い、画像が実際に存在するかどうかを調べています。
ちなみに、戻り値を全て取得すると時間がかかるので、1文字だけ取得するようにして、高速化を図っています。
そして、Switch文で末尾を確認して、画像の拡張子が何かを判断しています。
22行目では、ファイルデータをBase64にエンコードしています。
エンコードには、PHPの関数の base64_encode を使用しています。
なお、最終的に変換したデータは $entry_image に格納され、もし変換できなかった場合は空文字が格納されます。

 

以上、画像URLから、画像を Base64 にエンコードする方法でした。
これを試したところ、実際画像の表示速度は速くなりましたね。
が、文字数としてはかなり増えたので、若干通信速度が遅くなりました…。
通信速度が画像の表示速度か…どちらを取るかはその時の状況によって対応してください。

  • この記事いいね! (0)