Laravelの管理画面について(Laravel-adminは止めたほうがいい)

「Laravel 管理画面」で検索すると上位に表示されるサイトに、

「Laravel-admin」がオススメ!とか書いてある。

 

それを信じて、「Laravel-admin」を入れてみたが、正直止めたほうがいい。

 

「Laravel-admin」は、どうも中国人が作ったようで、

コミュニティーが中国語がメインになっている。

 

ドキュメントがあるのだが、詳しいことが書いておらず、

コミュニティーを見ようと思ったが、中国語メインなので全く使えない。

 

DBを表示させるだけの管理画面であれば使えるかもしれないが、

ちょっと変わったことをしようとすると、途端にやり方がわからなくなる。

 

個人的な意見だが、2日間を無駄に費やした身として、Laravel-adminはオススメしない。

 

以上

 

PDFからPNGへの変換について

ImageMagickで変換する場合、元のPDFがCMYKで作成されていると、

どうやってもうまく行かなかった。(微妙に色が変わってしまう)

試したコマンドは以下のような感じ。

 

====いずれもうまく行かないので注意====

$exec="timeout 120 /usr/local/bin/convert -density 400 +profile -colorspace cmyk ".$originalPDF."[".$i."] -profile '".config('myconst.ROOTDIR')."resources/sRGB2014.icc' -colorspace sRGB ".$convertedPNG." 2>&1";

$exec="timeout 120 /usr/local/bin/convert -density 400 +profile -profile '".config('myconst.ROOTDIR')."resources/JapanColor2001Coated.icc' -colorspace cmyk -intent Relative -black-point-compensation -profile '".config('myconst.ROOTDIR')."resources/sRGB2014.icc' -colorspace sRGB ".$originalPDF."[".$i."] ".$convertedPNG." 2>&1";

 $exec="timeout 120 /usr/local/bin/convert -density 400 +profile -profile '".config('myconst.ROOTDIR')."resources/JapanColor2001Coated.icc' -colorspace cmyk -intent Relative -black-point-compensation ".$originalPDF."[0] ".$convertedPNG." 2>&1";

 $exec="timeout 120 /usr/local/bin/convert -density 400 -quality 1 +profile '*' -profile '".config('myconst.ROOTDIR')."resources/JapanColor2001Coated.icc' ".$originalPDF."[0] ".$convertedPNG." 2>&1";

$exec="timeout 120 /usr/local/bin/convert -density 400 ".$originalPDF."[0] +profile '*' -profile '".config('myconst.ROOTDIR')."resources/JapanColor2001Coated.icc' -profile '".config('myconst.ROOTDIR')."resources/sRGB_v4_ICC_preference.icc' ".$convertedJPG." 2>&1";

$exec="timeout 120 /usr/local/bin/convert -density 400 ".$originalPDF."[0] -profile '".config('myconst.ROOTDIR')."resources/sRGB_v4_ICC_preference.icc' ".$convertedJPG." 2>&1";

$exec="timeout 120 /usr/local/bin/convert -density 400 ".$originalPDF."[0] +profile '*' -profile '".config('myconst.ROOTDIR')."resources/JapanColor2001Coated.icc' PNG00:".$convertedPNG." 2>&1";

 

私の結論としては、元画像がCMYKの場合、ImageMagickではうまく行かない。

ImageMagickのバージョンは、Version: ImageMagick 7.0.7-25)

 

よって、XPDF(pdftocairo)を使う。

pdftocairo -png book.pdf test.png

 

まだ詳しくは見ていないが、CMYKでもいい感じで変換されている。

 

ImageMagick をLCMSに対応させる

ImageMagickを使ってPDFをPNGに変換していると以下のエラーが出ていた。

'convert: delegate library support not built-in \'
/var/www/xxx/book.pdf\' (LCMS) @ warning/profile.c/ProfileImage/836.'

 

ググるとどうやらLCMSというものを入れればいいらしい。

よって、入れてみる。

LCMSは以下にあった。

http://www.imagemagick.org/download/delegates/

 

sudo wget -P /usr/local/src http://www.imagemagick.org/download/delegates/lcms2-2.8.tar.gz

