20200320のPHPに関する記事は15件です。

【Laravel】配列取り出し方パターン

単純配列

単純配列
$memo[] = array();
$memo = [100,200,300,400,500];
$data = $memo[2];

echo $data;
//300
連想配列
$memo[] = array();
$memo = [
  'counry' => 'Japan',
  'capital' => 'Tokyo',
  'population' => 120000000 
];
$data = $memo['capital'];

echo $data;
//Tokyo
連想配列(value値が複数)
$memo[] = array();
$memo = [
  'country' => ['Japan', 'China', 'Korea'],
  'capital' => ['Tokyo', 'Beigin', 'Sore']
];
$data = $memo['capital'][1];

echo $data;
//Beigin
多次元配列
$memo[] = array();
$memo = [
  ['田中', '兵庫', 26],
  ['斎藤', '京都', 30],
  ['鈴木', '徳島', 43]
];
foreach($memo as $value) {
  $memos = $value[0].'('.$value[1].'県出身'.$value[2].'才'.')';
  echo '<br>';
}

//"田中(兵庫県出身26才)"
//"斎藤(京都県出身30才)"
//"鈴木(徳島県出身43才)"
多次元配列
$memo[] = array();
$memo = array(
  '東京' => [
      '世田谷区'=>'100',
      '渋谷区'=>'255',
      '町田市'=>'1731',
  ],
  '北海道' => [
      '札幌市'=>'27',
      '函館市'=>'-34',
  ],
  '福岡県' => [
      '福岡市'=>'3312',
      '北九州市'=>'6398',
      '糸島市'=>'33.5',
  ]
);

$items = [];
foreach($memo as $key => $value) {
  foreach($value as $sub_key => $sub_value) {
    $items = $sub_key.":".$sub_value;
  }
}

echo $items;
/*
"世田谷区:100
渋谷区:255
町田市:1731
札幌市:27
函館市:-34
福岡市:3312
北九州市:6398
糸島市:33.5"
*/
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel 検索機能サンプル

searchアクションで検索結果があれば表示するサンプル

routes.php
Route::get('/person/{id}', 'PersonController@find');
Route::post('/person/{id}', 'PersonController@search');
controller.php
  public function find(Request $request){
    return view('person.find', ['input' => '', 'id' => $request->id]);
  }

  public function search(Request $request){
    $input_val = $request->input;
    $item = Person::find($input_val);
    return view('person.find', ['input' => $input_val, 'id' => $request->id, 'item' => $item]);
  }
view.blade.php
  <form action="/person/{{$id}}" method="post">
    {{ csrf_field() }}
    <input type="text" name="input" value="{{$input}}">
    <input type="submit" value="find">
  </form>

  @if (isset($item))
    <table>
      <tr>
        <th>Data</th>
      </tr>
      <tr>
        <td>{{ $item->getData() }}</td>
      </tr>
    </table>
  @endif
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPのisset()と等価な条件式を書いてisset()への理解を深めたい

問い

$hoge を変数とする。 $hoge は定義されていて、かつ配列型であるとする。

このとき、 isset($hoge['fuga']['piyo']) と等価な条件式を書け。

ここで「2つの条件式が等価である」とは、「条件を満たすどのような $hoge に対しても2つの条件式の真偽が一致する」ことを意味することとする。

また、条件式を書くにあたっては論理演算子と以下の関数のみを用いることとする。

  • array_key_exists()
  • is_array
  • is_null

答えの例

array_key_exists('fuga', $hoge)
&& !is_null($hoge['fuga'])
&& is_array($hoge['fuga'])
&& array_key_exists('piyo', $hoge['fuga'])
&& !is_null($hoge['fuga']['piyo'])

証明

省略

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

モデルメソッドの使い方

メソッドを定義してuseして使うだけ

# 使い方(Personモデルでの例)
use App\Person; #コントローラでuse

$person = Person::all(); #インスタンス取得
$Person->モデルメソッド(); #メソッドを使用

viewで表示する例:

Person.php
    # メソッド定義
  public function getData()
  {
    return $this->id . ':' . $this->name . '(' . $this->age . ')';
  }
PersonController.php
use App\Person;
use Illuminate\Http\Request;

class PersonController extends Controller
{
  public function index(){
    $people = Person::all();
    return view('person.index', ['people' => $people]);
  }
}

person/index.blade.php
  <table>
    @foreach($people as $person)
    <tr>
    <!-- ここでメソッド呼び出し -->
      <td>{{ $person->getData() }}</td>
    </tr>
    @endforeach
  </table>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ユリウス日の算出方法

ユリウス日の算出方法を調べていたら、出典によって数式がマチマチでどれが正しいのか困ってしまったのでとりあえず整理。
また、比較も行ってみたが、各算出方法で結果に差があることと傾向は分かったものの、どれが正しいのか、あるいは何か一つの方法を正しいと断ずることはそもそも出来るのかは不明なまま。

ユリウス日の算出方法

wikipedia / ユリウス通日#Julian Day Number (JDN) によると、

換算式は、Fliegel and Van Flandern[13]、Hatcher[14]、Meeus[15]によって考案されている。ただしこれらに整理を施した換算式が使われることも多い[16]。

とのことであり、式にはいくつかの形がある模様。
以下に、wikipediaでの式と、他文献等の式を列挙する。

それぞれ式の形がかなり違っているけど、ほんとに等価なんだろうか…。

wikipediaの方法

wikipedia / 恒星時#恒星時の計算法

\begin{aligned}
JD = & \left\lfloor 365.25 Y \right\rfloor + \left \lfloor \frac{Y}{400} \right\rfloor - \left\lfloor \frac{Y}{100} \right\rfloor + \left\lfloor 30.59 \left( M-2 \right) \right\rfloor + D + 1721088.5 \\
& + \frac{h}{24} + \frac{m}{1440} + \frac{s}{86400} \\
\\
& \lfloor x \rfloorは床関数
\end{aligned}

