20190324のPHPに関する記事は14件です。

WordPressインストールしたあとにやった方がよさそうなことメモ

前回の記事の続きです。
勉強する気力がびっくりするくらい湧かないしWordPressでアフィブログ作ろうと思った話

前回のあらすじ

ドメイン取得してレンタルサーバー借りてWordPressインストールしました。
宣伝⇒できたブログ

サーバー設定でやり忘れてたこと

SSLの設定

どうもGoogle先生はSSL設定してないサイトが嫌いみたいなので一応設定しました。
こうするとhttpでもhttpsでもどっちでもアクセスできるようになります。サーバーの管理コンソールからぽちぽちやったらできました。
Secureになって何がうれしいのかはよくわかりません。

WordPressの設定をいじる

SEO対策の設定まわり

だいたいこのあたりのサイトを見ながらやっておきました。

WordPressインストール後すぐやっておきたい6つの初期設定

SEO的にもいいらしいです。

デザインテーマの設定をする

LION BLOGってテーマがイケてるって話だったので使ってみました。
管理用のダッシュボードで検索しても出てこないのでググったら公式っぽいのが出てきました。(はい
zipがダウンロードできるので何も考えずに解凍したんですけどzipのままぶっこめってなってて少し損しました。
細かい設定はよくわからないのであんまり弄ってないです。

プラグインをいれる

ゴテゴテにプラグイン入れてるサイトもあるみたいですけど重くなるし個人的にも管理しきれないなってことで相当絞ってます。
以下入れたやつ

  1. Akismet Anti-Spam
    スパムコメント勝手に消してくれるマン。インストールしたら最初っから入っていたので有効にしておきました。
  2. Edit Author Slug
    WordPressで作ってるサイトってURL末尾に/?author=IDをつけるとIDが見れちゃうみたいでそれをガードしてくれます。設定方法はググってください。
  3. EWWW Image Optimizer
    画像をいい感じに圧縮してくれる。らしいです。詳しくはわからないですけど位置情報とかも消してくれるみたいなのでこのまま入れておこうと思います。
  4. Google XML Sitemaps
    サイトマップのXMLを勝手に作ってくれる?よくわからない子です。おすすめされてたので入れました。
  5. All In One SEO Pack SEO対策をあれこれやってくれる。たぶん。これ入れると微妙にサイトのレスポンス悪くなるらしいので入れたくない人はいれなくていいかもです。

Googleにゴマすりをする

Google先生にゴマすりしないとサイトのアクセスが増えないみたいなのでやっておきます。
詳しくはよくわからないんですけどググったらサーチコンソールとGoogleアナリティクスがどうのこうのって書いてあったので登録しておきました。たぶん全然活用できてないです。

おわりに

たぶんここまでやったらまあまあ問題ないページなんじゃないでしょうか。あとはたぶん宣伝用にSNS周りの設定が必要だと思うんですけどめんどくさかったのでやってないです。
クラウドワークスとかでWordPressのページ作成3万とかで受けてる人マジですげーなって思いました。
おわり。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel5.4以上でGD Library extension not available with this PHP installation.のエラーが出た時の対処法

環境

PHP:v7.0.31
Laravel:v5.5
IDE:cloud9

エラー内容

composer require intervention/image

も実行した。

config/app.php
//provider
'Intervention\Image\ImageServiceProvider',
//aliases
'Image' => 'Intervention\Image\Facades\Image',

この2つも追加した。

いざアップロードすると

Driver.php
GD Library extension not available with this PHP installation.

このエラーが出る。

なんと

実は、「Intervention/image」はPHP5.4以上で画像処理ライブラリのGDまたはImageMagickがインストールされている必要があるそうです。てことでGDをインストールします。

sudo apt-get update
sudo apt-get install php7.0-gd

以上2つのコマンドをターミナルでうち、apache再起動すれば動くと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LaravelでGD Library extension not available with this PHP installation.のエラーが出た時の対処法

環境

PHP:v7.0.31
Laravel:v5.5
IDE:cloud9

エラー内容

composer require intervention/image

も実行した。

config/app.php
//provider
Intervention\Image\ImageServiceProvider::class,
//aliases
'Image' => Intervention\Image\Facades\Image::class,

この2つも追加した。

app/http/Controllers/PhotosController.php
use Image;

も対象のコントローラのトップに追加してある。
しかしながら、以下

Driver.php
GD Library extension not available with this PHP installation.

このエラーが出る。

なんと

実は、「Intervention/image」はPHP5.4以上で画像処理ライブラリのGDまたはImageMagickがインストールされている必要があるそうです。てことでGDをインストールします。

sudo apt-get update
sudo apt-get install php7.0-gd

以上2つのコマンドをターミナルでうち、apache再起動すれば動くと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【PHP】APIを使用しQiitaでの自分の投稿を取得する方法。

Qiitaでの自分の投稿を取得しよう!

今回は、ポートフォリオに学習したことを掲載するためQiitaの投稿を取得しました。そして、取得した内容をブラウザに表示するまでのことを記事にします。

コード

index.php
<?php
$curl = curl_init('https://qiita.com/api/v2/authenticated_user/items');
$option = [
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    'Authorization: Bearer [取得したアクセストークン]',
    'Content-Type: application/json',
  ],
];
curl_setopt_array($curl, $option);

$result = curl_exec($curl);

$decode_res = json_decode($result);
?>

<DOCTYPE html>
/
/ (省略)
/
<?php foreach($decode_res as $res){ ?>
   <a href="<?php echo $res->url;?>" target="_brank">
     <p><?php echo $res->title;?></p>
   </a>
<?php } ?>

基本的にはアクセストークンをQiitaで取得し自分の投稿を取得します。
配列の形になって返ってくるので、foreachで回すだけです。

Qiitaのアクセストークン取得方法

「設定」⇨「アプリケーション」⇨「新しくトークンを発行する」
この後は、自分が何をしたいのかによって取得するトークンは変わるのですが、今回は投稿を取得するので「read_qiita」でアクセストークンを取得します。

関数curl()

取得したら実際にコードを書いていきます。
その時に使うのがcurl()関数です。
今回はこちらを使います。
・curl_init()
・curl_setopt_array()
・curl_exec()
・curl_close()
流れはこう。
1,curl_init()で初期化
2,curl_setopt_array()で色々なオプションを決める
3,curl_exec()で実行
4,curl_close()で終了