cd /usr/local/src

sudo tar -zxvf lcms2-2.8.tar.gz

cd lcms2-2.8

sudo ./configure --prefix=/usr/local

sudo make
sudo make install

 

※上記だけでいけるのかと思ったが、上記だけではImageMagickで使えるようにならなかった。

色々調べたが、『lcms2-devel』が必要だった。

これをyumで入れておく

sudo yum install lcms2-devel

 

ImageMagickを再コンパイルする

cd /usr/local/src/ImageMagick-7.0.7-25
sudo ./configure

sudo make clean
sudo make
sudo make install

 

■確認は以下のコマンド

convert -list configure | grep -i "delegates"

 DELEGATES mpeg jng jpeg lcms lzma png ps xml zlib

 

以上

 

Laravelでキャッシュを削除するコマンド

Laravelがインストールされたディレクトリに移動して以下のコマンドを打つ。

php artisan view:clear

 

以上

Laravel でasset()やurl()が返すURLを『https』 にするためのメモ

https://readouble.com/laravel/5.5/ja/requests.html#configuring-trusted-proxies

App\Http\Middleware\TrustProxies を開き、

protected $proxies = '**';

にする。

これだけでOK!

Laravel5.6 へ Stripe.com の checkout を導入する

<前準備>

1.composer.jsonに以下を追記

"require": {
"php": ">=7.0.0",
"fideloper/proxy": "~3.3",
"laravel/framework": "5.5.*",
"laravel/tinker": "~1.0",
"laravelcollective/html": "^5.5",
"league/flysystem-aws-s3-v3": "~1.0",
"stripe/stripe-php": "6.*" ←☆ここを追記
},

 

2.SSHでlaravelのインストールディレクトリに移動し、以下を実行

$ composer update

 

3.vendorディレクトリの下に、「stripe」が出来ていればインストール成功

 

<プログラム>

https://stripe.com/docs/quickstart

 このページを見ると、Stripeには、大きく、

●Checkout

●Stripe.js and Elements

の2つの方法があることがわかる。

カスタマイズが必要な場合は、Stripe.jsを使うようだが、とりあえず、Checkoutで進める。

 

<決済画面の作成>

stripe.comのCheckoutのページをみると、以下のコードを貼ると、ポップアップで決済画面が表示されるとのことであった。

https://stripe.com/docs/checkout#integration-simple

<form action="your-server-side-code" method="POST">
  <script
    src="https://checkout.stripe.com/checkout.js" class="stripe-button"
    data-key="pk_test_******************"
    data-amount="999"
    data-name="Demo Site"
    data-description="Widget"
    data-image="https://stripe.com/img/documentation/checkout/marketplace.png"
    data-locale="auto"
    data-currency="jpy">
  </script>

 

しかし、何度やっても表示されない。

どうやら、Laraveのテンプレ(app.blade.php)に標準で入っている『app.js』

<script src="{{ asset('js/app.js') }}"></script>

があると、Stripeのコードが動かないことがわかった。

 

よって、【シンプル】コードは諦め、同じページにある【Custom】タブにあるコードを貼ると、うまくポップアップするようになった。

https://stripe.com/docs/checkout#integration-custom

<script src="https://checkout.stripe.com/checkout.js"></script>

<button id="customButton">Purchase</button>

<script>
var handler = StripeCheckout.configure({
  key: 'pk_test_***********************',
  image: 'https://stripe.com/img/documentation/checkout/marketplace.png',
  locale: 'auto',
  token: function(token) {
    // You can access the token ID with `token.id`.
    // Get the token ID to your server-side code for use.
  }
});

document.getElementById('customButton').addEventListener('click', function(e) {
  // Open Checkout with further options:
  handler.open({
    name: 'Demo Site',
    description: '2 widgets',
    currency: 'jpy',
    amount: 2000
  });
  e.preventDefault();
});

// Close Checkout on page navigation:
window.addEventListener('popstate', function() {
  handler.close();
});
</script>

 

上記サンプルプログラムでは、カード情報のトークン化完了後、決済処理に移る方法が書かれていない。そこで、トークンが返ってきた後、フォームをコントローラーに送信するために、以下のような感じにした。

