20200808のPHPに関する記事は8件です。

CakePHP3 の Cell を利用してアクセスカウンターを実装

はじめに

私が運営しているブログ (駆け出しです) にサイトへの訪問者を表示させたかったので、アクセスカウンターを実装してみました。
CakePHP3 にはCell という機能があるので、こちらの機能を使ってみました。
※ブログ『CerisierAvantech FC-スリジエ・アバンテック FC』
URL:https://avantech-fc.com/

環境

  • OS: Windows10
  • PHP: 7.4.1

仕様

  • リロードしてもカウントされない
  • 自宅からのアクセスは対象外

Cellのファイルを作成 (コントローラーの役割)

  • display()では実行するための条件文、内部関数のgetCount()ではカウント処理を行なう。
  • カウントを行う際は $counter_file で指定したファイルに書き込む。
  • ○○○.○○○.○○.○○○ には自宅のIPアドレスが入ります。
site\src\View\Cell/CountsCell.php
<?php
namespace SiteApp\View\Cell;

use Cake\View\Cell;

/**
 * Counts cell
 */
class CountsCell extends Cell
{
    /**
     * count method
     * @return void
     */
    public function display()
    {
        session_start();
        $countTarget = false;

        if(@$_SESSION['access'] === 1) { // セッションが存在しているときはカウント対象外
            $countVal = $this->getCount($countTarget);

        } else { // セッションが存在していないとき
            if($_SERVER['REMOTE_ADDR'] !== '○○○.○○○.○○.○○○') { // 管理者のIPアドレス以外の時のみカウント処理を実行
                $countTarget = true;
                $_SESSION['access'] = 1;
            }
            $countVal = $this->getCount($countTarget);
        }
        $this->set('countVal', $countVal);
    }

    // *********************************************************
    // * User-defined functions
    // *********************************************************
    /**
     * Get Count Number
     * @param boolean
     * @return integer
     */
    private function getCount($countTarget) {
        $counter_file = 'avantech/counter.txt';
        $fp = fopen($counter_file, 'r+'); // ファイルがないときはエラーを返す
        $counter_length = 7;
        $countVal = fgets($fp, $counter_length);

        if ($fp && $countTarget) {
            if (flock($fp, LOCK_EX)) {// 排他ロック。読み取り/書き込みともに不可。
                $countVal++;
                rewind($fp); // ファイルポインタの位置を先頭に戻す

                if (fwrite($fp, $countVal) === FALSE) {
                    echo ('<p>'.'入場者数のカウントに失敗しました'.'</p>');
                }
                flock ($fp, LOCK_UN); // ファイルロックを解放。
            }
        }
        return $countVal;
    }
}

テンプレート

site/src/Template/avantech/Cell/Counts/display.ctp
<section class="access-counter">
    <p>ご来場ありがとうございます。<br>
    あなたは<span><?= $countVal ?>人目</span>のサポーターです。</p>
</section>

Cell の呼び出し (サイドメニューで表示)

CountsCell.php から変数を受け取り表示させる。

site/src/Template/avantech/Layout/default.ctp
    <aside class="sidebar">
      <?= $this->cell('Counts'); ?>
    <aside>

さいごに

下記参考サイトを参考になんとか実装して、本番環境にアップはしてみたものの、正確にカウントされていない(Googleアナリティクスの訪問数よりもはるかに多い)ので、何かがおかしい状態だと思われます。。
まずは備忘録として残しておきます。
改善点等がありましたら、ご指摘いただけますと幸いです。

参考

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

【PHP,Laravel】PHPから変数や配列をまとめて送り、Laravelで表示する方法

とても悩んだので、プログラムを簡略化して記録します。

問題点

name  | number | text
test  |      1 | test
sample|      2 | sample

以上のようなとき、一行目しか変数に入らない!

できた時のプログラム

index.php
            $count = 1;

            $db = pg_connect("host=host port=5432 dbname=dashboard user=postgres password=○○" ); 
            if(!$db)throw new Exception("DB接続に失敗しました。");

            $search = pg_query("SELECT *FROM board_posted;");
            if (!$search)throw new Exception('クエリーが失敗しました。');