説明

まずcurl_init()にこのURLを「https://qiita.com/api/v2/authenticated_user/item」
ちなみにこのURLは何がしたいかによって変わるのでこちらを参照してください。
Qiita API

そして次にcurl_set_opt()でオプションの設定です。
オプションとはなんだ?って方はまたもやこちらを参考にしてください。
オプション一覧

ここで使っているオプションの説明だけします。
・CURLOPT_CUSTOMREQUEST⇨HTTPリクエストの方法を指定します。GETだったりPOSTだったり。
・CURLOPT_RETURNTRANSFER⇨curl_exec()の値をデータで返すのか、文字列で返すのかの指定です。trueなら文字列で返します。
・CURLOPT_HTTPHEADER⇨ 任意でHTTPヘッダーを設定できます。簡単にいうとサーバーにリクエストする際の情報をこちらで追加できるみたいな感じですかね。

後はcurl_seopt_array()で配列に格納。
実行したものを$resultに代入。
このとき$resultはjsonファイルになっているのでjson_decode()でPHPの型にして返します。

それをforeachでぶん回します。

取得したいものはQiit APIで確認してみてください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

リレーションはメソッドで定義したはずが、プロパティアクセスで動作する謎を解明する(Laravel)

前提

Bookというモデルには、detail()というメソッドが定義してあるとする。この定義によりBookモデルとBookdetailモデルが、「bookdetail_idとid」を通して、1対1に結合(hasOne)していることになる。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Book extends Model
{
  public function detail(){
    return $this->hasOne('\App\Bookdetail','id','bookdetail_id');
  }
}

下記は、Bookモデルからid=1であるもののbookdetail_idを通して、Bookdetailモデルからisbnを出力するコードである。

class TestController extends Controller
{
  public function test(){
    $book = \App\Book::find(1);
    echo $book->detail->isbn;
  }
}

疑問点

先ほどのBookモデルでは、detail()とメソッドとして定義したはずだ。しかし、このコードでは、->detailとプロパティアクセスの形になっている。どこにもメソッドとして実行する記述はない。いったい何が起こっているのだろう?

Laravelのコアファイルを深掘りする

それでは、Laravelのコアファイルを一つずつ辿っていきたい。
本記事の動作前提となるファイルは下記に用意してあるので、自分でサンプルデータを作るのが面倒な方は、適宜利用いただきたい。
https://github.com/3tomcha/qiita

->detailとはつまり何をしているのか

まずはアクセスされる側の$bookの型を調べて見よう。dd()を使って出力するとBook型とわかる。(これは大方の予想通りであろう)
つまり->detailの正体を知るには、\App\Bookを調べるのが良さそうだと検討がつく。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class TestController extends Controller
{
  public function test(){
    $book = \App\Book::find(1);
    dd($book);
    echo $book->detail->isbn;
  }
}

スクリーンショット 2019-03-24 12.09.19.png

さてApp\Bookをみてみると、直接関係ありそうな記述はない。よって、Illuminate\Database\Eloquent\Modelを辿ってみる。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Book extends Model
{
  public function detail(){
    return $this->hasOne('\App\Bookdetail','id','bookdetail_id');
  }
}

Illuminate\Database\Eloquent\Model をみると、気になる記述が見つかる。__getはマジックメソッドと呼ばれるもので、アクセスできないプロパティにアクセスした時に呼ばれるものだ。これが働いているのではと検討がつく。実際にdump()を使ってみると、__getは2回行われており、1回目はBookdetailオブジェクト、2回目は結果のisbnである"3333333333333"を返している。

    /**
     * Dynamically retrieve attributes on the model.
     *
     * @param  string  $key
     * @return mixed
     */
    public function __get($key)
    {
        return $this->getAttribute($key);
    }

スクリーンショット 2019-03-24 12.18.05.png

次に__getで行われている getAttribute()を辿って見よう。
Illuminate\Database\Eloquent\Concerns\HasAttrubute.php に定義されている。
今回は、hasOneというリレーションを定義しているため、最後の return $this->getRelationValue($key); が動いていそうだと検討を付けて、さらに進む。

    /**
     * Get an attribute from the model.
     *
     * @param  string  $key
     * @return mixed
     */
    public function getAttribute($key)
    {
        if (! $key) {
            return;
        }

        // If the attribute exists in the attribute array or has a "get" mutator we will
        // get the attribute's value. Otherwise, we will proceed as if the developers
        // are asking for a relationship's value. This covers both types of values.
        if (array_key_exists($key, $this->attributes) ||
            $this->hasGetMutator($key)) {
            return $this->getAttributeValue($key);
        }

        // Here we will determine if the model base class itself contains this given key
        // since we don't want to treat any of those methods as relationships because
        // they are all intended as helper methods and none of these are relations.
        if (method_exists(self::class, $key)) {
            return;
        }

        return $this->getRelationValue($key);
    }

getRelationValueは同じく Illuminate\Database\Eloquent\Concerns\HasAttrubute.php に定義されている。最下部にあるgetRelationshipFromMethod を辿って見よう。

/**
     * Get a relationship.
     *
     * @param  string  $key
     * @return mixed
     */
    public function getRelationValue($key)
    {
        // If the key already exists in the relationships array, it just means the
        // relationship has already been loaded, so we'll just return it out of
        // here because there is no need to query within the relations twice.
        if ($this->relationLoaded($key)) {
            return $this->relations[$key];
        }

        // If the "attribute" exists as a method on the model, we will just assume
        // it is a relationship and will load and return results from the query
        // and hydrate the relationship's value on the "relationships" array.
        if (method_exists($this, $key)) {
            return $this->getRelationshipFromMethod($key);
        }
    }

getRelationshipFromMethodは同じく Illuminate\Database\Eloquent\Concerns\HasAttrubute.php に定義されている。
ここで、今まで辿ってきたことに確信が持てるはずだ。$relation = $this->$method(); の記述によって、なぜ->detailとアクセスしたのに、detail()が動いているのだろうという疑問が解決された。

/**
     * Get a relationship value from a method.
     *
     * @param  string  $method
     * @return mixed
     *
     * @throws \LogicException
     */
    protected function getRelationshipFromMethod($method)
    {
        $relation = $this->$method();

        if (! $relation instanceof Relation) {
            throw new LogicException(sprintf(
                '%s::%s must return a relationship instance.', static::class, $method
            ));
        }

        return tap($relation->getResults(), function ($results) use ($method) {
            $this->setRelation($method, $results);
        });
    }