【Viewのソース】(Formで遷移バージョン)

 
<form id="stripecharge" method="post"
action="{{ asset('orderexec') }}" class="form-horizontal">
{{ csrf_field() }}
 
<button id="customButton" class="stripe_button">注文画面</button>
<input type="hidden" id="stripeToken" name="stripeToken" />
<input type="hidden" id="stripeEmail" name="stripeEmail" />
<input type="hidden" id="stripeArgs" name="stripeArgs" />
</form>
 
<script>
var handler = StripeCheckout.configure({
key: '{{ env('STRIPE_PUB_KEY') }}',
currency: 'jpy',
locale: 'auto',
zipCode: true,
name: '{{ config('app.name', 'Laravel') }}',
description: '2 widgets',
billingAddress: true,
shippingAddress: true,
email: "{{ $email }}",
token: function(token, args) {
   $("#stripeToken").val(token.id);
   $("#stripeEmail").val(token.email);
   $("#stripeArgs").val(JSON.stringify(args));
   $("#stripecharge").submit();
}
});

$("#customButton").on('click', function(e) {
var final_price = $("#changed_total_cost").text();
final_price = final_price.replace(/\$/g, '').replace(/\,/g, '');
final_price = parseFloat(final_price);

// Open Checkout with further options:
handler.open({
   amount: final_price,
});
e.preventDefault();
});

// Close Checkout on page navigation:
window.addEventListener('popstate', function() {
handler.close();
});
</script>
 

 

決済金額は、オプションやら送料やらで変動するため、$("#customButton").on('click')の中で決済金額を決定した後、

handler.open({ })

の中で、amountを決定している。

https://stripe.com/docs/recipes/variable-amount-checkout

 

上記Formで遷移バージョンの場合、やってみるとわかるが、stripeからトークン処理が返ってきた後、$("#stripecharge").submit() でフォームをPOSTするのだが、その間の処理が微妙に長く(数秒)、ユーザーは「あれ?」と思ってしまう。

よって、ajaxで処理し、途中はローディング画像を流し、決済完了後はモーダル画面を表示させるようにした。

【(改良版)Viewのソース】(ajaxバージョン)

 
<button id="customButton" class="stripe_button">ご注文画面</button>
{{!! 決済完了後に表示させるモーダルウィンドウの準備!!}}
<div class="remodal" data-remodal-id="modal_ordercomp"
data-remodal-options="hashTracking:false, closeOnOutsideClick: true">
    <h1>ご注文完了!</h1>
    <p>ご注文が完了しました。</p>
<button data-remodal-action="close" class="remodal-close"></button>
</div>

<script>
var handler = StripeCheckout.configure({
key: '{{ env('STRIPE_PUB_KEY') }}',
currency: 'jpy',
locale: 'auto',
zipCode: true,
name: '{{ config('app.name', 'Laravel') }}',
description: '2 widgets',
billingAddress: true,
shippingAddress: true,
email: "{{ $email }}",
token: function(token, args) {
   $("#kurukuru").css('display','block');←☆ローディングの表示
   $.ajaxSetup({
      headers: {
         'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
      }
  });
   $.ajax({
      type: "POST",
      dataType: "text",
      data: {'stripeToken': token.id,
      'stripeEmail':token.email,
      'stripeArgs': JSON.stringify(args),
      },
       url: "{{ asset('mypage/mybooks/orderexec') }}",
   }).done(function(data){
      //決済完了後、モーダルウィンドウを表示させる
      //以下は、remodal.jsとの連携例。適当に変えてください。
      $('[data-remodal-id=modal_ordercomp]').remodal().open();
  }).fail(function(res){
      alert('通信エラーが発生しました。');
   });
}
});

$("#customButton").on('click', function(e) {
var final_price = $("#changed_total_cost").text();
final_price = final_price.replace(/\$/g, '').replace(/\,/g, '');
final_price = parseFloat(final_price);

// Open Checkout with further options:
handler.open({
   amount: final_price,
});
e.preventDefault();
});
 

 

 <コントローラー側のプログラム>

 コントローラーは人によってする処理が違うので最低限のプログラムだけ下に書いておく。