//ここからポイント
            for($i=0;$i<$rows_count;$i++){
                $rows[] = pg_fetch_array($search, $i, PGSQL_ASSOC);
            }

        $info = array(
            "count"=> $count,//数値
            "board"=> $rows//配列
        );
        print_r($rows);

        return view('dashboard')->with('info',$info);

print_r($rows)の結果は

Array (
[0] => Array (
 [number] => 0 [name] => hoge [text] => This is a sample.
 ) 
[1] => Array (
 [number] => 1 [name] => hoge [text] => This is a sample2.
 ) 
)
index.blade.php.html
      @for($i = 0; $i < $info['board_count']; $i++)
                  <div class="card" style="width: 60rem;">
                  {{$info['board'][$i]['number']}}<!--ここで配列から取り出す-->   
                  </div>
                  <div class="card-body">
                      <table border="1">
                          <tbody>
                          <tr>
                            <td>{{$info['board'][$i]['name']}}</td><!--ここで配列から取り出す-->
                          </tr>
                          {{$info['board'][$i]['text']}}<!--ここで配列から取り出す-->
                      </tbody>
                      </table>
                  </div>
      @endfor

当たり前かもしれませんが、$rows[]と配列にしたらできました。
あとlaravel側での取り出し方がポイントでした。

できなかった時のプログラム

index.php
            $count = 1;

            $db = pg_connect("host=host port=5432 dbname=dashboard user=postgres password=○○" ); 
            if(!$db)throw new Exception("DB接続に失敗しました。");

            $search = pg_query("SELECT *FROM board_posted;");
            if (!$search)throw new Exception('クエリーが失敗しました。');

            $rows = pg_fetch_array($search, $i, PGSQL_ASSOC);//一行の配列は入る

        $info = array(
            "count"=> $count,//数値
            "board_number"=> $rows['number'],//1個しか入っていなかった
            "board_name"=> $rows['name'],//1個しか入っていなかった
            "board_text"=> $rows['text'],//1個しか入っていなかった
        );
        print_r($rows);

        return view('dashboard')->with('info',$info);

まとめ

このような配列の中に配列があるものを三次元配列というそうです。
普通の配列か、そうでない配列かをわかる必要がありました。
当たり前だなと思いました。が、使わなければ忘れます…。
もっと簡単な記述方法があればご教授ください。
以上です。

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

Laravel×Docker×Dusk×Seleniumでのテスト実行

はじめに

インターン現場でLaravelを使用しており、テスト環境の構築を行いました。

テストツールとしてDuskを使用し、seleniumとの連携という構成をとり、導入で何度かつまづいたので自分メモとして残したいと思います。

Duskって?

-ドキュメント
Laravelが標準で用意している、ブラウザの自動操作によるテストAPI。
テスト中はブラウザが勝手に動くのを眺めながらのんびりできます(笑)

Duskは「$php artisan dusk:install」でコマンドインストール後、すぐに使えます。
しかし今回は現場の意向でデフォルトのChromeDriverの使用ではなくseleniumを使用することになりました。

目標

--開発環境---
  • Laravel 6.18.26
  • Docker(Docker-compose) 19.03.8

docker環境でDusk × seleniumでテストを実行することを目標とします。
開発環境でdockerを使用していたので、selenium用のコンテナを準備するところからはじめました。

以下、順にまとめていきます

1.seleniumのコンテナを準備

selenium用のコンテナを定義するために、docker-compose.ymlに以下を追記。

docker-compose.yml
selenium:
    image: selenium/standalone-chrome-debug
    ports:
      - 4444:4444
      - 5900:5900
    container_name: selenium-container
    depends_on:
      - nginx
    privileged: true

ポートを2つ開放してますが、

4444 ⇨ selenium serverのポート
5900 ⇨ VNCのポート

です。
[参考]VNCについて

2.コンテナ起動

terminal

$ docker-compose up

...

Creating mysql-container      ... done
Creating phpmyadmin-container      ... done
Creating php-fpm-container         ... done
Creating nginx-container           ... done
Creating selenium-container        ... done

seleniumのコンテナが無事立ち上がりました。
php-fpmのコンテナ中に入ります。