$methodと$relation をそれぞれdumpしてみると、予想通り$methodはdetailであり、$relationにはBookモデルのdetail()が行われた結果であるHasOneオブジェクトが入っていることがわかった。

スクリーンショット 2019-03-24 13.00.48.png

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Book extends Model
{
  public function detail(){
    return $this->hasOne('\App\Bookdetail','id','bookdetail_id');
  }
}

結論

プロパティアクセスの形でしか書いていないのに、モデルのメソッドが動く理由は、コアの処理の途中で$method()として実行しているため。

修正ご意見お待ちしています

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[postfix,sendmail] phpでメールを送信するまでのまとめ

目的

プログラムでメールを送っている仕組みを整理したい。

本当の目的

qiitaで久しぶりに何か上げたかった

役者たち

  • php
    • 今回メール送信を行う言語
  • sendmail
    • プログラムでメール送信を行うときに内部で呼び出されるコマンド
  • postfix
    • メール送信の設定を行う何か(メールの送信元とか)

実験環境

OS: OSX ver 10.13.6
php: 7.1.16

メール送信プログラム

今回実行するコード(test.php)↓(メールアドレスは匿名)

<?php
$to = 'hogehoge@example.com';
$subject = "let's php mail";
$message = 'Can you see it?';
mb_send_mail($to, $subject, $message);

メールの送信元設定

メールは送信元がないと送れない(常識)
その設定をpostfixで行う

postfixでメールの送信元を設定

$ sudo vim /etc/postfix/sasl_password

今回はgmailを利用してメールを行う。
そのためには、gmailのアプリケーションパスワードが必要である。
アプリケーションパスワードの設定はこちら(注意:gmailに紐づくアカウントが2段階認証されてないとダメ)

sasl_password(メールを送信するエージェントをgmailに設定)

[smtp.gmail.com]:587 <ここにメールアドレス>:<ここにアプリケーションパスワード>

設定をpostfixに反映

$ sudo postmap /etc/postfix/sasl_password

試しにsendmailで送ってみる

$ sendmail hoge@example.com(送信先アドレス)
testhoge
.

phpで実行

$ php test.php

まとめ

メール送信するだけでも、色々疲れちゃった

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

laradock で『laradock_mysql_1 docker-entrypoint.sh mysqld Exit 2』となる問題を解決

環境

OS:macOS Mojave 10.14.3
Docker:18.09.2
docker-compose:1.23.2
docker-machine:0.16.1
php:7.1.23
Laravel Framework:5.8.7
mysql:Ver 14.14 Distrib 5.7.25, for Linux (x86_64) using EditLine wrapper

事象

laradockで構築したmysqlを起動すると

$ docker-compose up -d php-fpm nginx mysql
Recreating laradock_mysql_1          ... done
Starting laradock_docker-in-docker_1 ... done
Starting laradock_workspace_1        ... done
Starting laradock_php-fpm_1          ... done
Starting laradock_nginx_1            ... done


$ docker-compose ps
           Name                          Command              State                      Ports                   
-----------------------------------------------------------------------------------------------------------------
laradock_docker-in-docker_1   dockerd-entrypoint.sh           Up       2375/tcp                                  
laradock_mysql_1              docker-entrypoint.sh mysqld     Exit 2                                             
laradock_nginx_1              /bin/bash /opt/startup.sh       Up       0.0.0.0:443->443/tcp, 0.0.0.0:8080->80/tcp
laradock_php-fpm_1            docker-php-entrypoint php-fpm   Up       9000/tcp                                  
laradock_workspace_1          /sbin/my_init                   Up       0.0.0.0:2222->22/tcp

となり起動にコケてしまう事象が発生しました。

解決方法

一旦dockerを止めます。

docker-compose stop

以下のファイルを変更します。

.env
### MYSQL #################################################

MYSQL_VERSION=latest #latestのまま
- MYSQL_DATABASE=default
+ MYSQL_DATABASE=laradock
- MYSQL_USER=root
+ MYSQL_USER=laradock
- MYSQL_PASSWORD=root
+ MYSQL_PASSWORD=secret
MYSQL_PORT=3306
MYSQL_ROOT_PASSWORD=root
MYSQL_ENTRYPOINT_INITDB=./mysql/docker-entrypoint-initdb.d

さらに、以下のディレクトリ配下のファイルをすべて削除します。
/Users/{USER NAME}/.laradock/data/mysql/

終わり

以上、対応後にdockerを起動すると

$ docker-compose up -d php-fpm nginx mysql
Starting laradock_docker-in-docker_1 ... done
Recreating laradock_mysql_1          ... done
Starting laradock_workspace_1        ... done
Starting laradock_php-fpm_1          ... done
Starting laradock_nginx_1            ... done


$ docker-compose ps
           Name                          Command              State                     Ports                   
----------------------------------------------------------------------------------------------------------------
laradock_docker-in-docker_1   dockerd-entrypoint.sh           Up      2375/tcp                                  
laradock_mysql_1              docker-entrypoint.sh mysqld     Up      0.0.0.0:3306->3306/tcp, 33060/tcp         
laradock_nginx_1              /bin/bash /opt/startup.sh       Up      0.0.0.0:443->443/tcp, 0.0.0.0:8080->80/tcp
laradock_php-fpm_1            docker-php-entrypoint php-fpm   Up      9000/tcp                                  
laradock_workspace_1          /sbin/my_init                   Up      0.0.0.0:2222->22/tcp  

mysqlのプロセスが確認できれば完了です。お疲れ様でした^^

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【改】WordPressでMVCフレームワーク風の立ち回りをする。(3ヶ月間運用してみてこうなった)

前回、wordpressの運用管理が既存のテンプレート階層のルーティングだと大変だと感じ、サイトの設計をMCVフレームワーク風にしてみた。という記事を書きました。

WordpressでMVCフレームワーク風の立ち回りをする。

そこから実際に3ヶ月ほど運用を行い、こうした方が管理が楽という部分も出てきたので、結果はこうなりました。という部分を端的にまとめます。細かい部分を知りたい場合は是非、質問をください。