public function orderexec(Request $request)
{
try {
   Stripe::setApiKey(env('STRIPE_SECRET_KEY'));
   $token = $request->input('stripeToken');
   $stripeArgs = $request->input('stripeArgs');
   logger($stripeArgs);

   $customer = Customer::create([
      'email' => $request->stripeEmail,
      'source' => $token,
      'metadata' => ['user_id' => Auth::id()],
   ]);
   
   $charge = Charge::create([
      'customer' => $customer->id,//必須
      'amount' => 999,
      'currency' => 'jpy',
      'description' => 'Example charge',
      'metadata' => ['order_id' => 6735],
   ]);
}
catch (\Exception $ex) {
   return $ex->getMessage();
}
return;
}
 

 ポイントは以下の2点。

$customer = Customer::create([
      'email' => $request->stripeEmail,
      'source' => $token, ←★ここでStripeから帰ってきたトークンを指定
      'metadata' => ['user_id' => Auth::id()],
   ]);

$charge = Charge::create([
      'customer' => $customer->id,←★customerでトークンを使ったので、このように指定する。再度トークンを指定するとエラーになった。
      'amount' => 999,
      'currency' => 'jpy',
      'description' => 'Example charge',
      'metadata' => ['order_id' => 6735],
   ]);

 

以上、ご参考まで。

(おかしな点があればコメントいただければ助かります。)

Laravel 5.6 ログイン認証回数制限で、ユーザー名以外をキーにする方法

Laravelのログイン認証の回数制限は、デフォルトでは、『制限はユーザの名前/メールアドレスとIPアドレスで限定されます。』と書かれている。

認証 5.3 Laravel

独自認証でユーザー名以外をキーにした場合の認証回数制限の方法をメモしておく。

 

1.ログインに使用するコントローラーに、以下の赤字を追記する。

(認証回数制限なしのコントローラーの作成方法は以下の記事)

fushigi.hatenadiary.com

 

<?php


//namespace App\Http\Controllers\Auth; //コメントアウト
namespace App\Http\Controllers\ViewAuth; // 追加

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

use Illuminate\Http\Request;// 追加
use Illuminate\Support\Facades\Auth;// 追加
use Illuminate\Support\Str;//認証回数制限用に追加
 
use App\Viewer;//追加
use Validator;//追加

class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/

use AuthenticatesUsers;

/**
* Where to redirect users after login.
*
* @var string
*/
//protected $redirectTo = '/viewer';//変更

/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
//$this->middleware('guest')->except('logout');
$this->middleware('guest:viewuser')->except('logout');//変更
}
 
//以下追加
protected function guard()
{
return Auth::guard('viewuser'); //config/auth.phpで追加したguardを指定
}

//初期アクセス時。または認証後のアクセス時
public function index($page_id)
//$page_idは、web.phpの中で、Route::get('viewer/{page_id}'
//として指定している変数
{
$ninsyou = 0;//認証フラグ
//そのページにパスワードがついているかどうかを調べる
$password = Viewer::where('page_id', $page_id)->first();

if ($password->password != NULL) {//パスワードありの場合
if (Auth::guard('viewuser')->check()) { //認証済みの場合の処理。
$user = Auth::guard('viewuser')->user();
//guard('viewuser')のため、viewerテーブルのレコードが返される。
if ($user->page_id == $page_id) {
$ninsyou = 1; //認証OK
} else {
//違うページで認証は通っていたが、このページでは認証が通っていない場合
$ninsyou = 0;
}
} else { //未認証の場合の処理
$ninsyou = 0;
}
} else {//パスワードがない場合、そのままビュー画面へいく
$ninsyou = 1; //認証OK
}

if ($ninsyou==1) {
$this->view($page_id);
} else {
//ログインページへリダイレクト
return redirect()->route('viewlogin', ['page_id' => $page_id]);
}
}

