なおのつぼやき

Webエンジニアです。PHP/Laravel、あとRustを少々

Rustで.envファイルに設定した値を使う

Rustで.envファイルの値を使った際のメモです。

環境

  • Rust 1.47.0

やったこと

dotenvというクレートを使います。

https://crates.io/crates/dotenv

  1. Cargo.tomldotenvを追加します。
[dependencies]
dotenv = "0.15.0"
  1. プロジェクトルートに.envファイルを作成し、任意の環境変数を用意します。
URL=localhost
  1. main.rsを次のように書き換えます。
use dotenv::dotenv;
use std::env;

fn main() {
    dotenv().ok(); // ここで.envファイルの値を読み込んでいます。
    let value = env::var("URL").expect("URL is not found");

    println!("URL : {}", value);
}

標準ライブラリのstd::env::varを使うことで環境変数に取得は可能です。
dotenv()を実行しなかったら環境変数に追加されないのでエラーになります。

  1. cargo runを実行する。
$ cargo run
   Compiling dotenv v0.1.0 (`任意のパス`/dotenv)
    Finished dev [unoptimized + debuginfo] target(s) in 1.33s
     Running `target/debug/dotenv`
URL : localhost

無事に.envファイルに設定した値が取得できました。

RustからRedisを使ってみた

RustからRedisを使ってみた時のメモです

環境

  • Rust 1.47.0

準備

Rustのプロジェクトを作成

任意の場所でcargo newを実行します

$ cargo new redis
$ cd redis

docker-compose.ymlの内容

RedisはDockerを使って用意しますのでdocker-compose.ymlファイルを作成し、
以下の内容を追加します

version: '3'
services:
  redis:
    image: redis
    ports:
      - 6379:6379

用意したらあとは起動しておきます

$ docker-compose up -d --build

やったこと

今回はredisクレートを使ってみようとみます

https://crates.io/crates/redis

まずはCargo.tomlにクレートを追加します

[dependencies]
redis = "0.17.0"

その後にmain.rsの編集します

use redis::Commands;

fn main() {
    // redisに接続
    let clinet = redis::Client::open("redis://localhost/").expect("error");
    let mut connection = clinet.get_connection().expect("error");

    // 新規
    let _: () = connection.set("key", 10).unwrap();

    // 取得
    let result: i32 = connection.get("key").unwrap();

    println!("{}", result);

    // 更新
    let _: () = connection.set("key", 20).unwrap();

    // 取得
    let result: i32 = connection.get("key").unwrap();

    println!("{}", result);

    // 削除
    let result: i32 = connection.del("key").unwrap();

    // 1 -> 成功 0 -> 失敗
    println!("{}", result);
}

実行

$ cargo run
   Compiling redis v0.1.0 ('任意の場所'/redis)
    Finished dev [unoptimized + debuginfo] target(s) in 4.87s
     Running `target/debug/redis`
10
20
1

新規、更新、取得、削除と一連の流れは出来た感じです

Mockeryを使った時にprotectedメソッドのモックを作る

こんなクラスがありました

<?php

class TestClass
{
    public function aaaa(): string
    {
        return $this->bbbb();
    }

    protected function bbbb(): string
    {
        return 'bbbb';
    }
}

これをMockeryを使ってbbbbメソッドの返す値を変えようと思います

<?php

use PHPUnit\Framework\TestCase;
use Mockery as m;

class TestClassTest extends TestCase
{
    public function test1(): void
    {
        $mock = m::mock(TestClass::class)
            ->makePartial();
        $mock->shouldReceive('bbbb')-> andReturn('cccc');

        $this->assertSame('cccc', $mock->aaaa());
    }
}

このテストを実行すると次のようなエラーが出てきます

$ vendor/bin/phpunit tests/TestClassTest.php 
PHPUnit 9.2.6 by Sebastian Bergmann and contributors.

E                                                                   1 / 1 (100%)

Time: 00:00.043, Memory: 4.00 MB

There was 1 error:

1) Tests\TestClassTest::test1
InvalidArgumentException: bbbb() cannot be mocked as it is a protected method and mocking protected methods is not enabled for the currently used mock object. Use shouldAllowMockingProtectedMethods() to enable mocking of protected methods.

protectedメソッドは普通にやるとモックにはできないようです
エラーメッセージに書いてある通りshouldAllowMockingProtectedMethods()を使って書き直してみます

<?php

use PHPUnit\Framework\TestCase;
use Mockery as m;

class TestClassTest extends TestCase
{
    public function test1(): void
    {
        $mock = m::mock(TestClass::class)
            ->shouldAllowMockingProtectedMethods() // この1行を追加
            ->makePartial();
        $mock->shouldReceive('bbbb')-> andReturn('cccc');

        $this->assertSame('cccc', $mock->aaaa());
    }
}

あたらめて実行

$ vendor/bin/phpunit tests/TestClassTest.php 
PHPUnit 9.2.6 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 00:00.057, Memory: 4.00 MB

OK (1 test, 1 assertion)

成功です

一応、マニュアルに書いてありましたね readouble.com

PHPからS3へのファイルアップロードをLocalStackを使ってやってみる

ローカル環境からS3にファイルをアップするために本物を用意するのが面倒になっていた際にLocalStackと言うものを見つけたので使ってみた。

