プログラミング | POPWEB https://blog.popweb.dev Developer, Blogger, Illustrator in Tokyo. Mon, 17 Jul 2023 13:12:03 +0000 ja hourly 1 https://wordpress.org/?v=6.7.6 https://storage.googleapis.com/gcs.pop-web.net/2021/01/favicon.ico プログラミング | POPWEB https://blog.popweb.dev 32 32 window.top === window.selfは何をしているのか? https://blog.popweb.dev/programming/javascript/window-top-window-self/ https://blog.popweb.dev/programming/javascript/window-top-window-self/#respond Tue, 04 Jan 2022 13:48:00 +0000 https://blog.popweb.dev/?p=1745 プロジェクトで「if (window.top === window.self) {…}」という条件式を初めて見たので、その意味を調べてみました。 この条件式は、開いているページがiframeで読み込んだページを表示してい […]

The post window.top === window.selfは何をしているのか? first appeared on POPWEB.]]>
プロジェクトで「if (window.top === window.self) {…}」という条件式を初めて見たので、その意味を調べてみました。

この条件式は、開いているページがiframeで読み込んだページを表示しているかどうかを判定するためのものです。

window.topは、最上位のコンテキスト(ウィンドウ)を返します。iframe要素を複数埋め込んでいる場合でも、一番上の親ウィンドウを取得することができます。

一方、window.selfは現在のウィンドウ自身を返します。

したがって、iframeがないページではwindow.selfwindow.topは等価になります。これを利用して、ページがiframeを含むかどうかを判定することができます。

The post window.top === window.selfは何をしているのか? first appeared on POPWEB.]]>
https://blog.popweb.dev/programming/javascript/window-top-window-self/feed/ 0
【初心者解説】React.memo, useMemo, useCallbackとは? https://blog.popweb.dev/programming/react/%e3%80%90%e5%88%9d%e5%bf%83%e8%80%85%e8%a7%a3%e8%aa%ac%e3%80%91react-memo-usememo-usecallback%e3%81%a8%e3%81%af%ef%bc%9f/ https://blog.popweb.dev/programming/react/%e3%80%90%e5%88%9d%e5%bf%83%e8%80%85%e8%a7%a3%e8%aa%ac%e3%80%91react-memo-usememo-usecallback%e3%81%a8%e3%81%af%ef%bc%9f/#respond Tue, 23 Nov 2021 09:36:56 +0000 https://blog.popweb.dev/?p=1724 Ractには、メモ化するhookが用意されている。 そもそもメモ化とは? メモ化とは関数実行後の結果をキャッシュか何か保存しておくことによって、再度同じ関数を実行するのではなく、保存しておいた結果を返すこと。それによって […]

The post 【初心者解説】React.memo, useMemo, useCallbackとは? first appeared on POPWEB.]]>
Ractには、メモ化するhookが用意されている。

そもそもメモ化とは?

メモ化とは関数実行後の結果をキャッシュか何か保存しておくことによって、再度同じ関数を実行するのではなく、保存しておいた結果を返すこと。それによって実行速度を高速化させるためのものである。

Reactのパフォーマンスを最適化する

Reactはコンポーネントのpropsやstateが更新されると、その配下の全ての子コンポーネントも再レンダリングされる。

そのため、不要な再計算や再レンダリングを抑えるとことでパフォーマンスを最適化することができる。

その最適化の方法が、メモ化がである。

メモ化を実現する方法としてReact.memo useMemouseCallbackがある。

メモ化の対象するものがそれぞれ異なる。

  • React.memo: コンポーネントをメモ化するReactのAPI
  • useMemo: 計算結果をメモ化するHook
  • useCallback: コールバック関数をメモ化するHook

React.memo

React.memoを利用することで、コンポーネントの再レンダリングを抑止することができるのでパフォーマンス向上がする。

特に、レンダリング量が多いコンポーネントや再レンダリング頻繁に行われるコンポーネント内の子コンポーネントで有効である

React.memoの使い方

React.memoの書き方は以下のよう。

React.memo(メモ化したいコンポーネント)

以下、コードの一例

const Hoge = React.memo((props) => <div>{props.name}</div>);

codeSandbox

React.memoは、渡ってきたpropsが等価であるかをチェックして、等価であれば再レンダリングはされずにメモ化で保存したコンポーネントを再利用する。