//認証ページの表示
//$requestは、認証失敗時にGETでついてくるpass_eroorを取るために必要。
//$page_idは、web.phpで指定している、Route::get('viewer/login/{page_id}'の部分。
public function showLoginForm(Request $request, $page_id)
{
//function authenticate()で認証に失敗すると、
//redirect()でpass_error=1が付いてくる。
$pass_error = $request->input('pass_error');
 
return view('viewer.viewerlogin',
['page_id'=>$page_id, 'pass_error'=>$pass_error]);
}

//自前の認証
public function authenticate(Request $request)
{
//validatorを指定しないとエラーになる
$validator = Validator::make($request->all(), [
'page_id' => 'required|unique:posts',
'password' => 'required',
]);

 
//認証回数制限ここから
if ($this->hasTooManyLoginAttempts($request)) {
logger('認証回数制限!');
return $this->sendLockoutResponse($request);
}
//認証回数制限ここまで
 
Auth::guard('viewuser');

$page_id = $request->input('page_id');
$password = $request->input('password');

if (Auth::guard('viewuser')
->attempt(['page_id' => $page_id, 'password' => $password])) {
logger('認証成功!');
//閲覧ページを表示
return redirect()->route('viewurl',['page_id' => $page_id]);
} else {
logger('認証失敗');
$this->incrementLoginAttempts($request);//認証回数制限用に追加
//ログインページに戻る
return redirect()->route('viewlogin', ['page_id' => $page_id, 'pass_error'=>1]);
}
}

//認証回数制限ここから
protected function throttleKey(Request $request)
{
//デフォルトではユーザー名で認証回数制限をチェックしていた。
//これをpage_idに変える
//return Str::lower($request->input($this->username())).'|'.$request->ip();
return Str::lower($request->input('page_id')).'|'.$request->ip();
}
//認証回数制限ここまで
public function view($page_id)
{
認証後の閲覧ページの処理;
}

}

Laravel 5.6 で、userテーブル以外で認証を行う

Laravelを使って、特定ページに認証をつけることにした。

パスワードを知っている人だけが、そのページに入ることができるように。

 

そのページは、DBのviewerというテーブルにパスワードを設定しており、

そのviewerテーブルを使って認証を行うようにした。

各ページ毎にパスワードが異なっており、あるページで認証が通っても、別のページでは認証が通らないようにする。

またパスワードがついていないページは、認証なしで見ることができる。

 

(参考)

Laravelで複数テーブルを使ったログイン認証を実装する - Qiita

 

1.config/auth.php 

'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],

'api' => [
'driver' => 'token',
'provider' => 'users',
],
//以下を追加
'viewuser' => [
'driver' => 'session',
'provider' => 'viewusers',
],
],
 
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
//以下を追加
'viewusers' => [
'driver' => 'eloquent',
'model' => App\Viewer::class,
],
],

※パスワードの再送は設定しないため、'passwords'は追加していない

 

2.web.php

URL遷移のイメージ

//初期アクセス http://hogehoge/viewer/XXXXXXXXXX
Route::get('viewer/{page_id}',
'ViewAuth\LoginController@index')->name('viewurl');
 
//パスワードが付いている場合、ログイン画面へ
Route::get('viewer/login/{page_id}',
'ViewAuth\LoginController@showLoginForm')->name('viewlogin');
 
//ログイン認証
Route::post('viewer/login',
'ViewAuth\LoginController@authenticate')->name('viewpostlogin');

 

※Laravelのページで分かりにくかったが、通常の認証では、ログイン認証は、コントローラ@login を使う。

しかし、独自認証を行う場合、コントローラ@authenticateとして、コントローラ内にatuthenticate()を書く。

認証 5.3 Laravel

 

3.app/Viewer.php

通常のモデルは、

class Viewer extends Model

となっているが、このままでは認証に使うことができない。

よって、認証に使うモデル(ここでは、Viewer)は、以下のようにする。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;//認証用に追加

//class Viewer extends Model
class Viewer extends Authenticatable//User.phpに合わせて変更
{
protected $table = 'Viewer';
protected $fillable = [
'page_id',
'password',
・・・
・・・
];
protected $hidden = [
'password',
];
}

 

4.app/Http/Middleware/RedirectIfAuthenticated.php

認証が完了した場合、通所は所定のページにリダイレクトされるようになっている。

