PHPでjsonを読み込み、出力する方法

JSONはJavaScript Object Notationの略で、JavaScriptで書かれたデータ形式です。JavaScriptで書かれているのですが、PHPでも使用できます。

読み込むことも出力することも可能なので、その方法について解説していきます。

JSONとは

JSONの概要は上記の通りですが、問題は具体的にどのような内容になっているのかです。そこで、まずはサンプルを紹介します。

{
  "身長": "170cm",
  "体重": "80kg",
  "足のサイズ": "27cm",
  "服のサイズ": "L~XL"
}

このように、{}で囲み、キーと値をセットで記述しています。JSONと言うとなんとなく大げさで難しそうな感じがしますが、実際のデータ構造は至ってシンプルです。

また、一つのキーに対して複数の値を設定することも可能です。

{
  "身長":
    "160cm",
    "170cm",
    "180cm"
}

JSONを読み込む

JSON形式のデータを取得するには、json_decode関数を使用します。この関数はPHPのコードになります。json_decode関数の構文は以下です。

json_decode ( string $JSON文字列 [, bool $assoc = false [, int $depth = 512 [, int $options = 0 ]]] )

json_decode関数を使用したサンプルコードは以下です。

//配列を作成
$key_value_array = ['key1'=>'value1',
        'key2'=>'value2',
        'key3'=>'value3'
        ];

//配列をJSON形式に変換
$jsonstr = json_encode($key_value_array);

//JSON形式のデータをデコードする
$key_value = json_decode($jsonstr, true);

print_r($key_value);

このコードを実行すると以下のようになります。

Array
(
    [key1] => value1
    [key2] => value2
    [key3] => value3
)

JSON形式だったデータが、普通のPHPの配列に変換されました。

JSON形式に変換して出力する方法

次に、逆にデータをJSON形式に変換して出力する方法です。JSON形式に変換するには、json_encode関数を使用します。

上でJSON形式からPHPの配列形式に変換するにはjson_encode関数を使用すると説明しましたが、PHPの配列形式からJSON形式に変換する際はjson_encode関数を使用します。

json_encode関数の構文は以下です。

string json_encode( $値 [, JSON定数 [, 深さ = 512 ]] )

この構文を使用したサンプルコードは以下です。

<?php
$value_array = ['value1'=>1, 'value2'=>2, 'value3'=>3, 'value4'=>4, 'value5'=>5];

//配列をJSON形式に変換
$jsonstr = json_encode($value_array);
echo $jsonstr;
?>

このコードを実行すると、以下のように出力されます。

{“value1″:1,”value2″:2,”value3″:3,”value4″:4,”value5”:5}

値とキーがセットになっている、JSON形式に変換されました。またこのサンプルコードではキーと値がすべて一列になって出力されましたが、改行を指定して出力することもできます。サンプルコードは以下です。

<?php
$value_array = ['value1'=>1, 'value2'=>2, 'value3'=>3, 'value4'=>4, 'value5'=>5];

//JSON_PRETTY_PRINTを指定して、改行とインデントを指定する
$jsonstr = json_encode($value_array, JSON_PRETTY_PRINT);
print_r($jsonstr);
?>

このコードを実行すると以下のように出力されます。

{
    "value1": 1,
    "value2": 2,
    "value3": 3,
    "value4": 4,
    "value5": 5
}

改行して出力されたので、上のサンプルコードのときよりも見やすくなったかもしれません。

日本語をJSON形式に変換する

JSONはコードの指定ができるので、日本語をJSONに変換することも可能です。そのためにはjson_encode関数の第二引数に「JSON_UNESCAPED_UNICODE」を指定します。

サンプルコードは以下です。

<?php
$value_array = ['あたい1'=>1, 'あたい2'=>2, 'あたい3'=>3, 'あたい4'=>4, 'あたい'=>5];
$jsonstr = json_encode($value_array, JSON_UNESCAPED_UNICODE);
print_r($jsonstr);
?>

このコードを実行すると、以下のように日本語でも出力されます。

{“あたい1″:1,”あたい2″:2,”あたい3″:3,”あたい4″:4,”あたい”:5}

日本語で出力されました。ちなみに、json_encode関数の第二引数を指定しないと以下のようになります。

$value_array = ['あたい1'=>1, 'あたい2'=>2, 'あたい3'=>3, 'あたい4'=>4, 'あたい'=>5];

これを出力した場合が以下です。

{“\u3042\u305f\u30441″:1,”\u3042\u305f\u30442″:2,”\u3042\u305f\u30443″:3,”\u3042\u305f\u30444″:4,”\u3042\u305f\u3044”:5}

JSONはデフォルトではUnicodeに変換される仕様になっているので、日本語をUnicodeに変換した文字列が出力されました。Unicodeだとデータの中身がなんなのかよくわかりません。

JSON形式のデータを送信する

JSON形式への変換、JSON形式からの変換方法について解説してきましたが、最後にJSON形式のデータを送信する方法を紹介します。POSTで送信するサンプルコードは以下です。

//配列を作成
$alphabet_array = ['a'=>'alphabet1',
'b'=>'alphabet2',
'c'=>'alphabet3',
'd'=>'alphabet4',
'e'=>'alphabet5'
];

//配列をJSON形式に変換
$jsonstr = json_encode($alphabet_array);

//セッションを初期化する
$ch = curl_init();

//オプションの設定
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonstr);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, 'http://www.xxx.xxx');

//セッションの実行
$res = curl_exec($ch);

//結果を表示する
var_dump($res);

//セッションを終了する
curl_close($ch);

以上のように、PHPではJSONの読み込み、出力、送信が可能です。

PHPのintval関数で文字列を数値に変換する方法

intval関数は値を整数型に変換する関数です。

基本的なintvalの使い方は下端ですが、少し応用的な使い方やintval関数と同じようなことができるコードもあるので、それらについても紹介していきます。

intval関数で文字列を数値に変換する

まずintval関数の基本構文は以下です。

intval(値[,基数])

この構文を使用したサンプルコードは以下です。

<?php
$num = "12345";
var_dump($num);
echo "<br>";
var_dump(intval($num));
?>

上記のコードを実行すると、以下のようにコンソール出力されます。

string(5) “12345”
int(12345)

もともと数字を文字列として扱っていましたが、intvalで数値に変換して出力しています。その結果、string型からint型に変換されました。このように引数に指定するだけで変換できるのですが、デフォルトだと10進数に変換されるようになっています。

intvalは10進数以外にも変換できる仕様になっており、以下のように指定することが可能です。

<?php
$num = "100";

//指定しない(10進数)
var_dump(intval($num));
//2進数
var_dump(intval($num,2));
//8進数
var_dump(intval($num,8));
//16進数
var_dump(intval($num,16));
?>

上記のコードを実行すると、以下のように出力されます。

int(100)
int(4)
int(64)
int(256)

それぞれの進数に変換されました。普通は10進数以外使用しないかもしれませんが、一応仕様上可能なことは知っておくと良いでしょう。

intval関数が使用できない例

intval関数は文字列を数値に変換できるということでしたが、文字列に数字以外が入っている場合変換できません。以下のサンプルコードのようになります。

<?php
$str = "あいうえお";

var_dump(intval($str));
?>

この場合出力結果は以下のようになります。

int(0)

数字以外の文字は数値に変換することができないので、0が返ってくる仕様になっています。また、文字列が空の場合も同様になります。一応サンプルコードを紹介しておくと、以下のようになります。

<?php
$str = "";

var_dump(intval($str));
?>

