底辺SE奮闘記

年収300万SEブログ

【Stripe・Laravel Cashier】Attempt to read property "default_payment_method" on null で困った

現象

表題の通り。Stripeのテスト中に、

Attempt to read property "default_payment_method" on null

というよくわからないエラーが出る。

解法

下記を確認

  • Billableモデル(\App\Models\Userなど)に対応するユーザがStripe上に存在しているか。
  • Billableモデルに設定されている支払い方法がStripe上に存在しているか

【phpunit】dataProvider内のタイムゾーンがUTCな件

えらい目にあったので共有。

現象

タイムゾーンをAsia/Tokyoに設定しているのに、UTCで内部処理されている(今回の場合はCarbon)

環境

  • Larvel ^8.75 時刻設定 日本対応済
  • phpunit 9.5.19

問題のあるテストコード

下記のようなテストコードでテストを行っていた

<?php
use Carbon\Carbon

// 中略

public function hogeData() {
    return [
        "テストA" => [new Carbon("2000-01-01 10:00")]
    ];
}

/**
hogeなテスト
@dataProvider hogeData
@param Carbon $_date 日付
*/
public function test_hoge($_dateA)
{
    //中略
    $_dateB = new Carbon("2000-01-01 10:00");
    
    // ここで$_dateAと$_dateBは同じ日時か
    // 判定を行うとfalseとなる!
}

//中略

上記コードで$dateAと$dateBが同一日時か判定すると、falseとなった。

検証

ちょっと意味がよくわからないので、上記コードを下記コードのように変更し、タイムゾーンの確認を行った。

<?php
// 中略
public function hogeData() {
    echo ("A : " . date_default_timezone_get());
    return [
        "テストA" => [new Carbon("2000-01-01 10:00")]
    ];
}

// コメント部略
public function test_hoge($_dateA)
{
    //中略
    echo ("B : " . date_default_timezone_get());
}

//中略

上記のようなコードを実行した結果。

実行部位 タイムゾーン
echo A UTC
echo B Asia/Tokyo

となった。全く意味がわからないが、そういうものらしい。

結論

Carbon変数をdataProvider内に置く場合は、

new Carbon("2000-01-01", "Asia/Tokyo")

としておくほうが安全である。

【CPI・Python】ACEプラン Pythonについて

インストール場所

/usr/local/bin/python

SSHログインではみえない。実行もできない。

バージョン

2.7

3系は利用できない。萎え。

実行方法 1

PHP上で動かすと簡単。

以下一例。

<?php
exec('python /usr/home/XXXXXXXX/html/test.py', $output);
print_r($output);

【Xcode・iOS】"An SSL error has occurred and a secure connection to the server cannot be made."に対処

タイトル通り、

An SSL error has occurred and a secure connection to the server cannot be made.

のエラーに対応します。

上記エラーの原因はHTTPS接続がAppleのセキュリティ水準に達していないことにあります。

検索エンジンで検索するといくらでも回答が出てきますが、以外とハマる点についても言及しておきます。

解決できるエラー文言

An SSL error has occurred and a secure connection to the server cannot be made.
App Transport Security has blocked a cleartext HTTP connection since it is insecure. Use HTTPS instead or add Exception Domains to your app's Info.plist.

などなど

環境

  • Xcode13
  • iOS15

対応

通常の解法

  1. プロジェクトの管理画面を見る
  2. プロジェクトのTARGETSを選択
  3. 「Signing & Capabilities」を開く
  4. 左上の「+ Capability」をクリック
  5. 「App Transport Security Exception」を選択
  6. 「App Transport Security Exception」欄の+を押下し、セキュリティ除外したいドメインを設定。

f:id:uma-no-kawa:20211008141710p:plain

f:id:uma-no-kawa:20211008141755p:plain

f:id:uma-no-kawa:20211008141838p:plain

見逃しやすい?ポイント

上記対応を行なったドメインは「https://~」で接続してはいけない。

【SwiftUI・ColorPicker】カラーホイールをカスタマイズ(非表示)するアイデア