しかし、私の場合、リダイレクト処理はコントローラ内で書くようにしたかったため、以下のようにして、認証後のリダイレクトを止めるようにした。

public function handle($request, Closure $next, $guard = null)
{
//変更。オリジナルは以下。
//if (Auth::guard($guard)->check()) {
// return redirect('/home');
//}
if (Auth::guard($guard)->check()) {
if ($guard=='viewuser') { //ここを追加
//viewuserの認証時は、認証を通った後もリダイレクトしない
} else {
return redirect('/home');
}
}
  return $next($request);
}

 

5.app/Http/Controllers/ViewAuth/LoginController.php

参考にしてください。

<?php

//namespace App\Http\Controllers\Auth; //コメントアウト
namespace App\Http\Controllers\ViewAuth; // 追加

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

use Illuminate\Http\Request;// 追加
use Illuminate\Support\Facades\Auth;// 追加
use App\Viewer;//追加
use Validator;//追加

class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/

use AuthenticatesUsers;

/**
* Where to redirect users after login.
*
* @var string
*/
//protected $redirectTo = '/viewer';//変更

/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
//$this->middleware('guest')->except('logout');
$this->middleware('guest:viewuser')->except('logout');//変更
}
 
//以下追加
protected function guard()
{
return Auth::guard('viewuser'); //config/auth.phpで追加したguardを指定
}

//初期アクセス時。または認証後のアクセス時
public function index($page_id)
//$page_idは、web.phpの中で、Route::get('viewer/{page_id}'
//として指定している変数
{
$ninsyou = 0;//認証フラグ
//そのページにパスワードがついているかどうかを調べる
$password = Viewer::where('page_id', $page_id)->first();

if ($password->password != NULL) {//パスワードありの場合
if (Auth::guard('viewuser')->check()) { //認証済みの場合の処理。
$user = Auth::guard('viewuser')->user();
//guard('viewuser')のため、viewerテーブルのレコードが返される。
if ($user->page_id == $page_id) {
$ninsyou = 1; //認証OK
} else {
//違うページで認証は通っていたが、このページでは認証が通っていない場合
$ninsyou = 0;
}
} else { //未認証の場合の処理
$ninsyou = 0;
}
} else {//パスワードがない場合、そのままビュー画面へいく
$ninsyou = 1; //認証OK
}

if ($ninsyou==1) {
$this->view($page_id);
} else {
//ログインページへリダイレクト
return redirect()->route('viewlogin', ['page_id' => $page_id]);
}
}

//認証ページの表示
//$requestは、認証失敗時にGETでついてくるpass_eroorを取るために必要。
//$page_idは、web.phpで指定している、Route::get('viewer/login/{page_id}'の部分。
public function showLoginForm(Request $request, $page_id)
{
//function authenticate()で認証に失敗すると、
//redirect()でpass_error=1が付いてくる。
$pass_error = $request->input('pass_error');
 
return view('viewer.viewerlogin',
['page_id'=>$page_id, 'pass_error'=>$pass_error]);
}

//自前の認証
public function authenticate(Request $request)
{
//validatorを指定しないとエラーになる
$validator = Validator::make($request->all(), [
'page_id' => 'required|unique:posts',
'password' => 'required',
]);

Auth::guard('viewuser');

$page_id = $request->input('page_id');
$password = $request->input('password');

if (Auth::guard('viewuser')
->attempt(['page_id' => $page_id, 'password' => $password])) {
logger('認証成功!');
//閲覧ページを表示
return redirect()->route('viewurl',['page_id' => $page_id]);
} else {
logger('認証失敗');
//ログインページに戻る
return redirect()->route('viewlogin', ['page_id' => $page_id, 'pass_error'=>1]);
}
}

public function view($page_id)
{
認証後の閲覧ページの処理;
}

}

 

以上、ご参考まで。

 

 

 

 

 

 

EC2にsvgexportを入れるメモ

1.EC2でnpmを使えるようにnodejsを入れる

qiita.com

(追記)

※上の方法だと、PHPのexecからsvgexportが使えなかった。

ログに以下のエラーが表示された。