Hogeコンポーネントは、props.nameに変更がなければコンポーネントは再レンダリングされない。

コールバック関数をpropsで渡ってきた場合は再レンダリングされる

関数に関しては再レンダリングされるたびに、新しいオブジェクトを生成するためpropsで渡ってきた場合、等価とは判断されずに再レンダリングされる。

そのため、関数の内容が同じでも再レンダリングされる。

以下がその一例

import React, { useState } from "react";

const Hoge = React.memo((props) => {
  console.log("Hoge Render!");  
  return <div onClick={props.handleClick}>{props.name}</div>
});

export const App = () => {
  const [toggle, setToggle] = useState(false);

  //  関数は再レンダリングされるたびに再生成されるため等価評価されない
  const handleClick = () => {
    console.log("Click!");
  };

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <button onClick={() => setToggle(!toggle)}>
        Appコンポーネントを再レンダリング!
      </button>
      <br />
      <Hoge name={"fuga"} handleClick={handleClick} />
    </div>
  );
};

codeSandbox

この問題を解消するためには、useCallbackを使用するとよい。

useCallback

先述にあるようにReact.memoでメモ化したコンポーネントにコールバック関数が渡ってきた場合は再レンダリングがされる。

そのため、useCallbackを併用する。

useCallbackはメモ化したコールバック関数を返すhookである。

まず、useCallbackでコールバック関数メモ化する。

メモ化したコールバック関数をReact.memoでメモ化したコンポーネントにpropsとして渡すと再レンダリングを抑止することができる。

useCallbackの使い方

useCallback(コールバック関数, 依存配列);

依存は配列には、コーバルバック関数が依存している要素を入れる。

依存している要素が更新されれば、関数も新たに生成される。

先程のコードのにuseCallbackを加えてみる。

import React, { useState, useCallback } from "react";

const Hoge = React.memo((props) => {
  console.log("Hoge Render!");
  return <div onClick={props.handleClick}>{props.name}</div>;
});

export const App = () => {
  const [toggle, setToggle] = useState(false);

  // 関数をメモ化。等価ななるためHogeコンポーネントは再レンダリングされない
  const handleClick = useCallback(() => {
    console.log("Click!");
  }, []);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <button onClick={() => setToggle(!toggle)}>
        Appコンポーネントを再レンダリング!
      </button>
      <br />
      <Hoge name={"fuga"} handleClick={handleClick} />
    </div>
  );
};

codeSandbox

注意点は、React.memoでメモ化していないコンポーネントへuseCallbackでメモ化したコールバックス関数を渡しても意味はなく、再レンダリングがされてしまう。

つまり、useCallbackはReact.memoと併用して使用するものだということ。

また、useCallbackでメモ化したコールバック関数を、自身のコンポーネントで利用しても動作はするが意味がない。

useMemo

useMemoは計算結果の値をメモ化して返すhook。

useMemoの使い方

useMemo(() => 計算結果を出すロジック, 依存配列);

useMemoは、値が変わらない場合、再計算をさせないことでパフォーマンスを向上することができる。

依存配列には、値を計算する際に依存している要素を入れて、更新された時だけ再計算がされる。

また、React.memoのようにレンダリングもメモ化できる。

以下のコードは2倍にする計算をメモ化している。

Appコンポーネントが再レンダリングされても、doubleが実行されないことが分かる。

import React, { useState, useMemo } from "react";

export const App = () => {
  const [toggle, setToggle] = useState(false);

  const double = (count) => {
    console.log("Run double!");
    return count * 2;
  };

 // 2倍する計算結果をメモすることで、再レンダリングされても再計算されない
  const doubleResult = useMemo(() => double(1), []);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <button onClick={() => setToggle(!toggle)}>
        Appコンポーネントを再レンダリング!
      </button>
      <div>{doubleResult}</div>
    </div>
  );
};

codeSandbox

レンダリングのメモ化

useMemoはレンダリングもメモ化できる。

以下は、Hogeコンポーネントのレンダリングをメモ化して、不要なレンダリングを抑止している。

注意点として、関数コンポーネント内で、コンポーネントをメモ化したい時にuseMemoでメモ化ができるが、React.memoのようにコンポーネント外でではできない。

逆にコンポーネント内でReact.memoを利用しても意味がない。

import React, { useState, useMemo } from "react";