terminal
$ docker exec -it php-fpm-container bash

3.Duskのインストール

ほぼ公式の引用です。
以下のコマンドはコンテナ中で行ってください!

terminal(コンテナ内)
# 共存パッケージのインストール
$ composer require --dev laravel/dusk

# dusk install
$ php artisan dusk:install

dockerを起動するとselenium portとVNCポートが開放されます。

4.seleniumの接続(:4444)

デフォルトのChromeDriveではなくseleniumを使用する場合、tests/DuskTestCase.phpを書き換える必要があります。

DuskTastCase.php
#driverメソッドを以下に書き換え

protected function driver()
    {
        return RemoteWebDriver::create(
            'http://selenium:4444/wd/hub', DesiredCapabilities::chrome()
        );
    }

ここで、docker-compose.ymlで定義した4444portが登場します!

5.VNCの接続(:5900)

今度はVNCに接続を行います。
macのfinderからlocalhost:5900に接続します。

スクリーンショット 2020-07-31 20.17.43.png

↓dockerが起動していればこんな感じでseleniumの画面が表示されました!!
スクリーンショット 2020-07-31 20.18.30.png

6.テストの実行

以下の簡単なログインテストを実行してみました。

LoginTest.php
<?php
namespace Tests\Browser;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Laravel\Dusk\Browser;
use Tests\DuskTestCase;


class LoginTest extends DuskTestCase
{
    /**
     * A Dusk test example.
     *
     * @return void
     */
    public function test_02_PassReset(){

        // login test
        $this->browse(function (Browser $browser) {
            // ページ"/login"で文字列"LARAVEL"を確認
            $browser->visit('login')
                    ->assertSee('LARAVEL');
        }); 
    } 
}

こちらのテストを実行。

スクリーンショット 2020-07-31 22.53.20.png

↑テスト実行時のキャプチャです。きちんとテストブラウザが動いて/loginにアクセスできています!

terminal
$ php artisan dusk
PHPUnit 8.5.8 by Sebastian Bergmann and contributors.

..                                                2 / 2 (100%)

Time: 4.4 seconds, Memory: 18.00 MB

OK (2 tests, 2 assertions)

テスト結果も◎でした!!!

まとめ

ブラウザテスト自体が初めてだったので、単純に楽しかったです!
時間があればselenium関連でスクレイピングとかにも挑戦したい!!!

※誤りや質問等ございましたらコメント頂けますと幸いです。

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

Laravelのコンストラクタとは

はじめに

コンストラクタとはクラスからインスタンスを生成するとき(オブジェクトがnewによって作成されるとき)に自動的に呼び出されるメソッドです。
オブジェクト作成時に初期化処理が必要な場合、コンストラクタ内に記述しておけば自動的に実行してくるので大変便利です。

コンストラクタを用いて実装してみる

class Job
{
    protected $job_service;

    public function __construct(
        JobService $job_service
    ) {
        $this->job_service = $job_service;
    }

    public function main()
    {
        $recruiting_jobs = $this->job_service->recruitingJobs();
        return $this->render($recruiting_jobs);
    }
}

メソッド名の部分を__constructとするとコンストラクタとなります。
コンストラクタのアクセス制限はpublicのみです。

おわりに

コンストラクタに実装すれば必要なたびごとに初期化の実装が不要になるので便利ですね。

参考:コンストラクタ - Laravel学習帳

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

PHPのIFを使っての条件分岐

PHP初心者です。

PHPの条件分岐について質問させていただきます。
inputタグに値が入ったらpタグを出現させる条件分岐をするにはどうしたらいいでしょうか。
最初の段階ではpタグは無い状態とします。

<form action="index.php" method="post">
<input type="text" name="search">
</form>

<p>
<a href="index.php">
inputに値が入ると表示される
</a>
</p>

試したこと

<form action="index.php" method="post">
<input type="text" name="search">
</form>

<?php
$txt = '
<p>
<a href="index.php">
inputに値が入ると表示される
</a>
</p>';
?>

<?php
if (isset($search));{
echo $txt;
} ?>

var_dumpで確認したところ、値が入る以前も後もpタグは表示されていました。