1. ディレクトリ構成

[ディレクトリ名の意味]

  • pages => フロント用(管理画面じゃないページ)の格納場所
  • page => 固定ページ用のフォルダ
  • post_type => 投稿タイプ別のフォルダ (実際はpost_type別のフォルダはもっと多くなります。今回はゴチャゴチャしないように一つだけにしました。)
  • 下記ディレクトリ構成のファイル名の部分にORと記載している箇所がありますが、共通テンプレートや固有のテンプレートが存在する部分です。
    • 意味としては、page.phppost_type_single.phpは共通テンプレートpage_slug.phppost_type_single_name.phpは各ページ固有のテンプレートです。
.
├── app
│   ├── .npm
│   ├── .composer
│   ├── assets
│   │   └── pages
│   │       ├── home
│   │       │   ├── css
│   │       │   │   └── xxxxxx.css
│   │       │   ├── img
│   │       │   │   └── xxxxxx.png
│   │       │   └── js
│   │       │       └── xxxxxx.js
│   │       ├── page
│   │       │   ├── css
│   │       │   └── img
│   │       └── post_type
│   │           ├── post_type_archive
│   │           │   ├── css
│   │           │   └── img
│   │           └── post_type_single
│   │               ├── css
│   │               └── img
│   ├── functions
│   │   ├── controllers
│   │   │   ├── resources
│   │   │   │   ├── all
│   │   │   │   │   └── all.php
│   │   │   │   ├── home
│   │   │   │   │   └── home.php
│   │   │   │   ├── page
│   │   │   │   │   └── page.php OR page_slug.php
│   │   │   │   └── post_type
│   │   │   │       ├── post_type_archive
│   │   │   │       │   └── post_type.php
│   │   │   │       └── post_type_single
│   │   │   │           └── post_type_single.php OR post_type_single_name.php
│   │   │   └── router
│   │   │       └── router.php
│   │   └── models
│   │       ├── config
│   │       │   ├── basis.php
│   │       │   └── wpcf7.php
│   │       ├── data
│   │       │   ├── csv
│   │       │   └── json
│   │       ├── modules
│   │       │   ├── xxxx.php
│   │       │   └── shortcode.php
│   │       └── pages
│   │           ├── home
│   │           │   └── home.php
│   │           ├── page
│   │           │   └── page.php OR page_slug.php
│   │           └── post_type
│   │               ├── post_type_archive
│   │               │   └── post_type.php
│   │               └── post_type_single
│   │                   └── post_type_single.php OR post_type_single_name.php
│   └── views
│       ├── pages
│       │   ├── home
│       │   │   └── home.php
│       │   ├── page
│       │   │   └── page.php OR page_slug.php
│       │   ├── post_type
│       │   │   ├── post_type_archive
│       │   │   │   └── post_type.php
│       │   │   └── post_type_single
│       │   │       └── post_type_single.php OR post_type_single_name.php
│       │   └── error
│       │       └── 404.php
│       ├── templates
│       │   ├── footer.php
│       │   └── header.php
│       └── util
│           └── analysis
│               ├── fb-ad.php
│               ├── gtm.php
│               ├── gtm_no-script.php
│               └── ytm.php
├── editor-style.css
├── functions.php
├── index.php
└── style.css

まず、前回から変更した部分で言うと、テーマディレクトリ直下のsingle.phpやarchive.phpなどのテンプレートファイルを排除しました。これは極論、index.phpだけでルーティングしても問題なかったためです。

2. ルーティング

次にルーティングの方法を変更しました。

テンプレートのロード、cssとjsのロード

前回ではテンプレートを読み込むclassとcss、jsを読み込むclassを分けていたのですが、一つのclassへまとめました。
コードで見ると下記のようになります。

変更前

router_home.php
namespace controllers\router\pages\home;

class router_home
{
    public function __construct()
    {
        $this->load_template();
    }

    # テンプレートの読み込み
    public function load_template()
    {
        require_once get_template_directory() . '/app/views/pages/home/home.php';
    }
}
loader_home.php
namespace controllers\loader\pages\home;

class loader_home
{
    public function __construct()
    {
        $this->wp_enqueue_scripts();
    }

    # css、jsの読み込み
    public function wp_enqueue_scripts()
    {
        wp_enqueue_style('home', get_template_directory_uri() . '/app/assets/pages/home/css/style.css');
        wp_enqueue_script('app', get_template_directory_uri() . '/app/assets/pages/home/js/app.js', array(), null, true);
    }
}

変更後

home.php
namespace controllers\resources\home;

class home
{
    public function __construct()
    {
        $this->wp_enqueue_scripts();
        $this->template_directory();
    }

    # css、jsの読み込み
    public function wp_enqueue_scripts()
    {
        wp_enqueue_style('home', get_template_directory_uri() . '/app/assets/pages/home/css/style.css');
        wp_enqueue_script('app', get_template_directory_uri() . '/app/assets/pages/home/js/app.js', array(), null, true);
    }

    # テンプレートの読み込み
    public function template_directory()
    {
        require_once get_template_directory() . '/app/views/pages/home/home.php';
    }
}

変更後のhome.phpのように、resourcesフォルダ内の各classへまとめました。
ポイントとしてはこのクラスがインスタンス化された時にcss、jsの読み込みを行う関数が最初に動くようにしておく事です。(テンプレートを引っ張ってくる関数を最初に動かすと画面レイアウトが崩れる場合がある)←多分、フックをちゃんと指定すれば大丈夫だと思います。

router.php

こちらは結構、仕様変更しました。

変更前

router.php
class Router
{
    public function __construct()
    {
        add_action('wp', array($this, 'front_controller'));
    }

    public function front_controller()
    {
        global $wp_query;
        global $post;

        # トップページ
        if (is_home()) {
            new models\pages\home\model_home();
            new controllers\loader\pages\home\loader_home();
            new controllers\router\pages\home\router_home();
        }
        # 固定ページ
        else if (is_page()) {
            $pagename = isset($wp_query->query['pagename']) ? $wp_query->query['pagename'] : '';
            switch ($pagename) {
                case 'unique_slug_name':
                    new \models\pages\slug_name\model_slug_name();
                    new \controllers\loader\pages\slug_name\loader_slug_name();
                    new \controllers\router\pages\slug_name\router_slug_name();
                    break;
                case 'unique_slug_name':
                    ...
                    break;
                case 'unique_slug_name':
                    ...
                    break;
                default:
                    return;
                    break;
            }
        }
        # カスタム投稿アーカイブ
        elseif (is_post_archive()) {
        ...
        }
        # カスタム投稿個別ページ
        elseif (is_singular()) {
        ...
        }
        # 404ページ
        else {
            new \controllers\loader\pages\error\loader_404();
            new \controllers\router\pages\error\router_404();
        }
    }
}