export const App = () => {
  const [toggle, setToggle] = useState(false);

  const Hoge = useMemo(() => {
    console.log("Hoge Render!");
    return <div>fuga</div>;
  }, []);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <button onClick={() => setToggle(!toggle)}>
        Appコンポーネントを再レンダリング!
      </button>
      <br />
      {Hoge}
    </div>
  );
};

codeSandbox

メモ化をする処理自体のコストについて

useMemoやuseCallbackを使用してメモ化することで、パフォーマンスの向上を見込めるが、何でもかんでもメモ化したらいいわけではない。

なぜなら、メモ化する処理自体にもコストがかかるから。

useCallbackのメモ化のコストは、関数を再生成するコストより大きくなってしまう場合が多いから。

なので、useCallbackをわざわざ利用する必要ないところで使用するとパフォーマンスが悪くなってしまうということ。

明らかに再レンダリングや再計算のコストが高い場合に使用して、適切に使用することがポイントとなる。

The post 【初心者解説】React.memo, useMemo, useCallbackとは? first appeared on POPWEB.]]>
https://blog.popweb.dev/programming/react/%e3%80%90%e5%88%9d%e5%bf%83%e8%80%85%e8%a7%a3%e8%aa%ac%e3%80%91react-memo-usememo-usecallback%e3%81%a8%e3%81%af%ef%bc%9f/feed/ 0
【JavaScript】プリミティブ型(基本型)とオブジェクト型(参照型)について https://blog.popweb.dev/programming/javascript/primitive-object/ https://blog.popweb.dev/programming/javascript/primitive-object/#respond Sat, 16 Oct 2021 08:14:10 +0000 https://blog.pop-web.net/?p=1020 JavaScriptにのデータ型には、プリミティブ型(基本型)とオブジェクト型(参照型)がある 目次 プリミティブ型(基本型)オブジェクト型(参照型)プリミティブ型とオブジェクト型の違いプリミティブ型の場合オブジェクト型 […]

The post 【JavaScript】プリミティブ型(基本型)とオブジェクト型(参照型)について first appeared on POPWEB.]]>
JavaScriptにのデータ型には、プリミティブ型(基本型)とオブジェクト型(参照型)がある

プリミティブ型(基本型)

真偽値(boolean)
数値(number)
文字列(string)
null
undefined
シンボル(symbol)

オブジェクト型(参照型)

プリミティブ型(基本型)以外のデータ型

オブジェクト(object)
配列(array)
関数(function)

プリミティブ型とオブジェクト型の違い

プリミティブ型は変数をコピーする時、変数の中身の値がそのままコピーされる。

オブジェクト型は変数をコピーする時、その値がコピーされるのではなく、そのオブジェクトが持っているメモリ上のアドレスがコピーされる。

以下がその例

プリミティブ型の場合

let a = 20;
let b = a;
a = 80;
console.log(a); // 80
console.log(b); // 20

bにaを代入した後にaに新たに100の値を代入しているが、bに影響は受けない。

さっきも説明したように、メモリ参照せずに変数の値をそのままコピーしていることが分かる。

オブジェクト型の場合

let obj1 = {
  name: "ken",
  age: 20
};
let obj2 = obj1;
obj1.age = 80;
console.log(obj1.age); // 100
console.log(obj2.age); // 100

obj2にobj1を代入することで、obj1もobj2も同じメモリ上のアドレスと保持するようになったため、片方のageの値を変更すると、もう片方の値も同じになる。

The post 【JavaScript】プリミティブ型(基本型)とオブジェクト型(参照型)について first appeared on POPWEB.]]>
https://blog.popweb.dev/programming/javascript/primitive-object/feed/ 0
eslintのルールで特定ファイルのみ適用外にしたい場合の書き方 https://blog.popweb.dev/programming/javascript/eslint-overrides/ https://blog.popweb.dev/programming/javascript/eslint-overrides/#respond Fri, 28 May 2021 08:14:55 +0000 https://blog.popweb.dev/?p=1697 .eslintrcのrulesに「defalut export」の記述を禁止するルールを追加したとする。 このとき、sotrybookのstories.tsxにはこのルールは適用外にしたい。 その場合にはどうするか? o […]

The post eslintのルールで特定ファイルのみ適用外にしたい場合の書き方 first appeared on POPWEB.]]>
.eslintrcのrulesに「defalut export」の記述を禁止するルールを追加したとする。