この場合も、上と同様に0が返ってきます。ただし型自体はintに変換されるので、値こそなくなっていますが、型の変換にはある意味成功しています。

intval関数は配列で使うと独特な動きをする

intval関数は基本的に配列にも使用できません。使用すると、以下のように独特な仕様で値を返します。

<?php
$nums = ["1","2"];
$ary = [];

var_dump(intval($nums));//要素がある場合
var_dump(intval($ary));//要素がない場合
?>

このコードを実行すると、以下のように出力されます。

int(1)
int(0)

まず配列に要素が入っている場合、中身に関係なく「1」が返ってきます。逆に配列が空の場合、「0」が返ってきます。

booleanにも使えない

intval関数はbooleanにも使用できません。使用すると以下のようになります。

<?php
var_dump(intval(true));
var_dump(intval(false));
?>

これを実行すると以下のようになります。

int(1)
int(0)

trueなら1、falseなら0を返しています。このように一応trueとfalseの判定に使えなくもないのですが、あまりintval関数でbooleanの判定を行うことはないでしょう。

小数点以下の切り捨てに使える

intval関数は整数に変換する関数です。なので文字列を数値にするだけでなく、小数点以下を含む数値を整数に変換する目的で使用されることもあります。サンプルコードは以下です。

<?php
$num = 3.14159265359;

var_dump(intval($num));
?>

これを実行すると「3」が出力されます。小数点以下が切り捨てられました。ちなみについでですが、符号が付いている場合も問題なく変換できます。サンプルコードは以下です。

<?php
$max_num = "+20";
$min_num = "-20";

var_dump(intval($max_num));
var_dump(intval($min_num));
?>

このコードを実行すると、以下のように出力されます。

int(20)
int(-20)

+の場合符号は省略されますが、-の場合そのまま残っています。いずれにしても、意図している形に変換されているかと思います。

キャストを使って文字列を整数に変換する

intval関数を使用せず、キャストによって文字列を整数に変換することも可能です。キャストの基本構文は以下です。

(int)値

サンプルコードは以下です。

<?php
$num = "12345";
var_dump($num);
echo "<br>";
var_dump((int)$num);
?>

このコードを実行すると以下のように出力されます。

string(5) “12345”
int(12345)

intval関数を使用したときと同じように、型が変換されています。どちらを使っても同じなのですが、あえて違いを上げるとすればintval関数は基数を指定できます。

他には、上でも説明した通り数値以外を指定した際に0などが戻ってくる仕様になっています。この辺はキャストにはない仕様です。単純に10進数に変換する以外の機能を使いたい場合はintval関数を使った方が良いかもしれませんが、10進数に変換するだけなら普通にキャストした方がコードも短くシンプルなので良いかと思います。

条件判定を行ってから変換処理を行う

文字列に含まれている文字が数字だけの場合のみ変換処理を行う、といったコードが一般的です。サンプルコードは以下のようになります。

<?php
$num = "123a";

if(is_numeric($num)){
    echo intval($num);
}else{
    echo "変換できません";
}
?>

上記のコードを実行すると、「変換できません」と出力されます。if文の中でis_numeric関数を使用していますが、この関数は文字列の中に数値以外が含まれていないかどうかをチェックする関数です。

文字列が数字だけで構成されている場合はtrueを、数字以外の文字が含まれている場合はfalseを返します。上のサンプルコードではaが含まれているので、falseを返します。

falseを返したのでif文は実行されず、そのままelse文が実行されます。その結果、「変換できません」と出力されました。このように、条件設定して条件に合致する場合のみ整数型に変換すると設計上安全です。

以上、intval関数で文字列を数字に変換する方法、キャストを使う方法について紹介しました。intval関数は一応booleanの判定などにも使えますが、メインの用途ではないため、コードの可読性を考えてもメインの用途以外には使用しない方が良いでしょう。

PHPでアクセスのあるページのURLを取得する

PHPはWebサイトの画面作成、クライアントサイドの処理実装、サーバーサイドの処理実装、どれをとっても利便性の高い言語です。そして、クライアントとサーバーの間の処理を自由に扱える点も魅力です。

その中の簡単な機能の一つが現在アクセスしているページURLの取得です。

$_SERVERで現在のURLを取得する

$_SERVERではスーパーグローバル変数と呼ばれるもので、ここにアクセスすると現在アクセスのあるURLを取得できます。

具体的なコードは以下です。

$_SERVER['REQUEST_URI']

REQUEST_URIは、$_SERVERの中のURLが存在する場所です。ホスト名を取得したい場合、以下のようにHTTP_HOSTを指定します。

$_SERVER['HTTP_HOST']

URLを取得したい場合はREQUEST_URIを指定し、ホストを取得したい場合はHTTP_HOSTを指定します。

HTTP or HTTPSの判定

ここ数年はGoogleの検索エンジンでもSSL化が重要視されており、HTTPでのアクセスかHTTPSでのアクセスかを判定する機会は増えています。ブログ運営者などは、特にHTTPとHTTPSを意識する機会は多いでしょう。

ブログ運営の場合ツールで自動的に判別できるのですが、Webサイト制作においてはコードでも把握しておいた方が良いでしょう。と言っても判別方法は極めて簡単で、$_SERVER の’HTTPS’にアクセスするだけです。サンプルコードは以下です。

echo $_SERVER['HTTPS'];

このコードを実行すると、「on」と出力されます。つまり、HTTPSでのアクセスを意味しています。HTTPでアクセスした場合、NULLになります。またonとNULLで判別するのではなく、以下のようにあらかじめ出力コードを決めておくことも可能です。

echo (empty($_SERVER['HTTPS']) ? 'http://' : 'https://')

これを実行すると、「’https://’」となります。現在のURLを取得するコードは以下です。

echo (empty($_SERVER['HTTPS']) ? 'http://' : 'https://') . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

index.phpという名称のファイルで編集していた場合、出力結果は以下になります。

‘http://localhost/index.php’

クエリ文字の処理

クエリ文字列とは、WebブラウザなどがWebサーバーに送信するデータをURLの末尾に特定の形式で表記したものです。クライアントからサーバーにパラメーターを渡す際に付いている表記になります。

より具体的には、URLを後ろの方に付いている?の後ろにid等が付いているものです。厳密にはクエリ文字には二種類あり、「パッシブパラメーター」と「アクティブパラメーター」の二種類です。

まずパッシブパラメーターは表示されるコンテンツには影響を与えないクエリ文字で、目的はWebサイトのアクセス解析のみです。パッシブパラメーターを見ることで、ユーザーがどこからWebサイトを訪問したのかわかります。

特にWebサイトを収益化する際に使用します。次にアクティブパラメーターですが、これは表示されるコンテンツにも影響を与えるクエリ文字です。ECサイトの並べ替えやフィルタリングなどの機能がその代表例です。

ECサイトを利用したことのある人は多いかと思いますが、もしかするとURLまでは見ていないかもしれません。並べ替えやフィルタリングにアクティブパラメーターが使われていることにピンと来ない方は、ぜひ今度並べ替えやフィルタリングを行ったときのURLをチェックしてみてください。

ページ自体は変わっていないにも関わらず、URLの後半部分が変化しているはずです。ページ自体は変わっていないのに、ページの動的な動きに合わせて変化するのがアクティブパラメーターの役割です。

クエリ文字の説明が長くなりましたが、このクエリ文字に処理を加えてURLを取得することが可能です。サンプルコードは以下です。