LocalStackって何

  • AWSのサービスのモックを用意してくれるすごいやつ

github.com

  • 今回はS3のモックを使ってみる

環境

  • PHP 7.4.10
  • Composer 1.10.13
  • LocalStack 0.11.6

準備

docker-compose.ymlの内容

version: '3'
services:
  localstack:
    image: localstack/localstack
    ports:
      - 4566:4566
    environment:
      - SERVICES=s3
      - AWS_ACCESS_KEY_ID=dummy
      - AWS_SECRET_ACCESS_KEY=dummy
      - AWS_DEFAULT_REGION=ap-northeast-1
  • ポートはLocalStackのv0.11.5以降は4566のみになったので1つだけ指定する
  • SERVICESで使うサービスを指定する(今回はS3のみ指定)
  • AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYの値はなんでも良いです
  • AWS_DEFAULT_REGIONは東京リージョン
  • 永続化の設定とかあるけど今回はなし

Docker起動

$ docker-compose up -d --build

以降は起動している前提で書いていきます。

バケット作成

LocalStackのコンテナにAWS CLIも一緒に入っていたのでそこからコマンドでバケットを作成する。

$ docker-compose exec localstack aws --endpoint-url=http://localhost:4566 s3 ls s3://

$ docker-compose exec localstack aws --endpoint-url=http://localhost:4566 s3 mb s3://local-test
make_bucket: local-test

$ docker-compose exec localstack aws --endpoint-url=http://localhost:4566 s3 ls s3://
2020-10-11 21:47:34 local-test

s3にファイルアップロードするPHPのコード

パッケージのインストール

AWS SDK for PHPを使いたいのでComposerを使ってインストール

$ composer require aws/aws-sdk-php

PHPのコード

<?php

require_once 'vendor/autoload.php';

use Aws\S3\S3Client;

$config = [
    'credentials' => [
        'key' => 'dummy',
        'secret' => 'dummy',
    ],
    'region' => 'ap-northeast-1',
    'version' => 'latest',
    'endpoint' => 'http://localhost:4566',
    'use_path_style_endpoint' => true,
];

$s3 = new S3Client($config);

// アップロード
$result = $s3->putObject([
    'Bucket' => 'local-test',  // バケット名
    'Key' => 'hello.txt',      // s3のアップロード先
    'Body' => 'hello world!!', // ファイルの内容
]);

echo 'ファイルのURL => ' . $result['ObjectURL'] . PHP_EOL;

// 内容の取得
$result = $s3->getObject([
    'Bucket' => 'local-test',  // バケット名
    'Key' => 'hello.txt',      // s3のアップロード先
]);

echo 'ファイルの内容 => ' . $result['Body'] . PHP_EOL;

大事なところはendpointuse_path_style_endpointです。 LocalStackを使うと実際のS3のURLとは異なるなのでendpointバケット作成で使ったhttp://localhost:4566を設定する必要がある。

ただし、指定することでendpointhttp://{バケット名}.localhost:4566となり実行すると名前解決できずエラーが発生します。
そこでuse_path_style_endpointtrueを設定することでendpointがパス形式(http://localhost:4566/{バケット名})になり、実行可能になる。

動かしてみる

$ php s3.php
ファイルのURL => http://localhost:4566/local-test/hello.txt
ファイルの内容 => hello world!!

ファイルURLの表示とアップした内容の取得が表示していれば成功です。

確認

AWS CLIを使ってファイルがアップできているか見てみる。

$ docker-compose exec localstack aws --endpoint-url=http://localhost:4566 s3 ls s3://local-test
2020-10-11 23:49:33         13 hello.txt

ファイル名が表示していればOKです。

まとめ

LocalStackを使えば簡単にS3へのアップロードができました。
(ただ、エンドポイントあたりがややこしいです)

実際にS3を使っているとお金が、、、とかなったりしていろいろ面倒ですが、 LocalStackを使えばその辺は気にしなくてよくなるはず。

リモートワークが始まってからデスク周りの買ったものたち

私の勤めている会社でリモートワークが始まって半年が経過しました。
半年もやっているのでデスク周りで色々購入したものがあるのでちょっとご紹介です。

モニター & モニターアーム

元々は21インチのモニターを使っていたんですが、ちょうど5月に購入したモニターが発売したので買っちゃいました。
ついでにモニターアームも一緒に購入です。

パソコンスタンド

ノートパソコンで仕事をしている為か、目線が下に行って作業していることが多いので、
高さや角度の調整が出来るように購入しました。

キーボード & マウス

Apple Magic Keyboard - 日本語(JIS)

Apple Magic Keyboard - 日本語(JIS)

  • 発売日: 2015/10/14
  • メディア: Personal Computers

パソコンスタンドに乗せているとMacBookのキーボードでは打ちづらかったりするので、
外付けのキーボードとマウスを購入しています。
それぞれメーカーに対するこだわりがなかったのでキーボードは純正で、マウスは安かったやつを選んでいます。
(マウスも純正でもよかったかもって買ってから思ったりしています。)

まとめ

今のところはこれくらいです。
これからもリモートワークは続くはずなので、半年後には別のものを買ったり、買い替えたりしていると思います。