module.exports = {
...
  rules: {
...
    "import/no-default-export": "error",
...
  }
};

このとき、sotrybookのstories.tsxにはこのルールは適用外にしたい。

その場合にはどうするか?

overridesを使って、適用したいファイル名とルールを無効化する記述すればよい。

module.exports = {
...
  rules: {
...
    "import/no-default-export": "error",
...
  },
  overrides: [
    {
      files: ["**/*.stories.tsx"],
      rules: {
        "import/no-default-export": "off",
      },
    },
  ],
};

参考文献

Configuration Files - ESLint - Pluggable JavaScript Linter
A pluggable and configurable linter tool for identifying and reporting on patterns in JavaScript. Maintain your code qua...
The post eslintのルールで特定ファイルのみ適用外にしたい場合の書き方 first appeared on POPWEB.]]>
https://blog.popweb.dev/programming/javascript/eslint-overrides/feed/ 0
【Laravel】中間テーブルのカラムに対して検索をかけたい時【whereHas】 https://blog.popweb.dev/programming/laravel/%e3%80%90laravel%e3%80%91%e4%b8%ad%e9%96%93%e3%83%86%e3%83%bc%e3%83%96%e3%83%ab%e3%81%ae%e3%82%ab%e3%83%a9%e3%83%a0%e3%81%ab%e5%af%be%e3%81%97%e3%81%a6%e6%a4%9c%e7%b4%a2%e3%82%92%e3%81%8b%e3%81%91/ https://blog.popweb.dev/programming/laravel/%e3%80%90laravel%e3%80%91%e4%b8%ad%e9%96%93%e3%83%86%e3%83%bc%e3%83%96%e3%83%ab%e3%81%ae%e3%82%ab%e3%83%a9%e3%83%a0%e3%81%ab%e5%af%be%e3%81%97%e3%81%a6%e6%a4%9c%e7%b4%a2%e3%82%92%e3%81%8b%e3%81%91/#respond Wed, 17 Mar 2021 01:10:12 +0000 https://blog.popweb.dev/?p=1677 タイトル通りだが、まずはやりたいことの説明 目次 やりたいこと状況解決方法 やりたいこと リレーション先の中間テーブルのカラムの値に対して検索をかけたい。 状況 menus、stores、menu_store(中間テーブ […]

The post 【Laravel】中間テーブルのカラムに対して検索をかけたい時【whereHas】 first appeared on POPWEB.]]>
タイトル通りだが、まずはやりたいことの説明

やりたいこと

リレーション先の中間テーブルのカラムの値に対して検索をかけたい。

状況

menus、stores、menu_store(中間テーブル)とうテーブルを作成しており、

モデルは以下のような感じで中間テーブルを置いてリレーションしている。

class Menu extends Model
{    
    public function stores()
    {
      return $this->belongsToMany('App\Store','menu_store','menu_id','store_id')->withTimestamps();
    }
}
class Store extends Model
{    
    public function menus()
    {
      return $this->belongsToMany('App\Menu');
    }
}

解決方法

whereHasを使う。

以下だと、中間テーブルであるmenu_storeのstore_idでwhereInで条件を絞りたい時の場合。

$storeId = [1,2,3]
$query = Menu::query();
$query->whereHas('stores', function($q) use($storeId)  {
    $q->whereIn('menu_store.store_id', $storeId);
});

コールバック関数の中でリレーション先である中間テーブルの検索条件を指定してあげれば良い。

中間テーブルのカラムではなく、中間テーブルを介して結合しているテーブル(storesテーブル)のカラムで検索することも可能。

その場合も同様でコールバック関数の中の詳細条件を変更すれば良い。

$q->whereIn('store.store_id', $storeId)

The post 【Laravel】中間テーブルのカラムに対して検索をかけたい時【whereHas】 first appeared on POPWEB.]]>
https://blog.popweb.dev/programming/laravel/%e3%80%90laravel%e3%80%91%e4%b8%ad%e9%96%93%e3%83%86%e3%83%bc%e3%83%96%e3%83%ab%e3%81%ae%e3%82%ab%e3%83%a9%e3%83%a0%e3%81%ab%e5%af%be%e3%81%97%e3%81%a6%e6%a4%9c%e7%b4%a2%e3%82%92%e3%81%8b%e3%81%91/feed/ 0
【JavaScript入門】reduceについて説明と使い方 https://blog.popweb.dev/programming/javascript/javascript-reduce/ https://blog.popweb.dev/programming/javascript/javascript-reduce/#respond Tue, 26 Jan 2021 09:06:52 +0000 https://blog.popweb.dev/?p=1476 reduce()の説明と使い方を説明する。 reduce()は、配列の隣り合う値に対して関数を適用させて、その実行結果を返すメソッド。 コードを書いて動きを確認してみる。 まず、第2引数のcurには、arrの値が順番に入 […]