UTの現在のグレゴリオ暦での年をY、月をM、日をD、時間をh、分をm、秒をsとする。ただし、1月と2月はそれぞれ前年(Yの値を-1する)の13月、14月として代入する(例: 2013年2月5日の場合、Y=2012, M=14, D=5)。

Fliegelらの方法

Fliegel, H. F. and Van Flandern, T. C., "A Machine Algorithm for Processing Calendar Dates," Communications of the ACM 11, p. 657, 1968.

\begin{aligned}
JD(I,J,K) = & K - 32075 + 1461 * (I + 4800 + (J - 14) / 12) / 4 \\
& + 367 * (J - 2 - (J - 14) / 12 * 12) / 12 \\
& - 3 * ((I + 4900 + (J - 14) / 12 ) / 100 ) / 4
\end{aligned}

calendar date (I = year; J = month, a number from 1 to 12; K = day of month) to a Julian Date (JD)

COMPUTATION AND MEASUREMENT PROBLEM 11.

In FORTRAN integer arithmetic, multiplication and division are performed left to right in the order of occurrence, and the absolute value of each result is truncated to the next lower integer value after each operation, so that both 2/12 and -2/12 become 0.

乗算と除算は左から右に実行され、そのつど計算結果の絶対値は、その次に小さい整数値に切り下げられる。

wikipedia / Julian day#Converting Gregorian calendar date to Julian Day Number

The algorithm[61] is valid for all (possibly proleptic) Gregorian calendar dates after November 23, −4713. Divisions are integer divisions, fractional parts are ignored.

他と比較しやすいよう表現を変えると、

\begin{aligned}
JD = & D - 32075 + \left\lfloor \frac{ 1461 \left( Y + 4800 + \left\lfloor \frac{M - 14}{12} \right\rfloor \right)}{4} \right\rfloor \\
& + \left\lfloor \frac{ 367 \left( M - 2 - 12 \left\lfloor \frac{M - 14}{12} \right\rfloor \right) }{12} \right\rfloor \\
& - \left\lfloor \frac{ 3 \left\lfloor \frac{ Y + 4900 + \left\lfloor \frac{M - 14}{12} \right\rfloor }{100} \right\rfloor }{ 4 } \right\rfloor
\end{aligned}

Hatcherの方法

Hatcher, D. A., Simple formulae for Julian day numbers and calendar dates, Quarterly Journal of the Royal Astronomical Society, v. 25, p. 53-55, 1984

\begin{aligned}
Y' & = Y + y - ((n + m - 1 - M) / n) \text{INT} \\
M' & = (M - m) \text{MOD } n \\
D' & = D - 1 \\
J & = ((pY' + q) / r) \text{INT} + ((sM' + t) / u) \text{INT} + D' -j
\end{aligned}

Y, M, D and Y', M', D' are the year, month and day of month

(x) INT is the integral part of x, and x is assumed to be positive; (x) MOD y is the positive remainder on divideing x by y.

(x) INTはxの整数部であり、xは正と想定される。(x) MODはxをyで除算した正の剰余。

グレゴリオ暦からの変換の場合は