/usr/bin/env: node: No such file or directory

 理由はよくわからないが、恐らくnodejsがインストールされる位置が、

/home/ec2-user/.nvm/versions/node/v8.10.0/bin/svgexport

のようになるからだと思う。

 

よって、nvmを使ってインストールせず、直接ソースからインストールし直した。

$ sudo yum groupinstall 'Development tools'
$ curl -O https://nodejs.org/download/release/latest-v9.x/node-v9.8.0.tar.gz
$ tar xvf node-v9.8.0.tar.gz
$ cd node-v9.8.0
$ ./configure --prefix=/usr/local 
$ make            ←★ここでむっちゃ時間かかる
$ sudo make install

$ which node
/usr/local/bin/node

 

※アンインストールは、

$ cd node-v9.8.0

$ make uninstall

 

この状態でsvgexportをインストールすると

npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node_modules'

というエラーになった。

npmでpermission deniedになった時の対処法[mac] - Qiita

上記サイトをみて、

npm config get prefixを実行して、/usr/localが表示されることを確認し、

sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}

SSHでうってやると、インストールできた。

 

ここで、SSHからsvgexportを実行すると正常にSVGPNGに変換されるのだが、

PHPからexecでsvgexportを実行すると、以下のエラーが出た。

/usr/bin/env: node: No such file or directory

 

どうやら、nodeの実行場所が、

$which node
/usr/local/bin/node

になっているのが原因らしい。

よって、以下のサイトをみて、/usr/bin/node にシンボリックリンクを貼ってやると

うまくいった。

Ubuntuに最新のNode.jsを難なくインストールする - Qiita

sudo ln -sf /usr/local/bin/node /usr/bin/node

 

あ~、しんど。

 

 

2.svgexportのインストール

github.com

 

以上

 

---以下不使用

1.EC2でepelの有効化
sudo yum-config-manager --enable epel

確認は、
yum repolist all

2.nodejsのインストール
$ sudo yum install epel-release
$ sudo yum install nodejs

確認は、
$ node -v

3.npmのインストール
sudo yum install npm

4.nのインストール
sudo npm install -g n
sudo n latest

5.npmのアップデート
npm update -g npm


4.svgexportのインストール
npm install svgexport -g

libjpegのインストール方法

sudo wget -P /usr/local/src http://www.ijg.org/files/jpegsrc.v9b.tar.gz

cd /usr/local/src

sudo tar -zxvf jpegsrc.v9b.tar.gz

cd jpeg-9b

./configure

sudo make libdir=/usr/lib64

sudo make libdir=/usr/lib64 install

 

ImageMagickを使う時は、以下も行う

cd /usr/local/src/ImageMagick-7.0.7-25
sudo ./configure
sudo make
sudo make install

Laravel データベースからデータを取得する際、get()とfirst()の使い分け

■first()の場合

戻り値:モデル か null

nullかどうかの判定

$user = User::where('mobile', Input::get('mobile'))->first(); // model or null
if (!$user) {
   // Do stuff if it doesn't exist.
}

 

■get()の場合

戻り値:Collectionクラス

nullかどうかの判定

$user = User::where('mobile', Input::get('mobile'))->get();
if (!$user->isEmpty()){
    $firstUser = $user->first()
}

 

Laravelに自作関数を追加する

下のサイトを見ればよくわかる。

s8a.jp

 

1.appの直下に、自作関数を記載するファイルを追加する。

(例)app/myhelpers.php

 

if (! function_exists('xxx')) {
    /**
     * XXXする関数
     *
     * @param string $value
     * @return string
     */
    function xxx($value)
    {
        // 処理
        return $value;
    }
}

 

2.composer.jsonautoload.filesへ以下のようにパスを追加する。

(この作業は一度切り。)

"autoload": {
    "classmap": [
        ...
    ],
    "psr-4": {
        "App\\": "app/"
    },
    "files": [
        "app/myhelpers.php" // 追加
    ]
},

3.以下のComposerコマンドを実行します。(この作業は一度切り。)

composer dump-autoload

 

以上で終了。

 

一度設定すると、以後は、1のapp/myhelpers.phpの中に、自作の関数を追加していけばよい。