The post 【JavaScript入門】reduceについて説明と使い方 first appeared on POPWEB.]]>
reduce()の説明と使い方を説明する。

reduce()は、配列の隣り合う値に対して関数を適用させて、その実行結果を返すメソッド。

コードを書いて動きを確認してみる。

const arr = [1, 2, 3]

console.log(arr.reduce((acc, cur) => acc + cur)) // 6

まず、第2引数のcurには、arrの値が順番に入ってくる。

第1引数accには前回実行時の値が入ってくる。

そして、返値として最後に実行された値を返す。

具体的に実行処理は以下。

  • 1回目の実行:cur=1となり、前回実行の値はないので、1が返る
  • 2回目の実行:cur=2となり、前回実行の値はacc=1なので、1+2=3が返る
  • 3回目の実行:cur=3となり、前回実行の値はacc=1なので、3+3=6が返る
The post 【JavaScript入門】reduceについて説明と使い方 first appeared on POPWEB.]]>
https://blog.popweb.dev/programming/javascript/javascript-reduce/feed/ 0
LaravelでスクレイピングしてHerokuで定期実行する方法 https://blog.popweb.dev/programming/laravel/laravel%e3%81%a7%e3%82%b9%e3%82%af%e3%83%ac%e3%82%a4%e3%83%94%e3%83%b3%e3%82%b0%e3%81%99%e3%82%8b%e6%96%b9%e6%b3%95/ https://blog.popweb.dev/programming/laravel/laravel%e3%81%a7%e3%82%b9%e3%82%af%e3%83%ac%e3%82%a4%e3%83%94%e3%83%b3%e3%82%b0%e3%81%99%e3%82%8b%e6%96%b9%e6%b3%95/#respond Fri, 22 Jan 2021 04:38:07 +0000 https://blog.popweb.dev/?p=1472 まず、LaravelでWebスクレイピングするため、ライブラリである「FriendsOfPHP/Goutte」をインストールする。 LaravelのバージョンはLaravel6.20。 目次 インストール実装contro […]

The post LaravelでスクレイピングしてHerokuで定期実行する方法 first appeared on POPWEB.]]>
まず、LaravelでWebスクレイピングするため、ライブラリである「FriendsOfPHP/Goutte」をインストールする。

LaravelのバージョンはLaravel6.20。

インストール

$ composer require fabpot/goutte

以前のLaravelのバージョンではconfigファイルを設定する必要があるが、Laravel5.5以降はAutoDiscoveryがあるのでそのまま使える。

実装

まず、controllerを作成する。

$ php artisan make:controller ScrapingController

controllerに処理を書く

今回は漫画書籍ランキングからタイトルだけ取得してみる。

<?php

namespace App\Http\Controllers;

use Goutte\Client;

class ScrapingController extends Controller
{
    public function scraping()
    {
        $client = new Client();
        $crawler = $client->request('GET', 'https://www.amazon.co.jp/gp/bestsellers/digital-text/2430812051/ref=pd_zg_hrsr_digital-text');
        $titles = $crawler->filter('li.zg-item-immersion')->each(function ($li) {
            $title = $li->filter('div.p13n-sc-truncate-desktop-type2')->text();
            return $title;
        });
        return view('scraping', compact('titles'));
    }
}

基本的には、use Goutte\Client;してnew Client();でインスタンスを作ると色々メソッドが使えるようになる。

使い方は、FriendsOfPHP/GoutteDomCrawlerが参考になると思う。

viewを作る

次に取得したタイトルを表示するviewをつくる。

@extends('layouts.app')

@section('content')
    <ol class="container">
        @foreach($titles as $title)
            <li>{{ $title }}</li>
        @endforeach
    </ol>
@endsection

ルーティングの設定

Route::get('/scraping', 'ScrapingController@scraping')->name('scraping');

表示の確認

ブラウザで表示確認してみる。