new Router();

変更後

router.php
/*------------------------------------------------------------------------------------
/* 全ページ共通
/*----------------------------------------------------------------------------------*/
# 基本設定
new \models\config\basis();
...
# 全ページで読み込むcss
add_action('wp',function(){new \controllers\resources\all\all();});
/*------------------------------------------------------------------------------------
/* トップページ
/*----------------------------------------------------------------------------------*/
add_action('wp', function() {
    if (is_home()) {
        new \models\pages\home\home();
        new \controllers\resources\home\home();
    }
});
/*------------------------------------------------------------------------------------
/* 固定ページ
/*----------------------------------------------------------------------------------*/
# 固定ページの共通テンプレート
add_action('wp', function() {
    if (is_page()) {
        $template = get_field_object('example_template');
        $value = $template['value'];
        if ($value == 'default') {
            new \models\pages\page\page();
            new \controllers\resources\page\page();
        }
    }
});

# 共通ではなくオリジナルの固定ページテンプレート
add_action('wp', function() {
    if (is_page('example')) {
        $template = get_field_object('example_template');
        $value = $template['value'];
        if ($value == 'templateA') {
            new \models\pages\page\page_slug();
            new \controllers\resources\page\page_slug();
        }
    }
});
/*------------------------------------------------------------------------------------
/* 投稿タイプA
/*----------------------------------------------------------------------------------*/
# 共通テンプレートの記事ページ
add_action('wp', function() {
    if (is_singular('post_typeA') && is_single()) {
        $template = get_field_object('example_template');
        $value = $template['value'];
        if ($value == 'default') {
            new \models\pages\post_typeA\post_type_single();
            new \controllers\resources\post_typeA\post_type_single();
        }
    }
});

# 共通ではなくオリジナルテンプレートの記事ページ
add_action('wp', function() {
    if (is_singular('post_typeA') && is_single('example')) {
        $template = get_field_object('example_template');
        $value = $template['value'];
        if ($value == 'templateA') {
            new \models\pages\post_typeA\single_slug();
            new \controllers\resources\post_typeA\single_slug();
        }
    }
});

# アーカイブ
add_action('wp', function() {
    if (is_post_type_archive('post_typeA')) {
        new \models\pages\post_typeA\post_type_archive();
        new \controllers\resources\post_typeA\post_type_archive();
    }
});
/*------------------------------------------------------------------------------------
/* 404ページ
/*----------------------------------------------------------------------------------*/
add_action('wp', function() {
    if (is_404()) {
        new \controllers\resources\error\error_404();
    }
});

前回ではrouter.phpをクラスファイルとして利用していましたが、クラスではなく、ページ単位のアクションフック付き関数にしました。こっちの方がpost_type毎の関数を一箇所にまとめられて見通しが良かったです。(前回ではテンプレート階層毎にまとめていた)

また、途中で$template = get_field_object('event_template');のような記述が入っていますが、これはカスタムフィールドの値によって使用するテンプレートが正か否かを判別しています。

というのも、固定ページも含めこの構成にすると、なにかしらの工夫をしなければ、投稿編集画面からテンプレートの選択ができなくなります。( ̄Д ̄;)

私は対策としてAdvanced Custom Fieldsを使って投稿編集画面右側にテンプレート選択のフィールドを追加しました。

この辺も含め、まだまだ改良の余地がありそうです...

3. All in One SEO Packとの互換性

このディレクトリ構成にするとwp_title()がテンプレート内で使えなくなりました。
4.4ぐらいから非推奨にはなっていたものの、4.9とかでもまだ動いていたので放置していましたが、これを機にadd_theme_support('title-tag');へ移行しました。

