- 投稿日:2019-07-24T23:51:43+09:00
Laravel を composer からインストールできない
概要
composer global require laravel/installer
このURL:https://laravel.com/docs/5.8からのコピペでインストールしようとしたが、エラーで弾かれた。環境
- CentOS7
- php7.2
エラー内容
$ composer global require laravel/installer Changed current directory to /home/ec2-user/.config/composer Using version ^2.1 for laravel/installer ./composer.json has been created Loading composer repositories with package information Updating dependencies (including require-dev) Your requirements could not be resolved to an installable set of packages. Problem 1 - Installation request for laravel/installer ^2.1 -> satisfiable by laravel/installer[v2.1.0]. - laravel/installer v2.1.0 requires ext-zip * -> the requested PHP extension zip is missing from your system. To enable extensions, verify that they are enabled in your .ini files: - /etc/opt/remi/php72/php.ini - /etc/opt/remi/php72/php.d/20-bz2.ini - /etc/opt/remi/php72/php.d/20-calendar.ini - /etc/opt/remi/php72/php.d/20-ctype.ini - /etc/opt/remi/php72/php.d/20-curl.ini - /etc/opt/remi/php72/php.d/20-exif.ini - /etc/opt/remi/php72/php.d/20-fileinfo.ini - /etc/opt/remi/php72/php.d/20-ftp.ini - /etc/opt/remi/php72/php.d/20-gettext.ini - /etc/opt/remi/php72/php.d/20-iconv.ini - /etc/opt/remi/php72/php.d/20-json.ini - /etc/opt/remi/php72/php.d/20-phar.ini - /etc/opt/remi/php72/php.d/20-sockets.ini - /etc/opt/remi/php72/php.d/20-tokenizer.ini You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode. Installation failed, deleting ./composer.json.原因
- phpのZIPが利用出来ないためのエラーだった
yum install php-zipが出来なかった解決方法
試しに以下のコードを打ったところ[php72-php-pecl-zip]がインストールされた
yum install php72-php-zipこのあとに、
composer global require laravel/installerを実行したら普通にコマンドが通りました。
★php-zip という古い記事にかかれたものは、入りませんでした。
- 投稿日:2019-07-24T23:38:17+09:00
LaravelのControllerで生成・加工したデータをVue.jsのテンプレートファイルで利用する方法
はじめに
LaravelとVue.jsでちょっとしたアプリを作っていた時に、LaravelのControllerで生成・加工したデータをVue.jsのテンプレートファイルに渡して使用するには下記の手順でデータを渡す必要がありましたので今後必要になった時に直ぐに思い出せる様にまとめたいと思います。
Controller→View(Bladeファイル)→Vue(Vue.jsテンプレート)前提とするデータ構成
とある店舗情報を格納するデータをDB等から取得して下記の多次元配列としてControllerで整形したと想定します。
*Controllerでの細かいデータの取得・加工処理については本記事では割愛します。array(5){ 0 => array(5) 1 => array(5) 2 => array(5) 3 => array(5) 4 => array(5) }valueである各配列の中身は下記の様な形式のデータとします。
array(5){ 'shopId' => "testId1", 'shopName' => "testShop1", 'price' => "1000", 'shopTel' => "1234-5678-90", 'shopMessage' => array('short' => "test shot message", 'long' => "test long message" ), 'shopImage' => array('url1' => "https://example.com/sample1.jpg", 'url2' => "https://example.com/sample2.jpg" ) }Controller
順を追って、まずはControllerから流れを見て行きます。
上記の店舗情報データを$sampleDataとします。
この$sampleDataをVueファイルで配列の様に扱うにはjsonエンコーディングを行いオブジェクト化する必要があります。
$shopData = json_encode($sampleData);viewを指定する箇所を含めると下記の様な具合になります。
app/Http/Controllers/SampleController.php
public function index() { /*** データの加工処理は省略 ***/ // 配列のjsonエンコード化 $shopData = json_encode($sampleData); // viewファイルに$shopDataを渡す return view('index')->with('shopData', $shopData); }View
次はViewファイルを見て行きます。
bodyタグ内を下記の通り記述して行きます。
resources/views/index.blade.php
<main id="app"> <shop-page v-bind:shop-data="{{ $shopData }}"></shop-page> </main>shop-pageタグがVueテンプレートの内容を反映する箇所です。
このshop-pageタグにControllerから受け取ったデータをバインド(結びつける)します。
「v-bind」属性(ディレクティブ)でバインドを行います。
v-bindで指定した「shop-data」がVueテンプレート内にてControllerから来た$shopDataのデータを受け持つことになります。
Vueテンプレート内ではキャルメルケースのshopDataと言う名前でデータが利用されることになります。Vueテンプレート
Vueテンプレートの中身は下記の通りです。
resources/components/ShopPage.vue
<template> <div class="card text-white bg-dark mb-3" v-for="shop in shopData"> <div class="row no-gutters"> <img class="card-img" :src="shop.shopImage.url1" alt="no image"> <div class="card-body"> <h3 class="card-title">{{ shop.shopName }}</h3> <p class="card-text">{{ shop.shopMessage.short }}</p> </div> </div> </div> </template> <script> export default { props: { shopData: { type: Object }, }, name:'shop-page' } </script>scriptタグ内のprops(プロパティ)に記載されているshopDataがbladeファイル内での$shopDataになります。
型にObject型を指定する必要があります。データの利用例として、templateタグ内で店舗情報をBootstrapのcardで表示するコードを記載しています。
for文の要領で店舗情報ごとにcardを作成するには一番外側のcardクラスが指定されたdivタグ内でv-forディレクティブを設定する方法があります。
下記の通りに指定することでforeach文の様に各店舗情報のオブジェクトを抽出することが出来ます。v-for="shop in shopData"今回のデータ構成ではkeyの値を参照する必要の無い作りになっている為「v-for」ディレクティブでkeyの値を取得していませんが、もし必要な場合は下記の通りに記載する必要があります。
v-for="(shop, key) in shopData"「shop」はControllerで生成したの店舗ごとの情報をまとめたデータです。
このshopの値は「v-for」ディレクティブが指定されたタグ内で記載されている全てのタグ内で各データに沿ったkeyを指定することで利用出来ます。shop{ 'shopId' : "testId1", 'shopName' : "testShop1", 'price' : "1000", 'shopTel' : "1234-5678-90", 'shopMessage' : { 'short' : "test shot message", 'long' : "test long message" }, 'shopImage' : { 'url1' : "https://example.com/sample1.jpg", 'url2' : "https://example.com/sample2.jpg" } }h1タグやpタグにて文字列を出力する場合は下記の通り二重括弧を使って値を指定します。
<h1 class="card-title">{{ shop.shopName }}</h1> <p class="card-text">{{ shop.shopMessage.short }}</p>画像を表示させる場合は少し書き方が異なります。
src属性に画像データのパスやURLを指定しますが、「src」の直前に「:」(コロン)を指定する必要がある。<img class="card-img" :src="shop.shopImage.url1" alt="no image">店舗情報をボタンクリックイベント後の関数で利用したい場合は下記の様に「v-on:click」ディレクティブに関数名を指定してパラメータとして店舗情報を指定すると良いです。
関数定義内の各詳細のデータの指定の仕方は同様です。<a v-on:click="testFunc(shop)" href="javascript::void(0)" class="btn btn-primary">detail</a>ちなみに
bladeファイル上で配列のkey指定をして数値や文字列など単体のデータを渡す場合はControllerでjsonエンコードを行う必要はありません。
配列のままbladeファイルでkey指定することによって単体のデータを渡すことが出来ます。app/Http/Controllers/SampleController.php
$singleValue = array('key1' => 1, 'key2' => 2, 'key3' => 3);resources/views/index.blade.php
<shop-page v-bind:shop-data="{{ $shopData }}" v-bind:single-value="{{ $singleValue['key1'] }}" ></shop-page>この場合はVueファイル内ではpropsでNumber型やString型を指定する必要があります。
以上です。
LaravelをやるとVue.jsに触れる機会が出てくる為この辺りの理解も深める必要があるなと感じました!
- 投稿日:2019-07-24T23:27:14+09:00
laravelでchar型等のカラム属性を変更する
少しハマったのでメモ
laravelのマイグレーションでchar型等のカラム属性をchangeメソッドで変更する事が出来ない。
Laravel 5.8 データベース:マイグレーション
https://readouble.com/laravel/5.8/ja/migrations.html
上記より抜粋↓
Note: 以降のカラムタイプのみ変更可能です:bigInteger、binary、boolean、date、dateTime、dateTimeTz、decimal、integer、json、longText、mediumText、smallInteger、string、text、time、unsignedBigInteger、unsignedInteger and unsignedSmallIntegerそのため、上記以外のカラムタイプの場合、下記のようにSQLを直接実行すればカラム属性を変更する事ができます。
public function up() { DB::statement(" ALTER TABLE <テーブル名> MODIFY <カラム名> <カラム属性> "); }
- 投稿日:2019-07-24T17:16:11+09:00
Laravelで、Namespace declaration statement has to be the very first statement or after any declare call in the scriptってエラーが出た時の対策
環境
Ubuntu 16.04.5 LTS (Xenial Xerus)
Laravel Framework 5.6.26状況
普通にコントローラーを作っていて、エディタ上ではエラーがないのでサーバーを立ち上げてみると、
「Namespace declaration statement has to be the very first statement or after any declare call in the script」
とエラーが出ました。ググったら、
・namespaceの上に何も書くな
・<?php の上に何も書くな
みたいなことが書いてあったのですが、自分のコードを見た感じ問題なさそうだったが、、、僕の解決策
<?php
の上に文字はないが、改行されていた。
まず、IPを確認//ここは何もなく改行されていた。 <?php //Bladeのテンプレートを使ってみるコントローラ namespace App\Http\Controllers;上記の何もない行をつめた。
<?php //Bladeのテンプレートを使ってみるコントローラ namespace App\Http\Controllers;これでうまくいった。
感想
フレームワークとかではなくPHP単体で使っていた時は、
そんなことでエラーがでた記憶はないのだが、、、
- 投稿日:2019-07-24T16:49:30+09:00
Laravel ScoutでAlgolia使って全文検索〜リレーション・データベース同期編 〜
はじめに
前回までにやったことは以下の記事をご参照ください。
Lalavel ScoutでAlgoliaを使って全文検索を実装してみた!今回やること
・Algoliaにリレーションを実装
・Algoliaとデータベースの同期をとる前提
・scoutのインストールが完了している
booksテーブルとauthorsテーブルがあり、それぞれのモデルがすでにあるものとします。モデルの編集
まずリレーション定義をします。ここまではいつも書くLaravelのアレです。
App\Book.php<?php namespace App; use Illuminate\Database\Eloquent\Model; class Book extends Model{ //リレーション定義 public function author() { return $this->belongsTo('App\Author'); } }App\Author.php<?php namespace App; use Illuminate\Database\Eloquent\Model; class Author extends Model { //リレーション定義 public function books() { return $this->hasMany('App\Book'); } }次に全文検索できるようにメソッドを追加します。
ここで、Algoliaのリレーションについての話になるのですが、作成したインデックス同士のリレーションは定義できません!!
そのため、インデックス作成時にあらかじめリレーション定義したい項目を追加しておく必要があります。リレーションのカラムが追加されるイメージです。
早速処理を記述します。App\Book.php<?php namespace App; use Laravel\Scout\Searchable; use Illuminate\Notifications\Notifiable; use Illuminate\Database\Eloquent\Model; class Book extends Model{ use Searchable; use Notifiable; protected $touches = ['author']; public function searchableAs() { return 'books_index'; } public function toSearchableArray() { $array = $this->toArray(); $array = $this->transform($array); $array['author_name'] = $this->author->name; return $array; } public function author() { return $this->belongsTo('App\Author'); } }まず
use Laravel\Scout\Searchable;
use Illuminate\Notifications\Notifiable;
と、
use Searchable;
use Notifiable;
を追加するのを忘れないでください。
また、public function searchableAs() { return 'books_index'; }によりインデックスが作成されます。
次のtoSearchableArrayメソッドで、「bookのデータにauthor_nameを付与してインデックスを作成する」という処理を行っています。以下の部分にあたります。
$array['author_name'] = $this->author->name;次にAuthorモデルには「authorのデータに著者が書いたbookを全て一緒にインデックスとして作成する」という処理を追加します。(前半のnamespaceとsearchableAsメソッドはBookモデルと同じ)
App\Author.php<?php namespace App; use Laravel\Scout\Searchable; use Illuminate\Notifications\Notifiable; use Illuminate\Database\Eloquent\Model; class Author extends Model { use Searchable; use Notifiable; public function searchableAs() { return 'authors_index'; } public function toSearchableArray() { $array = $this->toArray(); $books = $this->books; for($i = 0; $i < $books->count(); $i++) { $array["book_names"][$i] = $books[$i]['name']; } return $array; } //リレーション定義 public function books() { return $this->hasMany('App\Book'); } }以下の部分で関連テーブルからデータを引っ張ってきているのですが、これがおそらく2次元配列として返ってきてるのだと思います。(連想配列ではないみたいです。間違っていたらすみません)
$books = $this->books;そのため関連テーブルのauthorのnameを取るためにforループで取り出しました。他に何か良い方法があれば知りたいです。
for($i = 0; $i < $books->count(); $i++) { $array["book_names"][$i] = $books[$i]['name']; }ここまで完了したら、Algoliaの方にデータを送ります。以下のコマンドです。
$php artisan scout:import "App\Author" $php artisan scout:import "App\Book"Algoliaの方を見てみましょう。
book_indexの方にはauthor_nameという項目が追加され、その中にはauthorテーブルのnameの内容が追加されているはずです。
author_indexの方にはbook_namesという項目が追加され、その中にはbookテーブルのnameの内容が追加されているはずです。
データベースと同期をとる
データベースに更新があった場合、同期ができている場合はリレーションも含めて同期されます。今回の場合だと、bookテーブルが更新されると関連するauthorテーブルのbook_namesカラムがちゃんと更新されます。
同期するには以下のコマンドを叩きます。
$php artisan scout:syncもしそんなコマンドないよ〜と怒られた場合は、
$composer require algolia/scout-extended $php artisan scout:reimportを叩いてみてください。
最初にsyncコマンドを叩いた時は、
scout-インデックス名.phpというファイルがconfig以下にできます。
このあともう一度$php artisan scout:syncすることで同期が完了です。
以下のコマンドで同期できているか確認できます。$php artisan scout:statussynchronizedとなっていれば大丈夫。
参考資料など
圧倒的公式ドキュメント。
https://www.algolia.com/
- 投稿日:2019-07-24T15:58:34+09:00
LaravelでSQSからメッセージをデキューしたいだけの場合のプラクティス
LaravelにあるQueue機能
AWS SQSに入ったメッセージを、Laravelフレームワークで処理したいことがあった。
LaravelにはもともとQueueの機能があり、それを使うことで簡易にできると思っていたが、これはLaravelからエンキューしLaravelからデキューする前提で作られているようだった。(?)
実際にJOBを投入するときは、処理するロジックのクラスも含めてエンキューする。
エンキューする際は決まった形にオブジェクトを作成し、デキューする際もそれ前提で処理をするようだった。以下はエンキューする前に呼び出される関数。
ペイロードのオブジェクトをLaravelの仕様で作っている。vendor/laravel/framework/src/Illuminate/Queue/Queue.php/** * Create a payload for an object-based queue handler. * * @param mixed $job * @return array */ protected function createObjectPayload($job) { return [ 'displayName' => $this->getDisplayName($job), 'job' => 'Illuminate\Queue\CallQueuedHandler@call', 'maxTries' => $job->tries ?? null, 'timeout' => $job->timeout ?? null, 'timeoutAt' => $this->getJobExpiration($job), 'data' => [ 'commandName' => get_class($job), 'command' => serialize(clone $job), ], ]; }今回やりたいこと
SQSにはLaravelではない別のクライアントからメッセージを入れる。
この入れられたメッセージをLaravelで処理したい。もちろんLambdaなどで処理したほうがいいケースのほうが多そうだが、今回はプロジェクトの仕様でLaravelで行いたい。
config/queue.php
今後Laravelの既存Queue機能を使うかもしれないので、configの場所は同じにする。
もともと以下の記述があるので、実際には.envへの追記になる。config/queue.php'sqs' => [ 'driver' => 'sqs', 'key' => env('SQS_KEY', 'your-public-key'), 'secret' => env('SQS_SECRET', 'your-secret-key'), 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'), 'queue' => env('SQS_QUEUE', 'your-queue-name'), 'region' => env('SQS_REGION', 'us-east-1'), ],AWS SDK
composerでrequire
$ composer require aws/aws-sdk-phpメッセージのデキュー
AWSクライアントを直接使うのではなく、config処理をそのまま活かすために、Laravelのクラスを使ってみた。
(Laravelのクラスの中で、AWSのSDKを使っている)use Illuminate\Queue\Connectors\SqsConnector; /** 省略 **/ public function handle() { $config = config('queue.connections.sqs'); $client = (new SqsConnector())->connect($config); $sqs = $client->getSqs(); $queue_url = $client->getQueue(null); $result = $sqs->receiveMessage([...]); ... }
- 投稿日:2019-07-24T15:01:25+09:00
ユーザー登録画面を作成しながらDBを操作する画面作成の基礎を勉強してみる~ユーザー編集画面の作成~
この記事の関連記事となります。
ユーザー登録画面を作成しながらDBを操作する画面作成の基礎を勉強してみる
はじめに
ユーザー編集画面を作成して、Userテーブルのデータを1件画面に表示してみます。また、更新ボタンが押された場合、ユーザー情報を更新します。
手順
- コントローラーを編集します
- 編集画面を作成します
1. コントローラを編集します
コントローラーを編集します。
app/Http/Controllers/UserController.php<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\User; class UserController extends Controller { // public function edit(Request $request, $id) { // ID(主キー)を条件にユーザーを取得します $user = User::find($id); // $errors = array(); // ユーザー編集画面へユーザーを渡します return view('users.edit', ['user' => $user, 'errors' => $errors]); } // public function update(Request $request, $id) { // ID(主キー)を条件にユーザーを取得します $user = User::find($id); // 氏名、メールアドレスを入力された値に変更します $user->name = $request->name; $user->email = $request->email; if($request->password != null) { $user->password = bcrypt($request->password); } // ユーザーを保存します $user->save(); // ユーザー一覧画面へ遷移します return redirect('/users'); } }2. 編集画面を作成します
編集画面を作成します。
その他のhtmlコードについては割愛します。resources/views/users/edit.blade.php<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="container"> <form method="post" action="/users/{{ $user->id }}"> {{ csrf_field() }} {{ method_field('PUT') }} <div class="form-group"> <label class="control-label">ID</label> <input class="form-control-plaintext" type="text" value="{{ $user->id }}" readonly> </div> <div class="form-group"> <label>氏名</label> <input class="form-control" name="name" type="text" value="{{ $user->name }}" required> </div> <div class="form-group"> <label>メールアドレス</label> <input class="form-control" name="email" type="email" value="{{ $user->email }}" required> </div> <div class="form-group"> <label>パスワード</label> <input class="form-control" name="password" type="password" value=""> <small class="text-muted">省略した場合、パスワードは変更されません</small> </div> <div class="form-group"> <label>作成日時</label> <input class="form-control-plaintext" type="text" value="{{ $user->created_at }}" readonly> </div> <div class="form-group"> <label>更新日時</label> <input class="form-control-plaintext" type="text" value="{{ $user->updated_at }}" readonly> </div> <a class="btn btn-secondary" href="/users">一覧へ</a> <input class="btn btn-primary" type="submit" value="更新"> </form> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> </body> </html>参考
- 投稿日:2019-07-24T14:06:05+09:00
laravelのミューテタを出力する方法
調べにくい
コード
protected $appends = ['is_admin'];参考
https://readouble.com/laravel/5.8/ja/eloquent-mutators.html
https://readouble.com/laravel/5.8/ja/eloquent-serialization.html
- 投稿日:2019-07-24T14:01:56+09:00
laravel guzzle post 通信
laravel guzzle http リクエストしようぜ
今回は yahoo の 形態素解析を使ってみる
https://developer.yahoo.co.jp/webapi/jlp/ma/v1/parse.htmlまずは composer
composer require guzzlehttp/guzzlecontroller で以下のように
今回 twitter の client とかぶってエラーになるので、
use GuzzleHttp\Client2; として 2 をつけて読み込んでおく。// use GuzzleHttp\Client2; としておく。 // 他の Client と バッティングさせないために 以下のように書く $client_id = 'hogeyour'; $secret_id = 'hogesecretyour'; $client = new \GuzzleHttp\Client([ 'base_uri' => 'https://jlp.yahooapis.jp/MAService/V1/', ]); $method = 'POST';//GET or POST $uri = 'parse?appid='.$client_id.'&results=ma,uniq&uniq_filter=9%7C10&sentence=恋に恋焦がれ恋に泣く'; // スカイツリーの郵便番号 $options = []; $response = $client->request($method, $uri, $options); //xml で帰ってくるので。 $data = simplexml_load_string($response->getBody()->getContents()); foreach ($data->uniq_result->word_list->word as $v) { pd($v->surface); }結果
/var/www/html/uranaibako.com/app/Http/Controllers/HogeController.php (line 221) SimpleXMLElement Object ( [0] => 恋 ) /var/www/html/uranaibako.com/app/Http/Controllers/HogeController.php (line 221) SimpleXMLElement Object ( [0] => 恋焦がれ ) /var/www/html/uranaibako.com/app/Http/Controllers/HogeController.php (line 221) SimpleXMLElement Object ( [0] => 泣く )
- 投稿日:2019-07-24T13:38:50+09:00
Laravelでいいね機能
環境
PHP 7.3
Laravel 5.8Laravelにいいね機能を実装しようと思い、調べていたらLaravel-LoveというライブラリがLaravel Newsで紹介されていました。
準備
今回は
UserモデルでPostモデルにいいねします。インストール
$ composer require cybercog/laravel-love
Likeタイプを生成$ php artisan love:reaction-type-add Like 1Reactarebl(いいねするモデル)の準備
app/User.php<?php namespace App; use Cog\Contracts\Love\Reacterable\Models\Reacterable as ReacterableContract; use Cog\Laravel\Love\Reacterable\Models\Traits\Reacterable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable implements ReacterableContract { use Reacterable; }$ php artisan love:setup-reacterable --model="App\User" --nullableReactable(いいねされるモデル)準備
app\Post.php<?php namespace App; use Cog\Contracts\Love\Reactable\Models\Reactable as ReactableContract; use Cog\Laravel\Love\Reactable\Models\Traits\Reactable; use Illuminate\Database\Eloquent\Model; class Post extends Model implements ReactableContract { use Reactable; }$ php artisan love:setup-reactable --model="App\Post" --nullable実際にいいねする
<?php use App\User; use App\Post; use Cog\Laravel\Love\ReactionType\Models\ReactionType; $user1 = User::find(1); $post1 = Post::find(1); $likeType = ReactionType::fromName('Like'); //リアクター、リアクタントとして登録。 //すでに登録してある場合、例外が投げられます。 if ($user1->isNotRegisteredAsLoveReacter()) { $user1->registerAsLoveReacter(); } if ($post1->isNotRegisteredAsLoveReactant()) { $post1->registerAsLoveReactant(); } $reacter = $user1->getLoveReacter(); $reactant = $post1->getLoveReactant(); //$user1が$post1をいいねしていないことを確認 if ($reacter->isNotReactedToWithType($reactant, $likeType)) { //$user1で$post1をいいね $reacter->reactTo($reactant, $likeType); } //$user1がいいねしたPostが入ったCollectionを取得 $posts = Post::query() ->whereReactedByWithType($reacter, $likeType) ->get(); //$post1をいいねしたUserが入ったCollectionを取得 $likeReactions = $post1 ->getLoveReactant() ->reactions() ->where('reaction_type_id', ReactionType::fromName('Like')->getId()) ->get(); $likeUsers = []; foreach ($likeReactions as $likeReaction) { $likeUsers[] = User::where('love_reacter_id', $likeReaction->getReacter()->id)->first(); } //$post1をいいねした数を取得 count($likeUsers); //いいね解除 if ($reacter->isReactedToWithType($reactant, $likeType)) { $reacter->unreactTo($reactant, $likeType); }参考