定期実行のやり方

定期実行されるには、まずコマンドラインで実行させるためコマンドクラスを作成する。

$ php artisan make:command ScrapingCommand

コマンドクラスに処理を書く

app/Console/Commands/ScrapeCommand.phpが作成されているので、これを編集。

<?php

namespace App\Console\Commands;

// useでGoutte\Clientをインポート
use Goutte\Client;
use Illuminate\Console\Command;

class ScrapingCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    // コマンド名を変更
    protected $signature = 'command:ScrapingCommand';

    /**
     * The console command description.
     *
     * @var string
     */
    // コマンドの説明を変更
    protected $description = 'スクレイピングコマンド';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        // スクレイピング処理を書く
        $client = new Client();
        $crawler = $client->request('GET', 'https://www.amazon.co.jp/gp/bestsellers/digital-text/2430812051/ref=pd_zg_hrsr_digital-text');
        $titles = $crawler->filter('li.zg-item-immersion')->each(function ($li) {
            $title = $li->filter('div.p13n-sc-truncate-desktop-type2')->text();
            return $title;
        });
        dd($titles);
    }
}

コマンドを実行してみる

$ php artisan command:ScrapingCommand

コマンド実行後、コマンドラインから取得が確認できたらOK。

データベース保存

データベースに保存する処理を追加。

モデルとマイグレーションファイルを作成しておく。

$ php artisan make:model Item -m

作成されたマイグレーションファイルを編集

<?php

//...

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('items', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('title');
            $table->timestamps();
        });
    }

    //...
}

マイグレーションを実行しておく。

$ php artisan migrate

データベース保存

コマンドクラスにデータベース保存処理を追記。

<?php

namespace App\Console\Commands;

use App\Item;
use Goutte\Client;
use Illuminate\Console\Command;

class ScrapingCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    // コマンド名
    protected $signature = 'command:ScrapingCommand';

    /**
     * The console command description.
     *
     * @var string
     */
    // コマンドの説明
    protected $description = 'スクレイピングコマンド';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        // スクレイピング処理を書く
        $client = new Client();
        $crawler = $client->request('GET', 'https://www.amazon.co.jp/gp/bestsellers/digital-text/2430812051/ref=pd_zg_hrsr_digital-text');
        $titles = $crawler->filter('li.zg-item-immersion')->each(function ($li) {
            $title = $li->filter('div.p13n-sc-truncate-desktop-type2')->text();
            return $title;
        });
        //データベース保存
        foreach ($titles as $title)
        {
            $item = new Item;
            $item->title = $title;
            $item->save();
        }
    }
}

Herokuに定期実行を設定

Herokuにアプリをデプロイしておく。

次に、HerokuSchedulerアドオンをアプリに追加。

$ heroku addons:create scheduler:standard

HerokuSchedulerのダッシュボードを開く。

$ heroku addons:open scheduler

Add Jobをクリックして、ジョブを登録する。

「Schedule」で実行時刻を選択し、「Run Command」に作成したコマンドクラスを実行するコマンドを入力しておく。

これで、定期的にスクレイピングしてデータを取得できるようになる。

The post LaravelでスクレイピングしてHerokuで定期実行する方法 first appeared on POPWEB.]]>
https://blog.popweb.dev/programming/laravel/laravel%e3%81%a7%e3%82%b9%e3%82%af%e3%83%ac%e3%82%a4%e3%83%94%e3%83%b3%e3%82%b0%e3%81%99%e3%82%8b%e6%96%b9%e6%b3%95/feed/ 0
テキスト下に蛍光色ラインマーカーをCSSで作る(改行対応) https://blog.popweb.dev/programming/css/css-line-marker/ https://blog.popweb.dev/programming/css/css-line-marker/#respond Thu, 31 Dec 2020 22:56:58 +0000 https://blog.popweb.dev/?p=1568 改行されているテキストにも対応できるCSSによるラインマーカーの作成。 以下、コード。 HTML CSS

The post テキスト下に蛍光色ラインマーカーをCSSで作る(改行対応) first appeared on POPWEB.]]>
改行されているテキストにも対応できるCSSによるラインマーカーの作成。

以下、コード。

HTML
<p>
  テキストテキストテキストテキストテキスト<br />
  <span class="line-marker">テキストテキストテキストテキストテキスト<br />
    テキストテキスト</span>テキストテキストテキスト<br />
  テキストテキストテキストテキストテキスト