しかし、思わぬところで落とし穴が...
All in One SEO Packの機能で、投稿編集画面内にTitleを個別に設定できるようにするフィールドを追加できますが、そこに入力されたTitleが読み込まれなくなってしまった...(SEO担当に注意されてしまいました...(´・ω・`))

下記はこちらの不具合で対応したコードです。
調べると参考になる記事がたくさん出てきましたが、どうやら_aioseop_titleでフィールドに入力した値を取れるみたいですね。

basis.php
namespace models\config;

class basis
{
    public function __construct()
    {
        add_filter('pre_get_document_title', array($this, 'custom_single_title'));
        ...
    }

    # 個別記事ページへAll in seo packで設定したタイトルを出力
    public function custom_single_title($title)
    {
        if (is_single()) {
            global $post;
            if (get_post_meta($post->ID, '_aioseop_title', true)) {
                $title = get_post_meta($post->ID, '_aioseop_title', true) . ' | サイトの名前';
            }
        }
        return $title;
    }
    ...
}

まとめ

私の場合は、すでにwordpressで構築されたサイトを引き継いでいるケースですが、サービスの初期構築段階で、ある程度の規模のサイトだという事が分かっているならlaravelなどのフレームワークを選択しましょう。

ここまで書いておいてですが、wordpressでMVCテーマを作るのはちょっと大変ですね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MVCフレームワーク風のWordPressテーマを3ヶ月間運用してみたらこうなった。

前回、wordpressの運用管理が既存のテンプレート階層のルーティングだと大変だと感じ、サイトの設計をMVCフレームワーク風にしてみた。という記事を書きました。

WordpressでMVCフレームワーク風の立ち回りをする。

そこから実際に3ヶ月ほど運用を行い、こうした方が管理が楽という部分も出てきたので、結果はこうなりました。という部分を端的にまとめます。細かい部分を知りたい場合は是非、質問をください。

1. ディレクトリ構成

[ディレクトリ名の意味]

  • pages => フロント用(管理画面じゃないページ)の格納場所
  • page => 固定ページ用のフォルダ
  • post_type => 投稿タイプ別のフォルダ (実際はpost_type別のフォルダはもっと多くなります。今回はゴチャゴチャしないように一つだけにしました。)
  • 下記ディレクトリ構成のファイル名の部分にORと記載している箇所がありますが、共通テンプレートや固有のテンプレートが存在する部分です。
    • 意味としては、page.phppost_type_single.phpは共通テンプレートpage_slug.phppost_type_single_name.phpは各ページ固有のテンプレートです。
.
├── app
│   ├── .npm
│   ├── .composer
│   ├── assets
│   │   └── pages
│   │       ├── home
│   │       │   ├── css
│   │       │   │   └── xxxxxx.css
│   │       │   ├── img
│   │       │   │   └── xxxxxx.png
│   │       │   └── js
│   │       │       └── xxxxxx.js
│   │       ├── page
│   │       │   ├── css
│   │       │   └── img
│   │       └── post_type
│   │           ├── post_type_archive
│   │           │   ├── css
│   │           │   └── img
│   │           └── post_type_single
│   │               ├── css
│   │               └── img
│   ├── functions
│   │   ├── controllers
│   │   │   ├── resources
│   │   │   │   ├── all
│   │   │   │   │   └── all.php
│   │   │   │   ├── home
│   │   │   │   │   └── home.php
│   │   │   │   ├── page
│   │   │   │   │   └── page.php OR page_slug.php
│   │   │   │   └── post_type
│   │   │   │       ├── post_type_archive
│   │   │   │       │   └── post_type.php
│   │   │   │       └── post_type_single
│   │   │   │           └── post_type_single.php OR post_type_single_name.php
│   │   │   └── router
│   │   │       └── router.php
│   │   └── models
│   │       ├── config
│   │       │   ├── basis.php
│   │       │   └── wpcf7.php
│   │       ├── data
│   │       │   ├── csv
│   │       │   └── json
│   │       ├── modules
│   │       │   ├── xxxx.php
│   │       │   └── shortcode.php
│   │       └── pages
│   │           ├── home
│   │           │   └── home.php
│   │           ├── page
│   │           │   └── page.php OR page_slug.php
│   │           └── post_type
│   │               ├── post_type_archive
│   │               │   └── post_type.php
│   │               └── post_type_single
│   │                   └── post_type_single.php OR post_type_single_name.php
│   └── views
│       ├── pages
│       │   ├── home
│       │   │   └── home.php
│       │   ├── page
│       │   │   └── page.php OR page_slug.php
│       │   ├── post_type
│       │   │   ├── post_type_archive
│       │   │   │   └── post_type.php
│       │   │   └── post_type_single
│       │   │       └── post_type_single.php OR post_type_single_name.php
│       │   └── error
│       │       └── 404.php
│       ├── templates
│       │   ├── footer.php
│       │   └── header.php
│       └── util
│           └── analysis
│               ├── fb-ad.php
│               ├── gtm.php
│               ├── gtm_no-script.php
│               └── ytm.php
├── editor-style.css
├── functions.php
├── index.php
└── style.css

まず、前回から変更した部分で言うと、テーマディレクトリ直下のsingle.phpやarchive.phpなどのテンプレートファイルを排除しました。これは極論、index.phpだけでルーティングしても問題なかったためです。

2. ルーティング

次にルーティングの方法を変更しました。

テンプレートのロード、cssとjsのロード

前回ではテンプレートを読み込むclassとcss、jsを読み込むclassを分けていたのですが、一つのclassへまとめました。
コードで見ると下記のようになります。

変更前

router_home.php
namespace controllers\router\pages\home;

class router_home
{
    public function __construct()
    {
        $this->load_template();
    }

    # テンプレートの読み込み
    public function load_template()
    {
        require_once get_template_directory() . '/app/views/pages/home/home.php';
    }
}
loader_home.php
namespace controllers\loader\pages\home;

class loader_home
{
    public function __construct()
    {
        $this->wp_enqueue_scripts();
    }

    # css、jsの読み込み
    public function wp_enqueue_scripts()
    {
        wp_enqueue_style('home', get_template_directory_uri() . '/app/assets/pages/home/css/style.css');
        wp_enqueue_script('app', get_template_directory_uri() . '/app/assets/pages/home/js/app.js', array(), null, true);
    }
}

変更後

home.php
namespace controllers\resources\home;

class home
{
    public function __construct()
    {
        $this->wp_enqueue_scripts();
        $this->template_directory();
    }

    # css、jsの読み込み
    public function wp_enqueue_scripts()
    {
        wp_enqueue_style('home', get_template_directory_uri() . '/app/assets/pages/home/css/style.css');
        wp_enqueue_script('app', get_template_directory_uri() . '/app/assets/pages/home/js/app.js', array(), null, true);
    }

    # テンプレートの読み込み
    public function template_directory()
    {
        require_once get_template_directory() . '/app/views/pages/home/home.php';
    }
}

変更後のhome.phpのように、resourcesフォルダ内の各classへまとめました。
ポイントとしてはこのクラスがインスタンス化された時にcss、jsの読み込みを行う関数が最初に動くようにしておく事です。(テンプレートを引っ張ってくる関数を最初に動かすと画面レイアウトが崩れる場合がある)←多分、フックをちゃんと指定すれば大丈夫だと思います。

router.php

こちらは結構、仕様変更しました。

変更前

router.php
class Router
{
    public function __construct()
    {
        add_action('wp', array($this, 'front_controller'));
    }

    public function front_controller()
    {
        global $wp_query;
        global $post;

        # トップページ
        if (is_home()) {
            new models\pages\home\model_home();
            new controllers\loader\pages\home\loader_home();
            new controllers\router\pages\home\router_home();
        }
        # 固定ページ
        else if (is_page()) {
            $pagename = isset($wp_query->query['pagename']) ? $wp_query->query['pagename'] : '';
            switch ($pagename) {
                case 'unique_slug_name':
                    new \models\pages\slug_name\model_slug_name();
                    new \controllers\loader\pages\slug_name\loader_slug_name();
                    new \controllers\router\pages\slug_name\router_slug_name();
                    break;
                case 'unique_slug_name':
                    ...
                    break;
                case 'unique_slug_name':
                    ...
                    break;
                default:
                    return;
                    break;
            }
        }
        # カスタム投稿アーカイブ
        elseif (is_post_archive()) {
        ...
        }
        # カスタム投稿個別ページ
        elseif (is_singular()) {
        ...
        }
        # 404ページ
        else {
            new \controllers\loader\pages\error\loader_404();
            new \controllers\router\pages\error\router_404();
        }
    }
}

new Router();

変更後

router.php
/*------------------------------------------------------------------------------------
/* 全ページ共通
/*----------------------------------------------------------------------------------*/
# 基本設定
new \models\config\basis();
...
# 全ページで読み込むcss
add_action('wp',function(){new \controllers\resources\all\all();});
/*------------------------------------------------------------------------------------
/* トップページ
/*----------------------------------------------------------------------------------*/
add_action('wp', function() {
    if (is_home()) {
        new \models\pages\home\home();
        new \controllers\resources\home\home();
    }
});
/*------------------------------------------------------------------------------------
/* 固定ページ
/*----------------------------------------------------------------------------------*/
# 固定ページの共通テンプレート
add_action('wp', function() {
    if (is_page()) {
        $template = get_field_object('example_template');
        $value = $template['value'];
        if ($value == 'default') {
            new \models\pages\page\page();
            new \controllers\resources\page\page();
        }
    }
});

# 共通ではなくオリジナルの固定ページテンプレート
add_action('wp', function() {
    if (is_page('example')) {
        $template = get_field_object('example_template');
        $value = $template['value'];
        if ($value == 'templateA') {
            new \models\pages\page\page_slug();
            new \controllers\resources\page\page_slug();
        }
    }
});
/*------------------------------------------------------------------------------------
/* 投稿タイプA
/*----------------------------------------------------------------------------------*/
# 共通テンプレートの記事ページ
add_action('wp', function() {
    if (is_singular('post_typeA') && is_single()) {
        $template = get_field_object('example_template');
        $value = $template['value'];
        if ($value == 'default') {
            new \models\pages\post_typeA\post_type_single();
            new \controllers\resources\post_typeA\post_type_single();
        }
    }
});

# 共通ではなくオリジナルテンプレートの記事ページ
add_action('wp', function() {
    if (is_singular('post_typeA') && is_single('example')) {
        $template = get_field_object('example_template');
        $value = $template['value'];
        if ($value == 'templateA') {
            new \models\pages\post_typeA\single_slug();
            new \controllers\resources\post_typeA\single_slug();
        }
    }
});

# アーカイブ
add_action('wp', function() {
    if (is_post_type_archive('post_typeA')) {
        new \models\pages\post_typeA\post_type_archive();
        new \controllers\resources\post_typeA\post_type_archive();
    }
});
/*------------------------------------------------------------------------------------
/* 404ページ
/*----------------------------------------------------------------------------------*/
add_action('wp', function() {
    if (is_404()) {
        new \controllers\resources\error\error_404();
    }
});

前回ではrouter.phpをクラスファイルとして利用していましたが、クラスではなく、ページ単位のアクションフック付き関数にしました。こっちの方がpost_type毎の関数を一箇所にまとめられて見通しが良かったです。(前回ではテンプレート階層毎にまとめていた)

また、途中で$template = get_field_object('event_template');のような記述が入っていますが、これはカスタムフィールドの値によって使用するテンプレートが正か否かを判別しています。

というのも、固定ページも含めこの構成にすると、なにかしらの工夫をしなければ、投稿編集画面からテンプレートの選択ができなくなります。( ̄Д ̄;)

私は対策としてAdvanced Custom Fieldsを使って投稿編集画面右側にテンプレート選択のフィールドを追加しました。

この辺も含め、まだまだ改良の余地がありそうです...

3. All in One SEO Packとの互換性

このディレクトリ構成にするとwp_title()がテンプレート内で使えなくなりました。
4.4ぐらいから非推奨にはなっていたものの、4.9とかでもまだ動いていたので放置していましたが、これを機にadd_theme_support('title-tag');へ移行しました。

しかし、思わぬところで落とし穴が...
All in One SEO Packの機能で、投稿編集画面内にTitleを個別に設定できるようにするフィールドを追加できますが、そこに入力されたTitleが読み込まれなくなってしまった...(SEO担当に注意されてしまいました...(´・ω・`))