// 最後のクエリ文字も表示させる($_SERVER['REQUEST_URI'])
echo (empty($_SERVER['HTTPS']) ? 'http://' : 'https://').$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];

// 最後のクエリ文字は表示させない($_SERVER['SCRIPT_NAME'])
echo (empty($_SERVER['HTTPS']) ? 'http://' : 'https://').$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'];

アドレスは適当に記載していますが、このように?id以降があるかないかで変わってきます。

http://www.○○.com/url-○○?id=○○
http://www.○○.com/url-○○

またURL自体は取得せず、クエリ文字のみを取得することも可能です。

echo $_SERVER['QUERY_STRING'];

このコードの結果、「id=○○」のようにクエリ文字のみが取得できます。また、以下のようにクエリ文字を含めたURLを定数に固定することもできます。

// 「URL」という定数名で定義する
define (URL, (empty($_SERVER['HTTPS']) ? 'http://' : 'https://').$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);

その他のサーバー変数

「$_SERVER[‘REQUEST_URI’]」と「$_SERVER[‘HTTP_HOST’]」を紹介しましたが、これ以外にもサーバー変数はいろいろあります。使用機会があるかもしれないので、有名どころを紹介しておきます。

$_SERVER['SERVER_NAME']
現在のサーバーのホスト名

$_SERVER['REQUEST_METHOD']
現在のページにアクセスする際に使用されたメソッド
(POST,GETなど)

$_SERVER['DOCUMENT_ROOT']
現在実行されているスクリプトのドキュメントルートディレクトリ

$_SERVER['SCRIPT_FILENAME']
現在実行されているスクリプトの絶対パス

$_SERVER['SCRIPT_NAME']
現在実行されているスクリプトのパス

$_SERVER['SERVER_PROTOCOL']
ページがリクエストされた際のプロトコル名/バージョン

$_SERVER['QUERY_STRING']
ページがリクエストされた際に検索引数があれば、その値

$_SERVER['PHP_SELF']
現在実行されているスクリプトのファイル名

$_SERVER['REMOTE_ADDR']
訪問したユーザーのIPアドレス

$_SERVER['REMOTE_PORT']
webサーバの通信に使用されているポート番号

他にも数多いのですべては紹介しませんが、だいたいどのような変数が取得できるのかイメージは付くかと思います。PHPでWebサイトを構築する際には使用することもあるので、きっちり覚えるというよりはざっくり把握しておいてください。

PHPのinstanceofでclassの比較判定を行う方法

オブジェクトの元のクラスを判定し、判定結果に応じて処理を切り替えるようなことがあります。

こういったロジックで活躍するのがinstanceofです。instanceofはオブジェクトとクラスの間に記述し、それによって前後のオブジェクトとクラスが一致しているかどうかを判定できます。

instanceof で判定を行う

さっそくinstanceof を使用したサンプルコードです。

<?php
class Foo {}
class Bar {}

function sample($obj){
    if($obj instanceof Foo){
        return "foo";
    } else if($obj instanceof Bar){
        return "bar";
    } else {
        return "";
    }
}

$foo = new Foo();
$bar = new Bar();
echo sample($bar);

このコードを実行すると、以下のように出力されます。

bar

$fooを渡した場合はfooが、$barを渡した場合barが入る仕様になっています。instanceofでオブジェクトとクラスを比較し、if文とelse if文で分岐させています。

ちなみにinstanceofはオブジェクトだけに使えるものなので、他の変数などの判定に使用することはできません。上記のコードではクラスオブジェクトとクラスを比較しましたが、クラスオブジェクト同士を比較したり、クラスを代入した変数と比較することもできます。

instanceofは変数には使用できないということでしたが、クラスが格納されている場合は例外です。サンプルコードは以下になります。

$bar1 = new Bar();
$bar2 = new Bar();

var_dump($bar1 instanceof $bar2); // TRUE

$str = 'Bar';
var_dump($bar1 instanceof $str); // TRUE

また少し応用的な使い方として、そのクラスオブジェクトがインターフェイスを実装しているかどうか判定することもできます。サンプルコードは以下です。

<?php
interface SampleInterface {}
class Foo implements SampleInterface{}

$foo = new Foo();
var_dump( $foo instanceof SampleInterface ); // TRUE

まずインターフェイスを宣言し、それを実装したクラスを宣言します。クラスオブジェクトを作成し、そのオブジェクトがインターフェイスを実装しているかどうかをinstanceofで判定しています。

その他の型チェック

instanceofでクラスオブジェクトを判定するだけでなく、その他のデータ型などのチェックが必要なケースもあるかもしれません。せっかくなので、その他の型チェックコードも紹介しておきます。

gettype()でプリミティブ型・組み込み型のデータ型の判定

gettype()を使用すると、引数の型を判定することができます。instanceofのように比較するものではありませんが、変数の型を調べるときなどに使用するかもしれません。基本となる使い方は以下です。

gettype(123456789);
// => 'integer'
gettype('abcdefghijklmn');
// => 'string'

この例では数値と文字列を直接格納していますが、もちろん変数に格納してから引数に変数を指定することも可能です。gettypeは引数がどの型かを文字列で返す関数ですが、特定の型かどうかをチェックして、戻り値にtrueかfalseを返す関数も複数用意されています。

具体的には以下のようなものです。is_scalar()、is_string()、is_numeric()、is_bool()、is_array()、is_null()、などがあります。

get_class()でオブジェクトの型をチェックする

get_classはinstanceofによく似た関数です。どちらもオブジェクトに対して使用する点では共通していますが、instanceofが比較に使用するのに対し、get_classはどのオブジェクト型かを文字列で返すという点に違いがあります。

サンプルコードは以下です。

$d = new DateTime();
get_class($d);
// => 'DateTime'

$zip = new ZipArchive();
get_class($zip);
// => 'ZipArchive'

それぞれオブジェクトを作成し、get_classで判定しています。そうすると、もとのクラスが文字列で返されました。

is_a()で親クラスも含めたクラス、インスタンスをチェックする

is_aはget_classよりもinstanceofによく似た関数です。サンプルコードは以下です。

class Dog {
}
$d = new Dog();
is_a($d, Dog);
// => true

class SpecialDog extends Dog {
}
$d = new SpecialDog();
is_a($d, Dog);
// => true

instanceofはオブジェクトとクラスをinstanceofの前後に記述しましたが、is_aはそれぞれ第一引数と第二引数に指定します。またクラスオブジェクトをクラスと対比させた際に一致すればtrueとなりますが、親クラスと対比させた場合も一致すればtrueとなります。

上の例だとDog→SpecialDog→dとそれぞれクラスとオブジェクトがありますが、この場合dはDogに対してもSpecialDogに対してもis_aを使えばtrueとなります。

method_exists()でメソッドがあるかどうかをチェックする

少しオブジェクトやクラスの話とは異なりますが、使い方が似たものとしてメソッドの存在チェックができるmethod_exists()があります。サンプルコードは以下です。

class Dog {
    public function bow() {
    }
    private function bowwow() {
    }
}

$d = new Dog();
method_exists($d, 'bow');
// => true

method_exists($d, 'bowwow');
// => true

第一引数がオブジェクト、第二引数がメソッドです。第一引数で指定したクラスオブジェクトのクラス内に第二引数で指定したメソッドが含まれていればtrueを返し、そうでない場合falseを返します。

またアクセス修飾子がpublicでもprivateでも同様に機能します。また、メソッドではなくクラス内にプロパティが存在するかどうかをチェックする場合property_exists()を使用します。引数の使い方はまったく同じです。