</p>
CSS
.line-marker {
	background: linear-gradient(transparent 70%, #FDDEB3 0%);
	display: inline;
	padding: 0 2px 4px;
}
The post テキスト下に蛍光色ラインマーカーをCSSで作る(改行対応) first appeared on POPWEB.]]>
https://blog.popweb.dev/programming/css/css-line-marker/feed/ 0
【初心者向け解説】PHPのクラス、抽象クラス、インターフェース、トレイトについて https://blog.popweb.dev/programming/php/php-object-orientation/ https://blog.popweb.dev/programming/php/php-object-orientation/#respond Wed, 02 Dec 2020 12:13:00 +0000 https://blog.popweb.dev/?p=1478 まず、オブジェクト指向とはなにかについて説明。 オブジェクト指向は、ざっくりいうと役割をクラスごとに分けてそれを組み合わせながらプログラミングを行っていくこと。 クラスは、変数、定数、関数を一つにまとめたものである。 オ […]

The post 【初心者向け解説】PHPのクラス、抽象クラス、インターフェース、トレイトについて first appeared on POPWEB.]]>
まず、オブジェクト指向とはなにかについて説明。

オブジェクト指向は、ざっくりいうと役割をクラスごとに分けてそれを組み合わせながらプログラミングを行っていくこと。

クラスは、変数、定数、関数を一つにまとめたものである。

オブジェクト指向の3つの要素として以下があげられる。

  • クラス継承
  • カプセル化
  • ポリモーフィズム(多様性)

クラスの種類には、クラス、抽象クラス、インターフェース、トレイトというものがある。

それぞれ使い方や特徴は以下の通り。

クラスの種類宣言方法使用方法特徴
クラスclassextends一般的なクラス
抽象クラスabstract classextends継承専用のクラス
インターフェースinterfaceimplementsメソッドのみ
トレイトtraituseuseで複数継承できる

クラスとインスタンスについて

まず、クラスからインスタンスを作るという基本的なやり方から。

<?php

class Human
{
    private $name = [];

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

    public function getName()
    {
        echo $this->name;
    }

    public static $friendName = '鈴木くん';
}

$instance = new Human('山田くん');

$instance->getName(); // 山田くん

echo Human::$friendName; // 鈴木くん

Humanクラスから、newを使ってインスタンスを生成する。

__constructは、インスタンスを生成するときに呼び出される初期化処理を書くことができる。

ここでは、インスタンス生成時に渡した値(’山田くん’)が、Humanクラスの$name変数に入る。

そして、インスタンス化されたオブジェクトである$intanceの関数であるgetNameで値を表示している。

また、staticを使用することで、インスタンスを生成せずに、静的にプロパティやメソッドを呼び出すこともできる。

呼び出し方は、24行目のように「クラス名::メソッド名」または、「クラス名::プロパティ名」という感じ。

クラスの継承

クラスの継承はextendを使って行う。

<?php

class BaseHuman
{
    public function echoFunction()
    {
        echo 'BaseHumanのメソッドです。';
    }
}

class Human extends BaseHuman
{
    private $name = [];

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

    public function getName()
    {
        echo $this->name;
    }
}

$instance = new Human('山田くん');

$instance->echoFunction(); // BaseHumanのメソッドです。

BaseHumanというクラスを作成して、Humanクラスで継承する。

そうすると、Humanクラスのインスタンス化したオブジェクトでBaseHumaクラスのメソッドを呼び出すことができる。

継承元と同じメソッドを定義することで上書き(オーバーライド)することができる。

<?php

class BaseHuman
{
    public function echoFunction()
    {
        echo 'BaseHumanのメソッドです。';
    }
}

class Human extends BaseHuman
{
    private $name = [];

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

    public function getName()
    {
        echo $this->name;
    }

    // 上書きオーバーライド
    public function echoFunction()
    {
        echo 'Humanのメソッドです。';
    }
}

$instance = new Human('山田くん');

$instance->echoFunction(); // Humanのメソッドです。

上記では、BaseHumanのメソッドであるechoFunction()を上書きしている。

補足:アクセス修飾子について

クラス内で使用する変数や関数にアクセス修飾子とつけて、どこからアクセスできるかを指定することができる。