下記はこちらの不具合で対応したコードです。
調べると参考になる記事がたくさん出てきましたが、どうやら_aioseop_titleでフィールドに入力した値を取れるみたいですね。

basis.php
namespace models\config;

class basis
{
    public function __construct()
    {
        add_filter('pre_get_document_title', array($this, 'custom_single_title'));
        ...
    }

    # 個別記事ページへAll in seo packで設定したタイトルを出力
    public function custom_single_title($title)
    {
        if (is_single()) {
            global $post;
            if (get_post_meta($post->ID, '_aioseop_title', true)) {
                $title = get_post_meta($post->ID, '_aioseop_title', true) . ' | サイトの名前';
            }
        }
        return $title;
    }
    ...
}

まとめ

私の場合は、すでにwordpressで構築されたサイトを引き継いでいるケースですが、サービスの初期構築段階で、ある程度の規模のサイトだという事が分かっているならlaravelなどのフレームワークを選択しましょう。

ここまで書いておいてですが、wordpressでMVCテーマを作るのはちょっと大変ですね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

php-master-changes 2019-03-23

2019-03-23

krakjoe: For consistency with Windows, and because ZTS is not experimental or a "maintainer" feature, this commits renames --enable-maintainer-zts to --enable-zts in the autotools build, and related documentation

  • https://github.com/php/php-src/commit/161adfff3f437bf9370e037a9e2bf593c784ccff
  • --enable-maintainer-zts を --enable-zts にする修正
  • マルチスレッドで速くしたいがために ZTS 版ビルドする時 maintainer って何だよ、とつい最近に俺も思ってた
  • 「PHP でマルチスレッド?一体何の話だい?」と思う向きもあるかもしれないが、なんなら今のところ 1.3 〜 1.5 倍くらいにしか性能上がらない JIT より効くケースがあるというのをマリオで試した俺は知っている
  • でもこれ 7.4 で deprecation にしつつエイリアスで入れるとかないと、PHP をビルドする系のツールとかが困るんじゃないかな、確かに期間はあるけど急に 8 で変わる感じになっちゃうし
  • PR:3974

alekitto: fix bug #76801: phpdbg too many open files error

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

php-master-changes 2019-03-22