ReflectionMethodでメソッドのアクセス修飾子をチェック

最後に、メソッドのアクセス修飾子をチェックすることもできます。サンプルコードは以下です。

class Dog {
    protected function bowwow() {
    }
}

$check = new ReflectionMethod(Dog, 'bowwow');
$check->isPublic(); // => false
$check->isProtected(); // => true
$check->isPrivate(); // => false

ReflectionMethodのオブジェクトを生成し、それぞれ修飾子をチェックしています。一致するとtrue、一致しない場合falseを返します。

以上、クラスオブジェクトとクラスの比較や、それに類似する判定、比較方法について紹介しました。

【SEで月100万は現実的か?】フリーランスエンジニアの仕事と市場について、最前線にいる人に聞いてみた

こんにちは!シノブ(https://twitter.com/sidelines_tw)です。

最近Twitterでよく見かけるタグの中に、こんなタグがあるんですよ。

#駆け出しエンジニアと繋がりたい

このタグは、プログラミング未経験の方が
ゼロからプログラミングの学習を始めたり、
将来的にプログラマーやSEとして仕事をしたい人が
同じ考えを持って頑張っている仲間を探すのに使われています。

かくいう僕も、最近HTMLの勉強をイチから始めました。
今までWordPressをすこーしだけいじったりはしていたんですが、
自分で出来ることを増やしたいと思いまして、現在勉強中です。
2019年には自分で何か1つサービスを作ることを目標にしています。

小学校でもプログラミングが必修科目として組み込まれ、
社会人の方でもゼロからプログラミングを勉強している方が増えたように思います。
Twitterではこの「#駆け出しエンジニアと繋がりたい」というタグを
見かけることもかなり増えてきました。

そこで今回は、未経験の人がゼロからプログラミング学習を始めて
実際に1人でフリーランスとして生きていくためには
どんなことをしていけば良いのかを、
現役のSES会社の営業マンの佐藤さんと、事業部長の薄さんにお話を聞いてみました。

プログラマー人材市場は現在も活況

シノブ
シノブ
今日はよろしくお願い致します!アルマサーチではフリーランスエンジニアの方の就業支援を行っていらっしゃるんですよね。エンジニアさん達のお仕事の前線にいらっしゃるおふたりから見て、フリーランスエンジニアの需要というのはどう感じられてますか?
需要は依然として高いです。
ですが一昔前の、ソーシャルゲームが流行ってた5年前くらいの時が1番ピークだったように感じます。それに比べたら今は少なくなっている。マクロ的には需要は高まっているけど、この10年間で転職市場も成熟してきたことを感じます。需要がある一方で求められるものも高まっていますね。未経験者や年齢の高いエンジニアの方が断られるケースも増えてきました。以前はあまりそういうケースはありませんでした。
薄
シノブ
シノブ
なるほど。活況ではあるけど求められているラインも高くなっているんですね。

フリーランスエンジニアの仕事は数・幅ともに広がっている?

薄
結論としては、確かなスキルと人間性を持っているエンジニアは雇用形態にかかわらず引く手あまたです。

ただ時代の流れもあって、エンジニアの世界に労働時間や働き方を是正するような仕組みが入ってきました。それによって労働環境の苛烈さは無くなってきたけど、フリーランスなのに正社員っぽい仕事が多くなったなとは感じます。

少し前なら精算幅の中での稼働なら何も言われることは無かったのですが、そこが厳しく管理されるようになりました。また、大手ゲーム会社ではそもそも業務委託を禁止したりしはじめています。

Webアプリは比較的少ない人数で作れてしまうということもあり、人気の無い企業ほどフリーランスを使うことから離れられない。フリーランスの需要は増えていくけど・・・確かなスキルを持っている人は引く手あまた。そうじゃないとなくなる。そこは市場うんぬんではないです。そしてこの状況は加速しています。需要が個別化されてきている=人による。昔は誰でもOKみたいな時期がありました。そのころはあまり人間性を気にされなかったですね。

佐藤
佐藤
薄
実際、優秀な人材は大手企業や体力のある企業に囲われがちというのが現状です。優秀な人を採用したい企業は、表面的な採用活動はもちろんですが、水面下でエンジニアと繋がりを持てるような活動や、リファラルなネットワーク構築が重要だと思います。

言語はRubyとUnity、Swift、PHPが多い

シノブ
シノブ
こんな質問は野暮かもしれませんが、フリーランスエンジニアの転職市場で引き合いの多い言語というのはどんな言語でしょうか?
今はRuby、Unity(C#)、Swift、Android、それらからはちょっと下がってPHPですかね。これはフリーランスという括りじゃなくても同じかなと思います。
佐藤
佐藤
シノブ
シノブ
そうなんですね。ありがとうございます。よく聞く言語の中だと、Pythonが挙がらなかったのがちょっと意外に感じるんですが、Python自体はどうなんでしょう?
PythonはAI・人口知能の分野では確かに使われています。ただ、AIや人工知能を扱う企業というのは、ビッグデータを扱える企業に限られるんですよね。AIが効果的に機能するほどのビッグデータを簡単に集められる企業というのがそもそも少なくて、国内の転職市場での盛り上がりとしては今ひとつというのが現状ですね。
薄
シノブ
シノブ
なるほど。非常に納得感のあるお話ですね。

フリーランスエンジニアで月収100万は目指せる?

薄
目指せます。ルートとしてはスペシャリストかゼネラリストの道ですね。エンジニアとしてのスキルだけで目指せるのは一部の人です。これから目指す人という観点では、イメージとしては「営業できて、プログラムかけて、PMできる」みたいないわゆるフルスタックを目指すと良いと思います。
例えば弊社経由でフリーランスで入った人だと、某SNSに入ったエンジニアさんで月115万の人がいます。その人はプログラミングも出来るしWebマーケティングも出来る、そして分析のスペシャリストですね。
佐藤
佐藤
シノブ
シノブ
すごい。しっかりと自分のスキルや仕事っぷりと向き合える人であれば、目指せるわけですね。

例えば経験2年のRubyエンジニアの平均単価は?

シノブ
シノブ
フリーランスエンジニアで月収100万円が目指せるというのは理解できました。一方で、これからフリーランスを目指す20代の目線で見るとどうでしょう?例えば経験2年のRubyのエンジニアさんがフリーランスになるとしたら?
本人の手取りで65~70万くらいですかね。他の言語ができればもっと上がります。言語のキャリアと、エンジニアとしてのキャリアと、ビジネスのキャリアってイコールでは考えられないんですよね。例えばですけど「東大出身・高学歴」みたいな方だったら経験1年とかでも出る可能性もあります。エンジニアとしてのスキルに加えて、自頭の良さやポテンシャルも加味すると多少幅が出てくる、という意味です。
薄
シノブ
シノブ
なるほど。その幅はフリーランスエンジニアに限らず、転職市場としても十分考えられる話ですね。

未経験のエンジニアが1年でフリーランスエンジニアになるには

薄
言語は何でも良いからとにかく使えるようになること。あとは強みを活かして欲しいですね。1年で身につくエンジニアとしての経験って、やっぱり限界があると思うんです。だからこそ、これまでの自分に身についている強みを活かして、「エンジニア」×「何か」っていう掛け算で考えられれば、フリーランスでも行ける可能性は十分にあります。
未経験とか経験1年っていうのは、数字の上ではやはり選考から外されがちです。なので数字で勝負せずに成果物で勝負できれば、可能性は広がると思います。自分で作ったアプリや、GitHubのソースとかがあると分かりやすい。仕事が決まりやすいエンジニアはみんなポートフォリオを自分で作っていますね。

あとはスキルシートの書き方で大体わかっちゃうんですよね。エンジニアとしての経験が豊富な人や、業界経験の長い営業に書き方を教えてもらったほうが確実に選考が通る確率が上がります。

佐藤
佐藤
シノブ
シノブ
なるほど。経験年数という数字で判断されないような見せ方も大事ということですね。

フリーランスになって在宅案件だけで仕事することって実際に可能?

シノブ
シノブ
フリーランスっていう言葉と並行して、在宅っていう言葉も耳にすることが多くなりましたが、フリーランスエンジニアで在宅の案件というのはあるのでしょうか?
在宅の案件は実際はほぼ無いです。正しく言うと、表面化してくることは少ないです。現実としては存在するんですが、企業とフリーランスの間の信頼関係が十分に構築されているという前提が絶対に必要です。例えば常駐で数年やっていた人、とか。
薄
シノブ
シノブ
先程おっしゃっていた労務的な観点でも、新規の契約では難しそうですね。

フリーランスエンジニアの方って何才くらいまで市場で需要あるの?

シノブ
シノブ
フリーランスという仕事の仕方を考えた時に、頭にちらつくものの1つが年齢なんですけど、市場の需要ってどうなんでしょう?
私は最高で64歳のフリーランスエンジニアに会ったことあります。知り合いとか商工会議所とかの仕事をもらったりして仕事をしているようでしたね。

年齢とともにエンジニアとしての需要が下がるのは間違いないですが、そこは先ほど事業部長が言っていた「掛け算」次第で、仕事は続けていけると感じています。

佐藤
佐藤

フリーランスエンジニアになって、地方での仕事ってどんな感じ?

シノブ
シノブ
最後に、フリーランスエンジニアとして地方で仕事をしようと思った場合、可能性はあるんでしょうか。
無くはないですね。例えば塾の教室管理のシステム開発とか。ビルの管理・メンテナンスとかですかね。主要都市にはそういった案件はあります。ただ、SESでは基本無いですね。仕事を受けるという点では、個人の営業力がより大切になってくると思います。仕事の幅も広いので、スペシャリストよりはゼネラリストの方がフリーランスとして仕事を受けられる可能性は高いと思います。
薄
シノブ
シノブ
なるほど。非常に勉強になりました!今日はありがとうございました!

新御茶ノ水でエンジニアランチに行ってきました!

牛カルビつけダレアップ

現在、新御茶ノ水のお客様先に就業しているエンジニアの方とランチに行ってきました!

以前一緒に行って、めちゃくちゃ美味しかった店でのランチなので、いやがおうにも期待は高まります!

ヒロ

集合場所はJR新御茶ノ水駅の改札

新御茶ノ水駅

まずは新御茶ノ水駅の改札前で待ち合わせ。

そんなに広くないのですぐに合流することができました。

新御茶ノ水の街並み

町並みを一緒に歩いていきます。

表通りに食事処が少ない印象です。
(と言いながら写真に大戸屋が見切れてますけど笑)

新御茶ノ水の表通り

少し進むとこんな交差点。

見た目からしてオフィス街という感じ。

路地裏に回らないと食事処にたどり着けません。

新御茶ノ水の裏道

ようやく遠くに目指すお店(↑)が見えてきました。

右奥の方なのですが、見えますか?

お店に到着

白銀屋の店前

炭火焼専門食処 白銀屋 大手町分店

ということで到着しました。

白銀屋(しろがねや)の大手町分店です。新御茶ノ水駅から歩いてきましたが、すでに大手町寄りなのですね。駅と駅が近いというのもありますけど。

お昼は写真のように表に行列ができるくらい人気のお店です。

白銀屋 入口

入り口から奥を見てみました。お客さんでひしめき合っていますね。

お会計をしてから入店するというシステムなので、並んでいる間にメニューを見て注文を決めておく必要があります。

白銀屋メニュー

これがメニュー表(↑)

このお店のオススメは圧倒的に魚料理!店内で炭火で調理してくれます。

前回あhサーモンのハラスを食して大満足したので、今回は牛カルビを食べてみることに。(魚じゃないんかい!)

一緒にきたエンジニアさんも全く同じメニューを頼まれたので、写真はこのカルビのみ・・・。(本当は別メニューにしたほうが絵面的には良かったんでしょうけど、すみません!)

牛カルビつけダレ

見てくださいこのボリューム感!

切り分け用のハサミも一緒についてきます。

この肉厚感もすごい!

牛カルビつけダレアップ

ということで、今回は魚が名物の白銀屋で、あえての肉を食べてみました。

そしてその結果、非常に満足でした!ただ、やはり魚のほうがより美味しいと思えたので、次回はまた白銀屋で魚料理を頼んでご紹介したいと思います!

 

【エンジニアランチシリーズ】
1, 国際展示場駅へエンジニアとランチに行ってきました!
2, 虎ノ門駅へエンジニアとランチに行ってきました!
3, 田町駅周辺でエンジニアさんとランチに行ってきました!
4, 天王洲アイル駅でエンジニアさんとランチしてきました!
5, 新宿でエンジニアさんとランチしてきました!
6, 恵比寿でエンジニアランチに行ってきました!
7, (この記事) 新御茶ノ水でエンジニアランチに行ってきました!

アルマシャチ
アルマシャチ
アルマサーチに登録して就業した方には、SES歴10年以上のプロの営業が毎月ランチでヒアリングを行います

アルマサーチに相談するボタン

【SES営業シリーズ】
1, SESとは?
2, SES営業の流れとコツ
3, SESの精算幅って何?
4, 派遣契約と業務委託契約の違い

PHPでデータベースからCSVをダウンロードしよう

PHPでデータベースからCSVをダウンロードしよう

PHPでデータベースからCSVをダウンロードしよう

PHPにはCSVのダウンロードや出力を簡単にするための関数が用意されています。

header関数を使用する

PHPでCSVファイルをダウンロードするには、header関数を使うのが簡単です。header関数を使えばCSVファイル以外にも、いろいろな種類のファイルをダウンロードすることが可能になります。

header関数の基本的な構文は以下です。

header ($ヘッダ文字列[, $同じ名前のヘッダが指定された時に値を置換するかどうか[, $レスポンスコード]] )

まず第一引数はヘッダ文字列です。第二引数は値を置き換えるかどうかの指定を行います。第三引数はHTTPレスポンスコードを強制的に指定したい場合に使用します。

header関数の使い方は上記の通りですが、そもそもHTTPヘッダが何かという疑問が残るかもしれません。HTTPヘッダとは、データ本体から独立してブラウザやデータに関する情報を記録したものです。

具体的には、クライアント端末がサーバーにアクセスした際に、サーバーからどのようなコンテンツを返すのかを記録しているようなことです。そして、HTTPヘッダには三種類あります。

「Content-Type」「Content-Length」「Content-Disposition」の三つです。

まず一つ目のContent-Typeはダウンロードするファイルのタイプのことです。指定の仕方は簡単で、PHFなら「Content-Type: application/pdf」、JPEGなら「Content-Type: application/jpg」、CSVなら「Content-Type: application/octet-stream」となります。

CSVだけCSVと入っていないのでややこしいのですが、「octet-stream」はファイルタイプを指定しないという意味です。つまり、デフォルトでCSVになっています。

二つ目のContent-Lengthはダウンロードするファイルサイズを指定するものです。

三つ目のContent-Dispositionはファイルの処理方法を指定するもので、「Content-Disposition: attachment; filename=ファイル名」の形式になっています。

これらのHTTPヘッダを把握したうえであれば、headerの引数を指定しやすいでしょう。以上を踏まえたサンプルコードは以下です。

<?php
// ダウンロードするサーバのファイルパス
$filepath = 'sample.csv';
// HTTPヘッダを設定
header('Content-Type: application/octet-stream');
header('Content-Length: '.filesize($filepath));
header('Content-Disposition: attachment; filename=file.csv');
// ファイル出力
readfile($filepath);
?>

上での説明通り、Content-TypeはContent-Type: application/octet-streamとCSVになるようにしています。Content-Lengthはfilesize($filepath)となっていますが、これはfilesize関数を$filepathを引数にして使用しています。

Content-Dispositionはファイル名がfile.csvとなっています。その結果、file.csvという名前でダウンロードされます。

複数のファイルを圧縮してダウンロードする

上の例では単一のファイルを圧縮なしでダウンロードしましたが、次はより効率的にCSVファイルをダウンロードしていく方法です。サンプルコードは以下です。

<?php
// ZipArchiveクラス初期化
$zip = new ZipArchive();

// Zipファイルパス
$zipFilepath = './sample.zip';

// Zipファイルオープン
$zip->open($zipFilepath, ZIPARCHIVE::CREATE);

// ファイル追加
$zip->addFile('csv1.csv');
$zip->addFile('csv2.csv');
$zip->addFile('csv3.csv');

// Zipファイルクローズ
$zip->close();

// HTTPヘッダを設定
header('Content-Type: application/zip');
header('Content-Length: '.filesize($zipFilepath));
header('Content-Disposition: attachment; filename=images.zip');

// ファイル出力
readfile($zipFilepath);

// Zipファイル削除
unlink($zipFilepath);
?>

まずZipArchiveはもともとPHPで用意されているクラスで、これを使用することでZipファイルを使用できます。クラスメソッドを作り、次にファイルパスを取得しています。

ファイルを開く際にはopenメソッドを使用し、引数にファイルパスとそれをZipにすることを指定しています。addFileメソッドではzipにしたいファイルを追加しています。

zipにするファイルを指定し終わったので、次にcloseします。次に上で説明した方法でHTTPヘッダを設定しています。Content-Typeではzipを指定しています。出力後はzipファイルを削除します。

CSVファイルの出力

CSVファイルのダウンロードについて解説しましたが、出力することも可能です。もっとも簡単な方法は、fputcsv関数を使用する方法でしょう。fputcsv関数は以下のような構文になっています。

int fputcsv ( $ファイルポインタ , array $書き込む値の配列 [, string $区切り文字 = "," [, string $フィールド囲み文字 = '"' [, string $エスケープ文字 = "\" ]]] )

これを使ったサンプルコードは以下です。

<?php
$data = [
    ['ID', '名前', '型番'],
    ['1', 'x', '30'],
    ['2', 'y', '26'],
    ['3', 'z', '32']
];

$fp = fopen('member.csv', 'w');

foreach ($data as $line) {
    fputcsv($fp, $line);
}

fclose($fp);
?>

このコードを実行すると以下のようになります。

ID,名前,型番
1,x,30
2,y,26
3,z,32

fopen関数の第二引数wは書き込みモードを意味しています。書き込みモードでファイルを開き、行数分出力し、最後にファイルをクローズしています。

まとめ

以上、PHPでCSVをダウンロードする方法と出力する方法を紹介しました。

もともと用意されているコードを使用すれば自分で新たに何か生み出すようなコーディングは不要で、関数の仕様通りに引数を指定していくだけです。

ちなみに読み込みでもだいたい同じようなコードになります。

PHPでのend関数の使い方

PHPでのend関数の使い方

PHPでのend関数の使い方

end関数とは、配列の最後の値を取得するための関数です。

使用目的としては、単純に配列の最後の値を知りたい場合や、最後の値を読み込んだタイミングで別の処理に移行するような際に使用します。

end関数の使い方

end関数の構文は非常にシンプルで、以下のようになります。

end($配列名)

引数に配列名を指定すれば関数が機能します。サンプルコードは以下です。

<?php
$coutries = ['America', 'Brazil', 'Canada', 'Dominica', 'Ecuador', 'France'];
//end関数を使用して配列の最後の要素を取得する
$countries_end = end($coutries);
echo.$countries_end;
?>

上記のコードを実行すると、「France」と出力されます。見たまんまかと思いますが、配列の一番後ろの要素が取得されました。

ついでですが、同様にreset関数を使用すると配列の先頭の要素を取得できます。サンプルコードは以下です。

$countries = ['America', 'Brazil', 'Canada', 'Dominica', 'Ecuador', 'France'];
//resetを使用して先頭の要素を取得する
$value = reset($countries);

foreach文で配列の最後の要素を取得する

foreach文では、end関数を使用するのと同様に配列の最後の要素を取得できます。

詳細は後から解説しますが、まずはサンプルコードを見てみます。

<?php
$countries = ['America', 'Brazil', 'Canada', 'Dominica', 'Ecuador', 'France'];
$i = 1;
foreach($countries as $value){
    if (count($countries) == $i){
        echo '最後の値:'.$countries[$i-1];
    }
    $i++;
}
?>

上記のコードを実行すると、「最後の値:France」と出力されます。

ただしこのコードを理解するためにはそもそもforeachの使い方を知っている必要があるので、foreachの使い方について解説します。

foreachについて

foreach文は配列の繰り返し処理に付けるコードで、構文は以下のようになります。

foreach ($配列 as $value){
    処理
}

これがもっとも基本的なforeachの構文です。またforeach文は連想配列のキーと値を指定することも可能で、その場合以下のようになります。

foreach ($配列 as $key => $value){
    処理
}

上記構文を使用したサンプルコードは以下です。

$countries = ['America', 'Brazil', 'Canada', 'Dominica', 'Ecuador', 'France'];
foreach($countries as $value){
    echo $value.'<br>';
}

このコードを実行すると、以下のような出力結果になります。

America
Brazil
Canada
Dominica
Ecuador
France

一応for文と対比させるためにfor文で記述してみると、以下のようになります。

$countries = ['America', 'Brazil', 'Canada', 'Dominica', 'Ecuador', 'France'];
for ($i = 0 ; $i < count($countries); $i++) {
    echo $countries[$i].'<br>';
}

ループ処理ではfor文を使用する方が一般的で、他のプログラミング言語の経験者の場合配列を扱う場合にも普通にfor文を使用していたかもしれません。しかしPHPでは配列でループ処理を行う場合foreachで実装した方がシンプルです。

foreachに慣れないうちは多少書きにくさを感じるかもしれませんが、見ての通りそれほど難しい構造にはなっていません。むしろfor文で書くよりも指定が少なくミスが少ないので、PHPで配列をループで回すならforeachを使用する方がおすすめです。

array_pop関数で配列の最後の要素を取り除く

上では配列の最後の要素を取得する方法を紹介しましたが、配列の最後の要素を取り除くことも可能です。使用する関数はarray_pop関数です。構文は以下になります。

array_pop(削除対象の配列名)

引数で配列を指定するだけなので書き方はシンプルです。次にarray_pop関数を使ったサンプルコードになります。

$countries = ['America', 'Brazil', 'Canada', 'Dominica', 'Ecuador', 'France'];
//配列末尾の値を削除する
array_pop($countries);
print_r($countries);

実行すると以下のように出力されます。

Array
(
[0] => America
[1] =>Brazil
[2] => Canada
[3] => Dominica
[4] => Ecuador
)

配列の最後の要素の文字を消す

array_pop関数は配列の最後の要素を削除する関数ですが、文字のみを削除することも可能です。具体的にはrtrim関数を使用します。rtrim関数は指定した文字列の最後の文字を取り除く関数です。構文は以下のようになります。

rtrim ( $文字列 [, $取り除く文字 ] )

rtrim関数を使用したサンプルコードは以下です。

<?php
$countries = ['America', 'Brazil', 'Canada', 'Dominica', 'Ecuador', 'France'];
$i = 0;
foreach($coutries as $value){
    $coutries_str = $coutries_str.$coutries[$i];
    $i++;
}
echo "カンマ除去前:".$coutries_str;
//カンマを取り除く
$coutries_str = rtrim($coutries_str, ',');
echo '<br>';
echo "カンマ除去後:".$coutries_str;
?>

このコードを実行した出力結果は以下です。

カンマ除去前:America,Brazil,Canada,dominica,Ecuador,France,
カンマ除去後:America,Brazil,Canada,dominica,Ecuador,France

第二引数にカンマを指定しているため、一番後ろのカンマが削除されています。ポイントとしては、すべてのカンマが削除されるのではなく、あくまでも一番最後のカンマのみが削除されるということです。

あまり役に立たなさそうに思われるかもしれませんが、文字列の一番後ろに区切り文字が入ってしまったときなどに使えるので意外と使用頻度は多いです。もちろん最初から区切り文字が入らないようにしておけば良いのですが、既存のシステムの改修などの案件だと土台を修正するのが難しい場合があります。

そこで別に関数を用意して最後の区切り文字を取り除くのです。以上配列の最後の要素や文字に対する処理方法を紹介してきました。文字列、要素操作はあまり面白くないかもしれませんが、業務系のシステムやWebサービスを作るなら必要な知識です。

PHPでのリファレンスの代入についてまとめました

PHPでのリファレンスの代入についてまとめました

PHPでのリファレンスの代入についてまとめました

プログラミング言語においてはリファレンス、参照、参照渡し、値渡し、などの概念があります。そしてそれはPHPでも同じです。

これらの概念は基本的にどのプログラミング言語でも同じなのですが、具体的にどのようなコードを記述したら参照になるのか値になるのか、といった点は言語によってまちまちです。

そこでこのページでは、そもそもリファレンス、参照、参照渡し、値渡しの概念の意味は?PHPではどのように記述する?といったことを解説していきます。

リファレンス、参照、参照渡し、値渡し、リファレンスの代入などの意味

まずリファレンス、参照、参照渡し、値渡し、リファレンスの代入などの用語の意味についてですが、リファレンスと参照は基本的に同じ意味になります。違いがよくわからないという声もあるようですが、英語か日本語かの違いです。

そして参照渡し、値渡しが対比されることが多いですが、要素を渡す方法にはこの二種類があります。この二種類の対比については後で説明します。リファレンスの代入については、参照渡しと同じ意味です。

たとえば変数から変数に要素を渡す際に、リファレンスの代入だと参照先のアドレスを渡すことになります。

参照渡しとは

参照渡しとは、渡したい要素に直接アクセスするための場所を渡す方法です。情報処理の勉強をされたことのある方はピンとくるかもしれませんが、プログラミングで扱う要素はすべてメモリ上のどこかに格納されています。

そして、参照渡しでは「メモリのここにアクセスしたら要素がありますよ」と参照値を渡しています。サンプルコードで確認すると、以下のようになります。

<?php
function hoge(&$foo)
{
    $foo = null;
}
$piyo = 1;
hoge($piyo);
var_dump($piyo);
?>

上記のコードを実行すると、「NULL」と出力されます。ここで重要なポイントは、hoge関数の中で書き換えた値が関数外にも影響が出ているということです。$piyo = 1で1を設定した後にhoge関数を呼び出して値を書き換えていて、最終的に出力した結果で関数で置き換えた値になっています。

参照渡しの場合メモリ領域で直接値を参照するので、それを書き換えると元の値が変わります。参照渡しにする場合、&$fooのように変数名の前に「&」を付けます。

値渡しとは

次に値渡しとは、値をコピーして渡す方法です。言葉のイメージ的に値渡しの方が直接値を渡したり書き換えたりしそうなイメージですが、値渡しはあくまでもメモリ領域の別の場所に値をコピーする方法で、直接元の値に影響を及ぼしません。

参照渡しは直接値を参照する、値渡しは間接的に値を渡す、ということです。初めて聞くとややこしいかもしれませんが、すぐに慣れるかと思います。値渡しのサンプルコードは以下です。

<?php
function hoge($foo)
{
    $foo = null;
}
$piyo = 1;
hoge($piyo);
var_dump($piyo);
?>

上記のコードを実行すると、「int(1)」と出力されます。$piyo = 1で1をセットした後にhoge関数を実行してnullを入れていますが、最終的な出力結果ではhoge関数の影響を受けていません。

これはhoge関数の引数が$fooとなっており、&が付いていないからです。&が付いていないと値渡しになるので、メモリ上は別の場所に新たに値をコピーしています。

コピーした値を書き換えるだけなので、元の値には何の影響も与えません。値渡しと参照渡しを知らない、もしくは特別意識せずにコードを書いている場合、&は付けずに書いているはずなので結果的に値渡しになっています。

意図しないバグを防ぐためには値渡しにしておいた方が別の場所の値を書き換えない分リスクが少ないのですが、場合によっては関数で関数外の変数に影響を与えたいこともあるかと思います。

その場合参照渡しを使うことになるので、値渡しと参照渡しは違いを理解したうえでコードを書いた方が良いです。

参照渡しの練習

参照渡しは上で説明した通り「&」を付けるだけなので特別難しいことはないのですが、実際にコーディングしているとどうしても混乱することがあったり、細かい記述がよくわからなかったりするかもしれません。

そこで、よくあるコーディングパターンで参照渡しを紹介しておきます。まずは配列を参照渡しして関数の中で処理するパターンです。

<?php
function hoge(&$foo)
{
    $foo[2] = 1;
    array_pop($foo);
}
$piyo = [1, 2, 3, 4];
hoge($piyo);
var_dump($piyo);
?>

上記のコードを実行すると、以下のように出力されます。

array(3) {
    [0]=>
    int(1)
    [1]=>
    int(2)
    [2]=>
    int(1)
}

参照渡しで関数に配列を渡し、関数の中では配列の2番目に1を格納し、次にarray_pop関数で配列の末尾を削除しています。その結果、配列の2番目の要素が1に変わり、配列の末尾も消えました。

ちなみに配列の要素は1からでなく0から数えるので、2番目は1から数えた場合の3番目になります。次にオブジェクトを参照渡しで渡す例です。

<?php
class Hoge {
    protected $piyo = 1;
    public function setValue($value) {
        $this->piyo = $value;
    }
    public function getValue() {
        return $this->piyo;
    }
}
function foo(&$qux)
{
    $qux->setValue(5);
}
$object = new Hoge();
foo($object);
echo $object->getValue();
?>

上記のコードを実行すると、「5」と出力されます。処理の流れとしてはまずHogeクラスを定義しています。クラスの中ではsetValueメソッドとgetValueメソッドが定義されています。

次にfoo関数を定義します。foo関数はsetValueメソッドを呼び出して5をセットするための関数です。次にHogeクラスのオブジェクトを生成します。そのオブジェクトを引数にする形でfoo関数を呼び出し、foo関数の中でsetValueで5をセットしました。

最後にgetValueでセットした値を取得して出力しています。このように一つ一つの処理を追っていくと、一見複雑に見えなくもないソースコードがトレースできます。

一つ一つのコードの詳細がいまいちわからないということがもしかするとあるかもしれませんが、今回は処理の大枠が理解でき、その結果参照渡しがどのように使われているのかわかればそれで問題ありません。

大枠さえ理解できれば、実際にコーディングする際の詳細はその都度調べれば実装できます。プログラミングにおいては大枠の設計を考えることがもっとも重要です。

まとめ

以上、リファレンスの代入、参照渡し、値渡しといった概念とその使い方について解説してきました。

基本的な部分なのであまり面白みはないかもしれませんが、機能性の高いシステムを作るためにはこのような基礎の部分が重要です。

すべてのシステムは基礎の積み重ねでしかないので、ぜひこういった基本概念をきっちり押さえていってください。

PHPでmb_substrを使って文字列を取得する

PHPでmb_substrを使って文字列を取得する

PHPでmb_substrを使って文字列を取得する

特に業務用のシステムを扱う際には文字列の処理が重要で、自由に文字列を取得する必要性のあるシステムも多いです。

そこで便利なコードの一つがmb_substrで、mb_substrを使用することで文字列の中から指定した部分を取得することが可能です。

mb_substrの使い方

mb_substrは文字列の一部を取得する関数で、引数は四つあります。第一引数が文字列(変数)、第二引数が文字列の開始位置、第三引数が文字列の終わり位置、第四引数が文字コードとなっています。

それではサンプルコードを紹介していきます。まずは第一引数と第二引数のみのパターンです。

<?php
$str = “abcde”;
echo mb_substr($str,1);
?>

上記を実行すると以下のようになります。

bcde

開始位置のみを1と指定したため、0から数えて1番目のbから順に出力されました。終わり位置を指定しないと文字列の最後まで出力されます。次に、第一引数~第三引数の文字列の終わりまでを指定したパターンです。

<?php
$str = "abcde";
echo mb_substr($str,1,3);
?>

上記のコードを実行すると、以下のように出力されます。

bcd

第三引数で終わりを3と指定しているので、文字列の3番目で出力は終わりました。次に、第四引数まで指定したパターンです。

<?php
$str = "あいうえお";
echo mb_substr($str,1,3,"UTF-8");
?>

このコードを実行すると、以下のように出力されます。

いうえ

第三引数までは先ほどの考えと同じで、第四引数でUTF-8を指定しています。これによって、日本語の文字列も取得することが可能になります。

またmb_substrと似たような形で文字列を取得できる関数もあるので、合わせてそちらも紹介しておきます。

substrの使い方

substrはmb_substrとほぼ同じですが、違いは第四引数があるかないかです。substrには第四引数はなくて、第一引数~第三引数までです。引数の内訳はmb_substrとまったく同じです。一応サンプルコードを紹介しておきます。

<?php
$str = “abcde”;
echo substr($str,1);
?>

これは第二引数までのパターンです。出力結果は「bcde」となります。次に第三引数まで指定するパターンです。

<?php
$str = "abcde";
echo substr($str,1,3);
?>

これも先ほどと同様に、「bcd」と出力されます。第四引数の文字コードを指定しない場合どちらを使っても変わらないのですが、文字数的にsubstrの方が少ないので、そちらを使うと良いかもしれません。

変数の中に日本語が入っているならmb_substrを使用した方が良いのかもしれませんが、そうでないならsubstrの方が書きやすいので使いやすいです。

substr_replaceの使い方

上では文字列の任意の部分を取得する方法を紹介しましたが、文字列の一部を操作することも可能です。substr_replaceはその名の通り、文字列の一部を置き換える関数になります。構文は以下です。

substr_replace(元の文字列,置換する文字列,開始位置[,範囲])

substr_replaceを使用したサンプルコードは以下です。

<?php
$str = "abcde";
echo substr_replace($str,"9",2,1);
?>

上記のコードを実行すると以下のように出力されます。

ab9de

0から数えて2番目のcが9に置き換えられました。また範囲は1を指定したので、置き換えられた文字数は1文字だけです。ポイントがあるとすればsubstr_replaceの使い方かどうかは微妙ですが、数字に置き換える際に文字列として指定することでしょう。

string型で文字列が入っている変数に対して置換を行っているので、数字に置き換える際は数字を文字列で指定する必要があります。

substr_countの使い方

substr_countは文字列の中で指定した文字が何回出現したのかをカウントする関数です。使い方は至ってシンプルで、構文は以下です。

substr_count(検索対象の文字列,検索する文字列)

引数は二つだけなので、上で紹介してきた文字列操作関数よりも簡単かもしれません。サンプルコードは以下です。

<?php
$str = "PHPの勉強を開始しました。";
echo substr_count($str,"P");
?>

上記のコードを実行すると、「2」と出力されます。

文字列を分割する

文字列の取得や簡単な操作は上記で解説した通りです。ここでもう一歩踏み込むと、文字列の分割も可能です。特に文字列分割に用がない方は知る必要がないのですが、使用機会がありそうな方はぜひ押さえておくと良いです。

とはいえ使用機会がなさそうな方であっても、知っておけば文字列操作のレパートリーが増える分理解も深まるでしょう。文字列の分割に使用する関数はwordwrapです。wordwrapは以下のような構文で使用します。

$変数名 = wordwrap(文字列, 分割する文字数, 分割する部分に入れる文字[, true/ false]);

まず第一引数は分割する対象となる文字列です。これについては上で紹介してきた関数と同じです。第二引数は分割する文字数です。何文字ごとに分割したいかを指定できます。

第三引数は分割部分に入れる文字です。どのような文字で分割するかを指定できます。分割だけでなく、<br/>や\nを指定することで改行も可能です。第四引数はtrue/falseで、trueなら必ず指定した文字数で分割されます。

falseの場合単語単位で分割するので、たとえば指定した文字数で単語の途中になる場合、その単語の前で分割します。wordwrapを使用したサンプルコードは以下です。

<?php
$longword = 'Do you know the word of Pneumonoultramicroscopicsilicovolcanoconiosis? This is name of lung disease.';
$words = wordwrap($longword, 30, '<br/>');
echo $words;
?>

このコードを実行すると、以下のように出力されます。

Do you know the word of
Pneumonoultramicroscopicsilicovolcanoconiosis?
This is name of lung disease.

30文字ごとに分割するように指定されていますが、一つの長い単語は30文字以上続いています。今回第四引数は指定しなかったのですが、仕様上デフォルトでは第四引数がfalseになっているので、第四引数を指定しないと単語は分割されません。

trueを指定すると以下のように単語の間でも分割されます。

<?php
$longword = 'Do you know the word of Pneumonoultramicroscopicsilicovolcanoconiosis? This is name of lung disease.';
$words = wordwrap($longword, 30, '<br/>', true);
echo $words;
?>

これを実行すると以下のようになります。

Do you know the word of
Pneumonoultramicroscopicsilico
volcanoconiosis? This is name
of lung disease.

単語の間でも分割されています。

以上文字列取得やその他文字列操作について解説しました。

文字列操作はあまり面白くないかもしれませんが、業務用のシステムでは基本になるので、押さえておくと役立つはずです。