アクセス修飾子説明
privateクラス外がアクセスできない、自分のクラスからのみアクセスできる
protected自分のクラスか、継承したクラスからアクセスできる
publicクラス外でも自分のクラスからでもアクセスできる

抽象クラスのついて

抽象クラスは継承される前提のクラスで、継承先で設定するメソッドやプロパティを強制する役割を持つ。

抽象クラスにはclassの前にabstractを付ける。そして、抽象化したいメソッドの前にもabstractを付けることで継承先で強制ができる。

この時、abstractを付けて、abstractメソッドにするとメソッドの中身は書けないことになっている。

abstractメソッドと普通のpublicメソッドも混在して定義することもできる。

継承するにはextendを用いる。

<?php

// 抽象クラス
abstract class humanAbstract
{
    public function echoFunction(){
        echo '抽象クラスのメソッドです。';
    }
    abstract public function getName();
}

// 具象クラス
class Human extends humanAbstract
{
    private $name = [];

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

    public function getName() // 抽象クラスでabstract設定したため必ず必要なメソッド
    {
        echo $this->name;
    }
}

インターフェースについて

インターフェースと抽象クラスの違いは、すべて強制するメソッドしか描けないこと。

定義する場合は、先頭にinterfaceとして、使用する場合はimplementsを使う。

抽象クラスの場合、1つの抽象クラスしか継承できないが、インターフェースは複数適用することが可能。

<?php

// インターフェース
interface humanInterface
{
    public function getName();
}

// インターフェース
interface foodInterface
{
    public function getFood();
}

// 具象クラス
class Human implements humanInterface,foodInterface
{
    private $name = [];

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

    public function getName() // 抽象クラスでabstract設定したため必ず必要なメソッド
    {
        echo $this->name;
    }
    public function getFood()
    {
        echo '食べ物です';
    }
}

$instance = new Human('山田くん');
$instance->getName(); // 山田くん
$instance->getFood(); // 食べ物です

トレイトについて

先頭にtraitとつけてclassと同じように定義していく。

使いたいclassの中にuseを使うことでtraitの内容を反映することができる。

traitも複数呼び出すことが可能で、上書き(オーバーライド)もできる。

<?php

trait HumanTrait
{
    public function getName(){
        echo '名前です';
    }
}

trait FoodTrait
{
    public function getFood(){
        echo '食べ物です';
    }
}

class Human{
    use HumanTrait;
    use FoodTrait;
    public function echoFunction()
    {
        echo 'Humanクラスです';
    }
}

$instance = new Human();

$instance->echoFunction(); // Humanクラスです
$instance->getName(); // 名前です
$instance->getFood(); // 食べ物です

以上、クラス、抽象クラス、インターフェース、トレイトの説明終わり。

The post 【初心者向け解説】PHPのクラス、抽象クラス、インターフェース、トレイトについて first appeared on POPWEB.]]>
https://blog.popweb.dev/programming/php/php-object-orientation/feed/ 0
Nuxt.jsで「TypeError: Cannot set property ‘render’ of undefined」のコソールエラー対処法 https://blog.popweb.dev/programming/vue-js/nuxt-js-typeerror-cannot-set-property-render-of-undefined/ https://blog.popweb.dev/programming/vue-js/nuxt-js-typeerror-cannot-set-property-render-of-undefined/#respond Wed, 28 Oct 2020 04:11:56 +0000 https://blog.popweb.dev/?p=1469 目次 エラー内容原因と対処法 エラー内容 Nuxt.jsで開発中、以下のコンソールエラーが出て画面が表示されなくなった。 原因と対処法 <script>タグの閉じタグがなかったり、空の<script&g […]

The post Nuxt.jsで「TypeError: Cannot set property ‘render’ of undefined」のコソールエラー対処法 first appeared on POPWEB.]]>

エラー内容

Nuxt.jsで開発中、以下のコンソールエラーが出て画面が表示されなくなった。

TypeError: Cannot set property 'render' of undefined

原因と対処法

<script>タグの閉じタグがなかったり、空の<script>タグが存在しているとエラーとなるため、ちゃんと閉じタグをしてあげるか、空タグを削除してあげるとよい。

The post Nuxt.jsで「TypeError: Cannot set property ‘render’ of undefined」のコソールエラー対処法 first appeared on POPWEB.]]>
https://blog.popweb.dev/programming/vue-js/nuxt-js-typeerror-cannot-set-property-render-of-undefined/feed/ 0