送信先は、同じ「index.php」です。
よろしくお願いします。

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

【初心者が悩む】RubyとPHPとPythonどれが良いのか?

まずはじめに

プログラミングをやってみようとしてまず考える事が「どのプログラミング言語から初めよう?」というところではないでしょうか。

そしてググっていくとRubyというプログラミング言語が真っ先に情報として入ってくるのではないでしょうか?

Rubyが真っ先に初心者に引っかかる理由は何と言っても「プログラミングスクールの殆どがRubyを激推ししているから」に尽きます。

ちなみに更にググってみるとRubyと似た言語にPHPとPythonがあるのです。

一体どの言語を勉強すれば良いのでしょうか?

RubyとPHPとPythonのイメージ

まず、殆ど知識が無い状態の私が持っていたイメージ。

  • Ruby - 初めて耳にする。
  • PHP - 古臭い。
  • Python - 初めて耳にする。

結果、なんとなくPHPは聞いたことがある...という程度です。私の場合は、ワードプレスでブログ運営していた時期が少しばかりあったのでPHPというプログラミング言語の存在は知っていました。

PHPは古臭いと書きましたが、ググってみると、

  • Ruby - 1993年2月24日生まれ(1995年12月発表)
  • PHP - 1994年生まれ(1995年6月8日発表)
  • Python - 1990年生まれ(1991年発表)

PHPがこの3つのプログラミング言語の中で新しいことが分かりました。イメージだけで、古臭いと決め付けていたPHPに謝りたいです。

PHPだけ少し違う!?

比較されるには何か理由がある訳ですが、この3つのプログラミング言語は、サーバーサイドでとても使われている言語です。

そして、記述の方法がとてもよく似ています。

例えばシンプルにHello world!を3つの言語で使用してみましょう!

Ruby
print "Hello World!"
PHP
<?php 
echo "Hello World!"; 
?>
Python
print("Hello world!")

......
....
..

気づきましたか!?
RubyとPythonは書き方が似ていますが、PHPだけ少しゴチャっとしていますよね。先ほどは、記述方法がよく似ていると書きましたが、実はよくよく見てみるとPHPだけどこか違います。

なぜ、PHPだけ少しゴチャっとしているのかはPHPのWikipediaに下記のような記載を見つけましたが、これが答えなのではないでしょうか?

元々PHPはプログラミング言語と言えるものではなく、単にテンプレート的な処理を行うだけであったが、度重なる機能追加やコードの書き直しにより、2017年現在リリースされているPHP 5やPHP 7は目的によらず汎用的に使うことの出来るスクリプト言語となっている。

要するに
PHPは元々、プログラミング言語とは違うものだった。
それが答えだと思います。

RubyとPHPとPythonはなぜ比較されるのか?

ここでは大きく考えられる2つの要因について書きます。

フレームワークが凄い

フレームワークは、アプリケーションを作るときに開発工程を大幅に短縮することのできるソフトウェアのことで、このフレームワークが充実している=凄い機能のアプリを短期間で作成することのできる。使える人が使えば、魔法のアイテムのようなものですが、今回紹介したRubyとPHPとPythonには、

  • Ruby - Ruby on Rails
  • PHP - Laravel
  • Python - Django

上記のような素晴らしいフレームワークが揃っています。

近年伸びているメジャーサイトが利用している

やっぱりここに尽きるのではないでしょうか?

  • Ruby - Twitter, Hulu etc...
  • PHP - Wikipedia, Facebook etc...
  • Python - Googleの検索エンジン, YouTube etc...

どのプログラミング言語も甲乙付け難い一流企業が利用しています。

結局どの言語を学べばいいのか?

興味を持った言語を学べば良いと言ったらそれで済む話ですが、

趣味ではなく就職や転職の為に学んでいるのならば単純に求人数だけを見てみると、
PHP>=Ruby>Python
の傾向なので、PHPが一番なのかもしれません。
あくまで、求人数だけでの話ですが...。

参考: 【PHP/Python/Rubyを比べてみた】言語のメリットとデメリット、特徴まとめ

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

PHPで他サイトのスクレイピング【作成中】

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

PHPで他サイトのスクレイピング

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