この日は AST の行番号管理の修正、重複コードをまとめる/削除する等のリファクタリング、新しいカスタムオブジェクトシリアライゼーションの実装、ReflectionClass::getMethods() に null を渡すと空配列を返す問題の修正、mysqli が unbuffered クエリでメモリリークする問題の修正、テストの微修正があった!

2019-03-22

nikic: Switch to bison location tracking

rjhdby: Deduplicate code in zend_builtin_functions.c

rjhdby: Make zend_hash_sort() return void

nikic: Remove HAVE_PCRE/HAVE_BUNDLED_PCRE checks

nikic: Implement new custom object serialization mechanism

nikic: Fixed bug #77772

nikic: Fixed bug #77773

remicollet: ensure pcre.jit=1 for these tests

remicollet: ensure pcre.jit=1 for this test

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

プリペアードステートメントでSQLを作成するときに同じ変数を2回使いたい

プリペアードステートメントを使うときにハマったので備忘録。

例えば、

$sql = 'SELECT * FROM orders WHERE buy_user = :user_id OR sale_user = :user_id AND delete_flg = 0';
$data = [':user_id' => $user_id];

だとエラーを吐く。

なので、

$sql = 'SELECT * FROM orders WHERE buy_user = :user_id OR sale_user = :id AND delete_flg = 0';
$data = [':user_id' => $user_id, ':id' => $user_id];

としなくてはならない。理由はわからないがPDOはそういう仕様らしい。バインドするときのキーは複数あったらだめらしい。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker-compose build でE: Failed to fetch http://... Writing more data than expected (1123368 > 1086978)が発生する時の対応方法

環境

OS:macOS Mojave 10.14.3
Docker:18.09.2, build 6247962
docker-compose:1.23.2, build 1110ad01
docker-machine:0.16.1, build cce350d7
php:7.1.23

事象

dockerを以下のコマンドでビルドをすると

docker-compose build --no-cache workspace

.
. 省略 
.

+ groupadd -g 1000 laradock
+ useradd -u 1000 -g laradock -m laradock -G docker_env
+ usermod -p * laradock -s /bin/bash
+ apt-get install -yqq apt-utils php7.1-zip nasm
E: Failed to fetch http://220.152.42.162:80/data/06abb81878b24fba/archive.ubuntu.com/ubuntu/pool/universe/n/nasm/nasm_2.11.08-1ubuntu0.1_amd64.deb  Writing more data than expected (1088616 > 1086978)

となりビルドがエラーで落ちるといった事象が発生しました。

対象となる方は少ないかと思いますが、もし同じ事象でお困りの方がいましたら、一旦私が行った処置をシェアしたいと思います。
お役に立てれは幸いです。

解決ではないが一旦これでエラー回避

以下のファイルの対象の部分をコメントアウトするだけです。

laradock/workspace/Dockerfile
# always run apt update when start and after add new source list, then clean up at end.
RUN set -xe; \
    apt-get update -yqq && \
    pecl channel-update pecl.php.net && \
    groupadd -g ${PGID} laradock && \
    useradd -u ${PUID} -g laradock -m laradock -G docker_env && \
    usermod -p "*" laradock -s /bin/bash && \
    apt-get install -yqq \
      apt-utils && \
      #
      #--------------------------------------------------------------------------
      # Mandatory Software's Installation
      #--------------------------------------------------------------------------
      #
      # Mandatory Software's such as ("php-cli", "git", "vim", ....) are
      # installed on the base image 'laradock/workspace' image. If you want
      # to add more Software's or remove existing one, you need to edit the
      # base image (https://github.com/Laradock/workspace).
      #
      # next lines are here becase there is no auto build on dockerhub see https://github.com/laradock/laradock/pull/1903#issuecomment-463142846
      - libzip-dev zip unzip \
      + # libzip-dev zip unzip \ コメントアウトした
      # Install the zip extension
      - php${LARADOCK_PHP_VERSION}-zip \
      + # php${LARADOCK_PHP_VERSION}-zip \ コメントアウトした
      # nasm
      - nasm && \
      + # nasm && \ コメントアウトした
      php -m | grep -q 'zip'

結論

時間がなくなぜエラーが発生しているのかまだわかっていません。
私が必要とする環境では、必要のないモジュールでエラーが発生していたので一旦コメントアウトで対応しました。

もし解決方法をご存知の方がいらしたら是非教えていただけると嬉しいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPで関数を書く方法

PHPで関数を作る方法

こんにちは、未来電子テクノロジーでインターンをしているueken0403です。
Progate/PHPのPHPⅠを学習し終えたので、得た学びを共有したいと思います。
今回は、PHPで関数を作る方法を解説したいと思います。

プログラミング初心者であるため、内容に誤りがあるかもしれません。
もし、誤りがあれば修正するのでどんどん指摘してください。

PHPでは関数が使える

PHPには、「組み込み関数」という便利な関数が元々埋め込まれており、決められた命令を打ち込めばそれらを使うことができます。
関数は、
[関数]()
という風に書くのですが、この()に与える数を「引数」と言います。
ちなみに読み方は「いんすう」ではなく「ひきすう」です。
例えば、strlenという関数があるのですが、これは引数の文字列の文字数を数えて返してくれる関数です。

PHPでは関数が作れる

関数を作るには「function 関数名(){ 処理 }」という書き方をします。
関数名は自由につけることができます。
作った関数を呼び出すときは、「関数名()」という風に書きましょう。

簡単な関数の例

めちゃくちゃ簡単ですが、「三角形の面積の公式」の関数を作ってみましょう。
三角形の面積の公式は当然「底辺×高さ÷2」ですね。
普通は英語を使うのですが、今回は便宜上日本語で行きますね。
自分としてもそっちの方が整理しやすいのでご容赦ください。

では関数の名前を「三角形の面積」にして、1つ目の変数を「$底辺」2つ目の変数を「$高さ」とします。
そうした場合、目的の関数は、

function 三角形の面積($底辺,$高さ){echo $底辺*$高さ/2;}

となります。

これで「三角関数の面積(3,4);」のように呼び出し、引数を入力すれば勝手に計算をしてくれます。(答えは6)

まとめ

今回は、PHPで関数を作る方法を解説しました。
用意されたものだけでなく、自分で関数を作れるのはシンプルに便利だし、応用の幅が広そうですね。
まだまだ初心者ですが、プログラミングの可能性を感じるレッスンでした。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む