環境

  • Xcode 13
  • Swift 5
  • SwiftUI
  • iOS14, 15

解決する問題

  • カラーホイールが邪魔(オリジナルデザインにしたい)
  • UIColorPickerViewControllerの出し入れを自分でコントロールしたい

作戦

現在(2021/10/07)のiOSデフォルトのカラーピッカーはラベル横のカラーホイールは非表示にできません。ラベルは非表示にできるのに...。

なのでUIColorPickerViewControllerをSwiftUIで使用することを考えます。

実装

UIViewControllerRepresentableプロトコルを実装したクラスを作成します。

import Foundation
import SwiftUI
import UIKit

/// カラーピッカーコンテナ
struct ColorPickerContainer : UIViewControllerRepresentable
{
    //新しい色が設定されたら呼ぶ
    let changedColor : (Color) -> Void
    
    //イベントを受け取るコーディネータ
    class Coordinator: NSObject, UIColorPickerViewControllerDelegate{
        // カラーピッカーコンテナ
        private let parent: ColorPickerContainer
        
        init(parent: ColorPickerContainer) {
            self.parent = parent
        }
        
        // 新しい色が設定されたら呼ばれる
        func colorPickerViewController(_ viewController: UIColorPickerViewController, didSelect color: UIColor, continuously: Bool) {
             changedColor(Color(color))
        }
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(parent: self)
    }
    
    // UIColorPickerViewControllerを表示しようとしたらよばれる
    func makeUIViewController(context: Context) -> UIColorPickerViewController {
        let controller = UIColorPickerViewController()
        controller.delegate = context.coordinator
        controller.title  = "タイトル"// カラーピッカーのタイトル
        controller.supportsAlpha = false// 色の透明度を設定できるか否か
        return controller
    }
    
    func updateUIViewController(_ uiViewController: UIColorPickerViewController, context: Context) {
        //
    }
}

使い方例 Example

import SwiftUI

struct TestView: View {

    ///カラーピッカーを表示するか
    @State private var isShow = false
    
    var body: some View {
        VStack{
            Button(action : {
                isShow = true// 押下でカラーピッカーを開く
            }) {
                Text("カラーピッカーを開く")
            }    
        }
        .sheet(
            isPresented: $isShow,
            onDismiss: {}) {
            ZStack(alignment: .top){
                ColorPickerContainer (){ color in
                    // ここのcolorを好きなように使う
                }
                // 閉じるボタンがなかったので下記のように設定すると良い
                HStack{
                    Spacer()
                    Button(action: {
                        isShow = false
                    }) {
                        Text("閉じる")
                            .foregroundColor(Color("text_main"))
                            .padding(.top, 20)
                            .padding(.trailing, 20)
                    }
                }
            }
        }
    }
}

struct TestView_Previews: PreviewProvider {
    static var previews: some View {
        TestView()
    }
}

【SwiftUI】テキストをセンタリングしたアイコン付きボタンを作るアイデア

テキストを中央寄せにしながら、そのテキストの前(後)にアイコンがついたボタンを製作します。

バージョン

  • Swift 5

完成イメージ

f:id:uma-no-kawa:20211001155538p:plain

実装

アイコンが必要な方の四角をImageなどに変更し、 Imageと同じサイズを不要な四角のframeにセット、 不要な四角の色を.clearに変更すれば完了です。

f:id:uma-no-kawa:20211001155248p:plain

Button(action:{
    //action
}){
    HStack(spacing:10){

        // 左四角
        Rectangle()
            .fill(.blue)
            .frame(width: 35, height: 35)

        //テキスト
        Text("次へ").foregroundColor(.white)

        // 右四角
        Rectangle()
            .fill(.blue)
            .frame(width: 35, height: 35)

    }.frame(width: 335, height: 60, alignment: .center)
}.background(Color.red)

別解

Rectangleではなく、Colorだけでもいけることに気がつきました。

Color.clear.frame(width: 35, height: 35)