y j m n r p q v u s t w
4716 1401+g 3 12 4 1461 - 3 5 153 2 2
g = (((Y' + 184) / 100) \text{INT} \times 3/4) \text{INT} - 38

と記載されているため、上記の式に代入すると

\begin{aligned}
Y' = & Y + 4716 - \left( \frac{14 - M}{12} \right) \text{INT} \\
M' = & (M - 3) \text{MOD } 12 \\
D' = & D - 1 \\
J = & \left( \frac{1461 Y'}{4} \right) \text{INT} + \left( \frac{153M' + 2}{5} \right) \text{INT} + D' \\
& - \left( 1401 + \left( \frac{Y' + 184}{100} \right) \text{INT} \times \frac{3}{4} \right) \text{INT} - 38 \\
= & \left( 365.25Y' \right) \text{INT} + \left( 30.6M' + 0.4 \right) \text{INT} + D' \\
& - \left( 1401 + \left( \frac{Y' + 184}{100} \right) \text{INT} \times \frac{3}{4} \right) \text{INT} - 38
\end{aligned}

Meeusの方法

Meeus, J., Astronomical Algorithms, 1998

\begin{aligned}
A & = \text{INT} \left( \frac{Y}{100} \right) \\
B & = 2 - A + \text{INT} \left( \frac{A}{4} \right) \\
JD & = \text{INT} (365.25 (Y + 4716)) + \text{INT} (30.6001(M + 1)) + D + B - 1524.5
\end{aligned}

Let Y be the year, M the month number (1 for January, 2 for February, etc., to 12 for December), and D the day of month (with decimals, if any) of the given calendar date.

INT(x) the greatest integer less than or equal to x.

for instance, INT(-7.83) = -8

他と比較しやすいよう表現を変えると、

\begin{aligned}
JD & = \left\lfloor 365.25 (Y + 4716) \right\rfloor + \left\lfloor 30.6001(M + 1) \right\rfloor + D + 2 - \left\lfloor \frac{Y}{100} \right\rfloor + \left\lfloor \frac{ \left\lfloor \frac{Y}{100} \right\rfloor }{4} \right\rfloor - 1524.5 \\
& = \left\lfloor 365.25 Y \right\rfloor + \left\lfloor 30.6001(M + 1) \right\rfloor + D - \left\lfloor \frac{Y}{100} \right\rfloor + \left\lfloor \frac{Y}{400} \right\rfloor + ‭1,720,996.5‬ \\
& = 365 Y + \left\lfloor \frac{Y}{4} \right\rfloor - \left\lfloor \frac{Y}{100} \right\rfloor + \left\lfloor \frac{Y}{400} \right\rfloor + \left\lfloor 30.6001(M + 1) \right\rfloor + D + ‭1,720,996.5‬
\end{aligned}

Valladoらの方法

CelesTrak / Revisiting Spacetrack Report #3 - AIAA 2006-6753 - Source code (C++)
Vallado, David A., Paul Crawford, Richard Hujsak, and T.S. Kelso, "Revisiting Spacetrack Report #3," presented at the AIAA/AAS Astrodynamics Specialist Conference, Keystone, CO, 2006 August 21–24.

\begin{aligned}
jd = & 367.0 * year - \\
& floor((7 * (year + floor((mon + 9) / 12.0))) * 0.25) + \\
& floor(275 * mon / 9.0) + day + 1721013.5 + \\
& ((sec / 60.0 + minute) / 60.0 + hr) / 24.0 \\
\end{aligned}

他と比較しやすいよう表現を変えると、

\begin{aligned}
JD = & 367 Y - \left\lfloor \frac{7}{4} \left(Y + \left\lfloor \frac{M + 9}{12} \right\rfloor \right) \right\rfloor + \left\lfloor \frac{275 M}{9} \right\rfloor + D + 1721013.5 \\
& + \frac{h}{24} + \frac{m}{1440} + \frac{s}{86400}
\end{aligned}

Howard D. Curtisの方法

ScienceDirect / Julian Day Number
Howard D. Curtis, in Orbital Mechanics for Engineering Students (Fourth Edition), 2020

\begin{aligned}
J_0 = & 367 y - \text{INT} \frac{7 y + \text{INT} \frac{m + 9}{12}}{4} + \text{INT} \frac{275 m}{9} + d + 1,721,013.5 \\
& 1901 \le y \le 2099 \\
& 1 \le m \le 12 \\
& 1 \le d \le 31
\end{aligned}

INT(x) means retaining only the integer portion of x, without rounding (or, in other words, round toward zero). For example, INT(− 3.9) = −3 and INT(3.9) = 3.

ScienceDirect / Julian Day Number
Howard D. Curtis, in Orbital Mechanics for Engineering Students (Third Edition), 2014

\begin{aligned}
J_0 = & 367 y - \text{INT} \left\{ \frac{7 \left[ y + \text{INT} \left( \frac{m + 9}{12} \right) \right] }{4} \right\} + \text{INT} \left( \frac{275 m}{9} \right) + d + 1,721,013.5 \\
& 1901 \le y \le 2099 \\
& 1 \le m \le 12 \\
& 1 \le d \le 31
\end{aligned}

INT (x) means to retain only the integer portion of x, without rounding (or, in other words, round toward zero), that is, INT (−3.9) = −3 and INT (3.9) = 3

上記のFourth EditionとThird Editionでは、第2項の分子の7がかかっている範囲が異なっている。

boostライブラリの方法

boost/date_time/gregorian_calendar.ipp

  //! Convert a ymd_type into a day number
  /*! The day number is an absolute number of days since the start of count
   */
  template<typename ymd_type_, typename date_int_type_>
  BOOST_DATE_TIME_INLINE
  date_int_type_
  gregorian_calendar_base<ymd_type_,date_int_type_>::day_number(const ymd_type& ymd)
  {
    unsigned short a = static_cast<unsigned short>((14-ymd.month)/12);
    unsigned short y = static_cast<unsigned short>(ymd.year + 4800 - a);
    unsigned short m = static_cast<unsigned short>(ymd.month + 12*a - 3);
    unsigned long  d = ymd.day + ((153*m + 2)/5) + 365*y + (y/4) - (y/100) + (y/400) - 32045;
    return static_cast<date_int_type>(d);
  }

  //! Convert a year-month-day into the julian day number
  /*! Since this implementation uses julian day internally, this is the same as the day_number.
   */
  template<typename ymd_type_, typename date_int_type_>
  BOOST_DATE_TIME_INLINE
  date_int_type_
  gregorian_calendar_base<ymd_type_,date_int_type_>::julian_day_number(const ymd_type& ymd)
  {
    return day_number(ymd);
  }

他と比較しやすいよう表現を変えると、

\begin{aligned}
a & = \text{INT} \left( \frac{14 - M}{12} \right) \\
y & = Y + 4800 - a \\
m & = M + 12 a - 3 \\
JD & = \text{INT} \left( D + \frac{153m + 2}{5} + 365 y + \frac{y}{4} - \frac{y}{100} + \frac{y}{400} - 32045 \right)
\end{aligned}

PHPの方法

PHP > マニュアル > 関数リファレンス > 日付および時刻関連 > カレンダー > カレンダー関数
gregoriantojd

gregoriantojd — グレゴリウス日をユリウス積算日に変換する

PHPの関数ではあるが、以下の通り実体はCで実装されている模様。

php-src/ext/calendar/calendar.stub.php

calendar.stub.ph
function gregoriantojd(int $month, int $day, int $year): int {}

php-src/ext/calendar/calendar.c

calendar.c
/* {{{ proto int gregoriantojd(int month, int day, int year)
   Converts a gregorian calendar date to julian day count */
PHP_FUNCTION(gregoriantojd)
{
    zend_long year, month, day;

    if (zend_parse_parameters(ZEND_NUM_ARGS(), "lll", &month, &day, &year) == FAILURE) {
        RETURN_THROWS();
    }

    RETURN_LONG(GregorianToSdn(year, month, day));
}
/* }}} */

php-src/ext/calendar/gregor.c

gregor.c
zend_long GregorianToSdn(
                           int inputYear,
                           int inputMonth,
                           int inputDay)
{
    zend_long year;
    int month;

    /* check for invalid dates */
    if (inputYear == 0 || inputYear < -4714 ||
        inputMonth <= 0 || inputMonth > 12 ||
        inputDay <= 0 || inputDay > 31) {
        return (0);
    }
    /* check for dates before SDN 1 (Nov 25, 4714 B.C.) */
    if (inputYear == -4714) {
        if (inputMonth < 11) {
            return (0);
        }
        if (inputMonth == 11 && inputDay < 25) {
            return (0);
        }
    }
    /* Make year always a positive number. */
    if (inputYear < 0) {
        year = inputYear + 4801;
    } else {
        year = inputYear + 4800;
    }

    /* Adjust the start of the year. */
    if (inputMonth > 2) {
        month = inputMonth - 3;
    } else {
        month = inputMonth + 9;
        year--;
    }

    return (((year / 100) * DAYS_PER_400_YEARS) / 4
            + ((year % 100) * DAYS_PER_4_YEARS) / 4
            + (month * DAYS_PER_5_MONTHS + 2) / 5
            + inputDay
            - GREGOR_SDN_OFFSET);
}

他と比較しやすいよう表現を変えると、

\begin{aligned}
Y' & = \left\{
    \begin{aligned}
        Y + 4801 \quad (Y < 0) \\
        Y + 4800 \quad (Y \ge 0)
    \end{aligned}
\right. \\
M' & = \left\{
    \begin{aligned}
        & M - 3 & (M > 2) \\
        & M + 9, \quad Y' = Y' - 1 & (M \le 2)
    \end{aligned}
\right. \\
JD & = \text{INT} \left( \frac{ \frac{Y'}{100} \times 146097 }{4} + \frac{(Y' \% 100) \times 1461}{4} + \frac{153 M' + 2}{5} + D - 32045 \right)
\end{aligned}

pyorbitalの方法

pyorbital/pyorbital/__init__.py

__init__.py
def dt2np(utc_time):
    try:
        return np.datetime64(utc_time)
    except ValueError:
        return utc_time.astype('datetime64[ns]')

pyorbital/pyorbital/astronomy.py

astronomy.py
def jdays2000(utc_time):
    """Get the days since year 2000.
    """
    return _days(dt2np(utc_time) - np.datetime64('2000-01-01T12:00'))


def jdays(utc_time):
    """Get the julian day of *utc_time*.
    """
    return jdays2000(utc_time) + 2451545


def _days(dt):
    """Get the days (floating point) from *d_t*.
    """
    return dt / np.timedelta64(1, 'D')

つまり

JD =  UTC(Y,M,D,h,m,s) - UTC(2000, 1, 1, 12, 0, 0) + 2451545

国立天文台のWebページの方法

国立天文台 / ユリウス日

1582年10月15日以後はグレゴリオ暦、それより前はユリウス暦の規則に従った日付となります。
紀元元年の前年を0年としています。このため、これを紀元前1年とする方法とは1年ずつ差異があります。

Webフォームに入力することでユリウス日を算出することができる。
他の算出方法での結果と比べるために、CSVファイルに出力しておく。手入力だと大変なため、pythonでWebフォームへリクエストを送信して結果を取得しCSVに出力する。

Pythonコード

以下は上記のコードで生成したCSVのグラフ。なお、このWebサイトでは -4712/01/01 12:00 が最小値(ユリウス日=0.0日)。

  • -4712年周辺(-4712/01/01 ~ -4711/12/01)
    JulianDay_by_NAOJ_-47120101_-47111201.png

  • 0年周辺(0001/01/01 ~ -0001/12/01)
    JulianDay_by_NAOJ_-00010101_00011201.png

  • グレゴリオ暦が始まった1582年10月(1582/10/01 ~ 1582/10/31)
    JulianDay_by_NAOJ_15821001_15821031.png

ユリウス暦の最終日である1582/10/04の次の日はグレゴリオ暦の最初日である1582/10/15であるため、Webページもそのような形で結果を返してきている。また、10/05~10/14という値が存在しない形になっている。その影響か、10/24の次が10/15になってしまっている。ともかく、10/04のユリウス日は2299160、10/15のユリウス日は2299161となっており、値が飛ぶことのない線形な結果が維持されている。

各方法の算出結果の比較

比較用のPythonコード

横軸:グレゴリオ暦(1582/10/15よりも前をグレゴリオ暦と呼ぶのは不適切な気もする…)
縦軸:ユリウス日

なお、NAOJ(国立天文台のWebサイトでの算出結果)については、-4713年~2000年を1ヶ月刻みで算出するのは負荷と時間が心配なので以下の期間だけを算出しており、グラフにも以下の期間でしかプロットされていない。

  • -4712年周辺(-4712/01/01 ~ -4711/12/01)
  • 0年周辺(0001/01/01 ~ -0001/12/01)
  • グレゴリオ暦が始まった1582年10月(1582/10/01 ~ 1582/10/31)

-4713年~2000年

-4713/01/01 ~ 2000/12/01 を1ヶ月刻み(各月の1日)で算出。

JulianDayCompare_-47130101_20001201.png

俯瞰するとどの算出方法でもほぼ同じ値で、ほぼ線形な結果になっている。

-4713年周辺の拡大図

-4713/01/01 ~ -4711/12/01 を1ヶ月刻み(各月の1日)で算出。

JulianDayCompare_-47130101_-47111201.png

NAOJ(国立天文台のWebサイトでの算出結果)については、このWebサイトでは -4712/01/01 12:00 が最小値(ユリウス日=0.0日)のため、-4712年から始まっている。

0年周辺の拡大図

-0001/01/01 ~ 0001/12/01 を1ヶ月刻み(各月の1日)で算出。

JulianDayCompare_-00010101_00011201.png

phpのみ、-0001年12月から0000年1月で不連続となっており、phpでは「紀元前1年の次は紀元後1年」という扱いをしていると考えられる。ユリウス日の値から見れば、紀元0年は紀元前1年と同じということになる。
逆にphp以外の方法では、「紀元前1年→紀元0年→紀元後1年」という扱いをしている模様。

0年周辺の拡大図、ただし0年は除外して描画

-0001/01/01 ~ -0001/12/01、0001/01/01 ~ 0001/12/01 を1ヶ月刻み(各月の1日)で算出。

JulianDayCompare_-00010101_00011201_exceptYear0.png

前述の通り、ためしに0年を除外してグラフを描画するとphpだけが連続になり、他の方法は不連続になる。

グレゴリオ暦が始まった1582年10月の拡大図

1582/10/01 ~ 1582/10/31 を1日刻みで算出。

JulianDayCompare_15821001_15821031.png

NAOJ(国立天文台のWebサイトでの算出結果)については、ユリウス暦の最終日である1582/10/04の次の日はグレゴリオ暦の最初日である1582/10/15になることに従い、10/05~10/14についてはユリウス日の算出対象外になっているため、値が無い。

最大値と最小値の差

-4713/01/01 ~ 2000/12/01 を1ヶ月刻み(各月の1日)で算出。

JulianDayCompare_-47130101_20001201_max-min.png

算出されたユリウス日の値は算出方法間でバラツキがあるため、バラツキがどれくらいかを見るために最大値と最小値の差をプロットしてみた。
- -4713/01/01 ~ -0001/12/01 における差: 417.5 ~ 381.5
- 0000/01/01 ~ 2000/12/01: 17.5 ~ 1.5
- 1582/10/01: 13.5(前述の通り1582/10はNAOJを算出しており、NAOJが最大値を出していて差が大きくなっている)

現在に近づくほど差は小さくなってきている。

比較した結論

各算出方法で結果に差があることと傾向は分かったものの、どれが正しいのか、あるいは何か一つの方法を正しいと断ずることはそもそも出来るのかは不明なまま。

ユリウス日における時刻

12:00 UT後のユリウス暦の完全な日付。

\begin{aligned}
JD & = JDN + \frac{hour - 12}{24} + \frac{minute}{1440} + \frac{second}{86400} \\
JD & : \text{Julian Date} \\
JDN & : \text{Julian Day Number}
\end{aligned}

wikipedia / Julian day#Finding Julian date given Julian day number and time of day

その他

Modified Julian Day: MJD(修正ユリウス日)

wikipedia / ユリウス通日#修正ユリウス日(MJD)
wikipedia / Julian day#Variants
Meeus, J., Astronomical Algorithms, 1998

\begin{aligned}
MJD & = JD - 2400000.5 \\
MJD & : 修正ユリウス日 \\
JD & : ユリウス日
\end{aligned}

Truncated Julian Day: TJD

床関数のあるのと無いの、どちらが正しいのか?

wikipedia / 恒星時#恒星時の計算法

TJD = JD - 2440000.5

wikipedia / Julian day#Variants

TJD = \left\lfloor JD - 2440000.5 \right\rfloor

J2000

wikipedia / Epoch (astronomy)#Julian Dates and J2000

date that is an interval of x Julian years of 365.25 days away from the epoch J2000 = JD 2451545.0 (TT), still corresponding (in spite of the use of the prefix "J" or word "Julian") to the Gregorian calendar date of January 1, 2000, at 12h TT (about 64 seconds before noon UTC on the same calendar day).10 Like the Besselian epoch, an arbitrary Julian epoch is therefore related to the Julian date by

J = 2000 + ( \text{Julian date} -2451545.0 ) \div 365.25

他参考サイト

ユリウス日(Julian Day)
「ユリウス日」で遊ぶ
The Julian Period

wikipedia / グレゴリオ暦

【Python】 GET・POSTリクエストによるWebデータの取得(Requestsモジュール)
【Python】BeautifulSoupを使ってテーブルをスクレイピング
10分で理解する Beautiful Soup

ticklabels empty when not interactive #6103

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

PHPで階乗を計算する関数

備忘録。PHPで階乗を計算するプログラム。

再帰関数を使わずに実装。

echo factorial_of($num);

function factorial_of($num){

    $num2 = $num-1;

    while($num2>0){
        $num *= $num2;

        if($num2>=1){
            $num2--;
        }
    }

    return $num;
}

再帰関数で実装。

echo factorial_of($num); 

function factorial_of($num){

    if($num>0) {
        return $num *= factorial_of($num-1);
    }

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

phpListのインストールからテスト送信まで

はじめに

前提として
* PHP、Apache、MySQLはインストール済(データベース作成済)
* PHPに関して、IMAPモジュールがインストールされていること
* メール送信可能なMTAサーバー(Sendmail、Postfixなど、外部サーバーでも可) が必要(ここの設定は今回書いていません)

phplistインストール

phpListをインストールしていきます。
zipファイルをダウンロード

wget --content-disposition https://sourceforge.net/projects/phplist/files/phplist/3.5.1/phplist-3.5.1.zip/download

/var/www/phplist に展開(phplistディレクトリは新規に作成)

$ unzip phplist-3.5.1.zip -d /var/www/phplist

phpListのconfigファイル設定変更

/var/www/phplist/public_html/lists/config/config.php

// 日本語に設定
$default_system_language = 'ja';
// データベースで作成するテーブル名のプレフィックス
$usertable_prefix = 'phplist_';
// phplistのルートディレクトリ
$pageroot = '/phplist/lists';
// phpListの管理ルートディレクトリを設定
$adminpages = '/phplist/lists/admin';

// データベースの設定
$database_host = 'localhost';
$database_name = 'database_name';
$database_user = 'database_user';
$database_password = 'database_password';

// SMTPサーバーの設定
define('PHPMAILERHOST', 'SMTPサーバー名');

// MTAサーバーへアクセスするユーザ名を設定
$phpmailer_smtpuser = 'smtp_user';
// MTAサーバーへアクセスするユーザのパスワードを設定
$phpmailer_smtppassword = 'password';

// ファイル添付ができるよう設定(0 -> 1)
define('ALLOW_ATTACHMENTS', 1);

// テストモード解除(1 -> 0)
define('TEST', 0);

phplist.conf ファイルを新規作成

/etc/httpd/conf.d/phplist.confファイルを新規に作成し、以下を記入する。

Alias /phplist /var/www/phplist/public_html 

<VirtualHost *:80>
  DocumentRoot /var/www/phplist/public_html
  ServerName example.com
</VirtualHost>

Apacheの再起動を忘れずに!

初期画面へ

以下からアクセスできます。

http://example.com/phplist/lists/admin/
  • データベースの初期化(設定画面)

以下の4項目を設定して初期化する。エラーがなければOK。

name : 
organisation : 
mail_address : 
password : 

以降はログイン画面からユーザー名:admin、パスワード:上記で指定したパスワードでログインできます。
スクリーンショット 2020-03-20 16.01.55.png

phpList側の設定

  • サーバーのドメイン名を変更
config > 設定 > generalの設定 > サーバーのドメイン名(メールアドレス用)
  • 送信用メールアドレスに変更
config > 設定 > campaignの設定 > キャンペーンの From 行の初期値

テスト送信

テストメールを作成

キャンペーン > キャンペーンの送信 > 新しいキャンペーンを開始

必要なものの記入が終わったら最下部にある、テスト送信のところに送信先を設定し、テスト送信を押下。
※ただし、アドレスが追加されていないものだと送信できず、追加するようアラートが出るので、指示にしたがって追加する。そうすると、無事テスト送信ができる。
スクリーンショット 2020-03-20 15.58.46.png

ファイル添付について

  • lists/config/config.php のALLOW_ATTACHMENTSを追記
  • メールにファイル添付がされるのはHTML形式でメッセージを送信したときのみ
  • TEXT形式でメッセージを作成すると、ファイルをダウンロードするためのURLがメッセージの末尾に記述される
  • メッセージをHTML形式で送信しても、登録されているユーザーの設定が「HTMLメールを受け取る」になっていなければ、TEXT形式でメール送信される

参考:https://blog.songs-inside.com/entry/oss/494

※今回baunceメールの受信設定はしていません。必要であれば、別途設定が必要です。

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

JavaScriptのthisとPHPのthis

どんな記事?

JavaScriptとPHPのthisを比べながら理解しよう。

背景

thisがよく分からん!

JavaScriptのthis他の言語と少々異なる動作をするらしい

よろしい、ならば比較だ

PHPのthis

PHPの疑似変数である$thisは、メソッドがオブジェクトコンテキストからコール場合に利用することができる。
$thisは呼び出し元オブジェクトへの参照である。

カレントオブジェクトからそのクラス内の関数や変数にアクセスする場合に$thisを使える。

(コンテキストは直訳だと文脈という意味。
プログラミング用語的には、背景となる情報という言い回しが妥当かな?)

(カレントオブジェクトとは、インスタンスメソッドが起動されたオブジェクトのこと)

<?php
//クラス(Sample)
class Sample
{
  //プロパティ($hoge)宣言
  public $hoge = 'foo';

  //メソッド(display)宣言
  public function display()
  {
    //displayメソッドで$hogeの内容を呼び出す
    echo $this->$hoge;
  }
}

$sample = new Sample;
$sample->display(); //出力結果:foo
?>

なぜ$thisが必要か?

それは、
クラス定義の内部では、それにアクセス可能なオブジェクト名を知ることができない
からである。
上記サンプルでは、Sampleクラスが書かれている時点では、
そのオブジェクトの名前があとで$sampleになるのか、はたまた$showになるのか分からない。

その為、Sampleクラスの中で

$sample->$hoge

と書くことはできないのである。

代わりに、クラスの中から、そのクラス内の関数や変数にアクセスする為に$thisを使う。

JavaScriptのthis

ほとんどの場合、thisの値は、関数の呼ばれ方によって決定されます。これは実行時に割り当てできず、関数が呼び出されるたびに異なる可能性があります。

ほう。

構文

this

値:現在のコードが実行されているJavaScriptコンテキストオブジェクトです

グローバルコンテキスト

JavaScriptにおけるグローバル実行コンテキスト(いずれかの関数の外側)では、
thisはグローバルオブジェクトを参照する。

例文
//whidowはグローバルオブジェクト
//thisはグローバルオブジェクトを示す
console.log(this === window);  // true

//グローバルオブジェクトで宣言
this.hoge = 37;
//windowグローバルオブジェクトから
//thisで宣言した値を呼び出すことができる
console.log(window.hoge); //出力結果:37

あれ、PHPとぜんぜん違いますね(驚愕)

関数コンテキスト

単純な呼び出し

次の例は呼び出し時にthisの値がセットされない為、thisはデフォルトでグローバルオブジェクトとなり、それはブラウザではwindowと同等である。

funcion f1() {
  return this;
}

f1() === window; //出力結果:true

別のコンテキストからthisの値を呼び出す場合はcallもしくはapplyを使用する。

//オブジェクト定義
var obj = {a: 'Custom'};

function whatsThis() {
  return this.a;
}

whatsThis.call(obj); //出力結果:Custom

アロー関数

アロー関数では、thisはそれを囲むレキシカル(静的)なコンテキストのthisの値が設定される。

var globalObject = this;
var foo = (() => this);
console.log(foo() === globalObject); //出力結果:true

オブジェクトのメソッドとして

関数がオブジェクトのメソッドとして呼び出される時、そのthisにはメソッドが呼び出されたオブジェクトが設定される。

次の例ではtest.func()が起動した時、関数内のthisにはtestオブジェクトが関連付けられる。

const test = {
  prop: 42,
  func: function () {
    retrun this.prop;
  },
};

console.log(test.func());
//出力結果: 42

この振る舞いは、関数定義の方法や場所に全く影響を受けない。

オブジェクトのプロトタイプチェーン上のthis

同じ概念が、オブジェクトのプロトタイプチェーンのどこかに定義されたメソッドにもあてはまる。
そのメソッドがオブジェクト上にあるかのように、thisはメソッドを呼び出したオブジェクトを参照する。

var o = {
  f: function() {
    return this.a + this.b
  }
}
var p = Object.create(o);
p.a = 1;
p.b = 4;

console.log(p.f()); //出力結果:5

コンストラクタとして

関数がコンストラクタとして(newで生成される)使用される時、そのthisは生成された新しいオブジェクトにバインド(拘束)される

//関数定義
function C() {
  this.a = 37;
}
//コンストラクタ生成
var o = new C();
console.log(o.a); //出力結果:37

DOMイベントハンドラとして

関数がイベントハンドラとして使用される場合、そのthisにはイベントを発火させた要素が設定される

//要素を青色にする関数
function bluify(e) {
  console.log(this === e.currentTarget);
  console.log(this === e.target);
  this.style.backgroundColor = '#A5D9F3';
}
//全ての要素を取得
var elements = document.getElementByTagName('*');
//クリックリスナーとしてbluify関数を設定
//クリックした要素が青色に変わる
for(var i = 0; i < elements.length; i++){
  elements[i].addEventListener('click', bluify, false);
}

比べてみて

JavaScriptのthisは、オブジェクトのメソッドコンストラクトとして使うのであればPHPと同じような理解でいいのかな、と思いました。
DOMイベントハンドラとしてはフロントエンドならでは、という感じですね。

グローバルコンテキスト・関数コンテキストでのthisは、まだ使い道が分からん...

参考

PHP: クラスの基礎 - Manual
PHPで擬似変数$thisって何のためにあるのか?
this - JavaScript|MDN
「コンテキスト」という言葉が何を指しているのかよく分からない
レキシカルスコープとクロージャを理解する

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

PHP(Laravel)でレコードのinsert, update, delete

insert

DB::table('テーブル名')->insert(配列データ);

update

DB::table('テーブル名')->where('更新対象を検索')->update(配列データ);
    $params = [
      'id' => $request->id,
      'name' => $request->name,
      'email' => $request->email,
      'age' => $request->age
    ];

delete

#使い方
DB::table('テーブル名')->where(検索条件)->delete();
#削除ルーティング
Route::post('/hoge/delete', 'HogeController@delete');
HogeController.php
  public function delete(Request $request){
    $id = $request->delete_id;
    $person = DB::table('people')->where('id', $id);
    $person->delete();
    return redirect('/hello');
  }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【PHP】SQLクエリの実行

実行環境 
PHP 7.4
Postgre 12.2

queryメソッド

SQLステートメント(SQLで作成した命令文)を実行し、成功した場合は PDOStatement オブジェクト、失敗した場合はfalseを返します。

$db = new PDO("pgsql:host=localhost; dbname=postgres;","user","password");

$sql = "INSERT INTO test_tbl (id,name) VALUES (1,'yamada')";

$action = $db->query($sql);

SELECTした結果を使いたい場合などはqueryメソッドを使用します。

execメソッド

SQLステートメントによって更新や削除された行数を返します。
1行も作用しなかった場合は0を返します。

$db = new PDO("pgsql:host=localhost; dbname=postgres;","user","password");
$sql = "INSERT INTO test_tbl (id,name) VALUES (1,'yamada')";

$action = $db->exec($sql);

if($action>0) {
    echo "{$action}件のデータ挿入";
} else {
    echo "データ挿入失敗";
}

行数を返すので、ifやforで活用できますね。

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

【PHP】連想配列に代入した値を使って文字を置換する

入力した文字列の中から任意の文字を置換したくて、for文使ったりforeach使ってみたりして数時間うんうん悩んでたけど、strtr()関数に配列突っ込んだら解決したっていうメモ。

なんやそれ?

str_replace — 検索文字列に一致したすべての文字列を置換する

とのこと。
参考: PHP: strtr - Manual

引数
strtr($検索する文字列, $対象文字列, $置換する文字列);

引数に連想配列を渡すこともできる。
$keyが対象文字列、$valueが置換する文字列になる。

引数に連想配列を渡す
$s = 'AI';
$ary = ['A' => 1];

echo strtr($s, $ary);

//実行結果
1I

実装

<?php
$str = 'PIZZA EAT PIZZA';
$words = [
    'A' => 4,
    'E' => 3,
    'G' => 6,
    'I' => 1,
    'O' => 0,
    'S' => 5,
    'Z' => 2,
    ];

echo $str."\n";
echo strtr($str, $words);


//実行結果
PIZZA EAT PIZZA
P1224 34T P1224

おわり

str_replace()ちゅーものもあるみたい。パラメータが多くて便利そうだけど、使うときに注意が必要っぽい。
参考1: PHP: str_replace - Manual
参考2: str_replaceとstrtrの違いって何なのさ

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

PHP 年と月からその月の長さ(最終日)を取得する うるう年判定込

function checkFinalDay($year,$month){
    $finalDay = [
        "1" => 31,
        "2" => 28,
        "3" => 31,
        "4" => 30,
        "5" => 31,
        "6" => 30,
        "7" => 31,
        "8" => 31,
        "9" => 30,
        "10" => 31,
        "11" => 30,
        "12" => 31,
    ];

    if( $year%4 == 0 && $year%100 != 0 || $year%400 == 0 {
        $finalDay["2"] = 29;
    }
    return $finalDay[$month];
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SimpleSAMLPHPでIdPのログインページをカスタマイズする方法

やりたいこと

SimpleSAMLPHPを使ってIdpを構築してSSOをやっているのですが
いざ、構築し終わったらデフォルトのログインページのまま

これではだめなので変えようとしたところ死ぬほど苦戦したのでメモ

実現方法

デフォルトのログイン画面は

modules/core/templates/loginuserpass.tpl.phpになります

こいつをオーバライドしてやる必要があるわけです。

SimpleSAMLPHPにはテーマ機能があって、すべての画面をカスタマイズできます。
しかしその情報が公式ドキュメントのみなので面倒です

公式の通りにディレクトリを作成します

cd modules
mkdir mymodule
cd mymodule
touch default-enable
cd modules/mymodule
mkdir -p themes/fancytheme

configの設定を変えます

'theme.use'         => 'mymodule:fancytheme',

公式の例3を確認すると

たとえば、preprodwarningテンプレートを上書きするには(ファイルはにありますmodules/preprodwarning/templates/warning.php)、新しいファイルを追加する必要があります。

modules/mymodule/themes/fancytheme/preprodwarning/warning.php
モジュールfoomoduleで言うと、bar.phpテンプレートを表示するいくつかのコード要求、SimpleSAMLphpは次のようになります。

最初にテーマを確認して、代替品を探してくださいmodules/mymodule/themes/fancytheme/foomodule/bar.php。
見つからない場合、そのモジュールのベーステンプレートを使用します。 modules/foomodule/templates/bar.php

とあるので
loginuserpassをオーバーライドしたい場合
今回の場合modules/mymodule/themes/fancythemecoreディレクトリを作成します。(core内のテンプレートのため)
そこにloginuserpass.phpを作成してやれば上書きできます。

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

Wordpressでカスタマイザーにオプションを追加する一番簡単な方法

カスタマイザーを使うことでロゴやヘッダー画像のアップロード、テーマカラーの設定などWordpressテーマの様々なオプション設定ができるようになる。

カスタマイザーを作成する方法

functios.phpに以下のコードを追記する。

function mytheme_customize_register( $wp_customize ) {
  // セクション(グループ)を作成
  $wp_customize->add_section( 'theme_color' , array(
        'title'      => __( 'Theme Color', 'text_domain' ),
        'priority'   => 21,
    ) );
  // データベースに新しい設定項目を登録
    $wp_customize->add_setting( 'color_base' , array(
    'default'   => '#fff',
        'transport' => 'refresh',
        'sanitize_callback' => 'sanitize_hex_color',
    ) );
  // 管理画面に表示するコントローラ(フォーム)を登録
    $wp_customize->add_control( new WP_Customize_Color_Control( $wp_customize, 'color_base', array(
        'label'      => __( 'Base Color', 'text_domain' ),
        'section'    => 'theme_color',
        'settings'   => 'color_base',
    ) ) );

  // 画像のアップロードの場合
    $wp_customize->add_section( 'theme_image' , array(
        'title'      => __( 'Image', 'text_domain' ),
        'priority'   => 20,
    ) );
    $wp_customize->add_setting( 'logo_upload' , array(
        'transport' => 'refresh',
        'sanitize_callback' => 'text_domain_sanitize_file',
    ) );
    $wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, 'logo', array(
        'label'      => __( 'Upload a logo', 'text_domain' ),
        'section'    => 'theme_image',
        'settings'   => 'logo_upload',
    )));
}

// カラー設定をCSSで表示するための関数、wp_headで呼び出し
function header_output() {
    $color_base = get_theme_mod('color_base', '#fff');
    $css = '
    /**
     * custom theme
     */
    body { color: '.$color_base.'; }
    '
  ?>
    <style type="text/css">
        <?php echo $css; ?>
    </style>
    <?php
}
// 画像用サニタイザー、ファイルタイプをチェックする
function text_domain_sanitize_file( $file, $setting ) {
  //allowed file types
  $mimes = array(
    'jpg|jpeg|jpe' => 'image/jpeg',
    'gif'          => 'image/gif',
    'png'          => 'image/png'
  );

  //check file type from file name
  $file_ext = wp_check_filetype( $file, $mimes );

  //if file has a valid mime type return it, otherwise return default
  return ( $file_ext['ext'] ? $file : $setting->default );
}

// カスタマイザーの登録
add_action( 'customize_register', 'mytheme_customize_register' );

// headに設定したCSSを表示
add_action( 'wp_head' , 'header_output' );

カスタマイザーにオプションを登録するには以下の3つの設定を行う必要がある。

  • section: オプションのグループを作る
  • setting: オプションの設定をデータベースに登録
  • control: オプションの表示(フォームやラベルなど)を設定

コードを追記してカスタマイザーを表示すると、画像のように項目が追加される。

customizer.png

カスタマイザーのデータをテンプレートに表示する方法

上記のコードの場合、headで出力するものはアクションの登録で自動的に表示される。

画像はアップロードしたデータをテンプレート側で取得して表示する必要がある。

取得方法は、get_theme_mod()で登録した設定名を指定するだけ。

<?php if( get_theme_mod('logo_upload') ): ?>
  <h1><img src="<?php echo get_theme_mod('logo_upload'); ?>" alt="logo"></h1>
<?php endif; ?>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHP 配列に連想配列を入れたものをforeach文で出力する

目的

  • 下記の記事で配列に連想配列を入れることをまとめた、その応用として配列の中身をforeach文で出力する方法をまとめる

実施環境

  • MacOS上のローカル環境にテスト用スクリプトファイルを作成してVisual Studio Codeのデバッグを用いて結果を確認した。
  • 下記にVisual Studio CodeでPHPのデバッグ環境を構築する際の手順をまとめた記事へのリンクを記載する。
  • 下記に実施環境の詳細な情報を記載する。
項目 情報
OS macOS Catalina(10.15.3)
ハードウェア MacBook Air (11-inch ,2012)
プロセッサ 1.7 GHz デュアルコアIntel Core i5
メモリ 8 GB 1600 MHz DDR3
グラフィックス Intel HD Graphics 4000 1536 MB

書き方の例(連想配列のキーを出力しない)

  • 下記に配列に連想配列を入れたものを定義し、foreach文で配列の中の要素がある分だけ繰り返す処理を記載する。
  • 配列のインデックスが0の連想配列には'num1' => 10, 'num2' => 20, 'num3' => 30を格納する。
  • 配列のインデックスが1の連想配列には'num1' => 40, 'num2' => 50, 'num3' => 60を格納する。
  • 配列のインデックスが2の連想配列には'num1' => 70, 'num2' => 80, 'num3' => 90を格納する。

    # 配列の中にインデックス0の連想配列を格納する
    $data = [
        [
            'num1' => 10,
            'num2' => 20,
            'num3' => 30
        ]
    ]
    
    # 配列の末尾に連想配列を追加する(インデックス1の追加)
    array_push($data, [
            'num1' => 40,
            'num2' => 50,
            'num3' => 60
        ]);
    
    # 配列の末尾に連想配列を追加する(インデックス2の追加)
    array_push($data, [
            'num1' => 70,
            'num2' => 80,
            'num3' => 90
        ]);
    ];
    
    # 配列のインデックス0の内容から順に$datumに格納される。
    # $dataの内容は連想配列なので出力時は連想配列のそれと同じく、連想配列名('キー名')で出力できる。
    foreach ($data as $datum){
        echo $datum['num1'];
        echo '/';
        echo $datum['num2'];
        echo '/';
        echo $datum['num3'];
        echo '///';
    }
    
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む