こなさんち

しがないフリーランスエンジニアの備忘録。

【Laravel5.4】laravel de ajax【ajax苦労した。】

はじめに

「そんなこと知っとるわ」って言わないでね。

routes

まず、通常のアクセス(通常のGETやPOST、CRUDによるPUT、DELETE)はweb.phpに書くとして、
apiajaxに関してはapi.phpに記載したいと思った。

で、api.phpに飛ばすためには、 /api/hogehoge とprefixを「api」にすりゃいいのよね。

ルーティング 5.5 Laravel

routes/api.php

<?php

Route::group(['middleware' => ['web.ajax']], function () {
    // 設定ファイル /app/Http/Middleware/AjaxOnlyMiddleware.php
    
    Route::post('/getsubmenu/{id}', 'MenuMasterComtroller@getSubMenu');
});

AjaxOnlyMiddleware.php

routes/api.php にて、「ajaxのみ通信許可すっぜ!」という処理を追加しましょう。 こういった通信制限はroutesでやっちゃいたいですね。

api.phpの中にmiddlewareを作っちゃいましょう。

$ php artisan make:middleware AjaxOnlyMiddleware

これで、

app/Http/Middleware/AjaxOnlyMiddleware.php

ができちゃうね。

中身はこうしよう。 簡単だね、$request->ajax() で判定できちゃうね。

<?php

namespace App\Http\Middleware;

use Closure;

class AjaxOnlyMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if($request->ajax() === true)
        {
            return $next($request);
        }
        else 
        {
            abort(404,'is not ajax!!!!');
        }
    }
}

Kernel.php

app/Http/Kernel.php だす。

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    /**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array
     */
    protected $middleware = [
        \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
        \App\Http\Middleware\TrustProxies::class,
    ];

    /**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
        
        'web.auth' => [
            \App\Http\Middleware\Auth::class,
        ],
        
        // ↓ここ!!!!!
        'web.ajax' => [
            \App\Http\Middleware\AjaxOnlyMiddleware::class,
        ],

        'api' => [
            'throttle:60,1',
            'bindings',
        ],
    ];

    /**
     * The application's route middleware.
     *
     * These middleware may be assigned to groups or used individually.
     *
     * @var array
     */
    protected $routeMiddleware = [
        'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    ];
}

実際のjs

ここでは、selectboxで選択したdata-要素を渡す設定。

<script>
    
$(document).ready(function() 
{

    $('select').change(function() 
    {
            
        //選択したvalue値を変数に格納
        var val = $(this).val();
        val = $('select option:selected').data('menuid');
        
        $.ajax({
            type: 'POST',
            url: '/api/getsubmenu/' + val,
            headers: {
                'Content-Type': 'application/json',
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content'),
            },
            dataType: 'json',
            success: function(data)
            {
                console.log(data);
            },
            error: function(XMLHttpRequest,textStatus,errorThrown) // 接続が失敗
            {
                console.log(textStatus);
                alert('It is error!!'); // エラーメッセージ
            }
        });
        return false;
        
    });
});

</script>

【代入、返り値編】python での特殊な書き方。@phper の驚き!

ほおーーー!!!!! って驚くこと書いてみた。

複数の値へ同時に代入。

初期化用かな。

 
>>> hoge ,fuga = (10, 100)
>>> hoge
10
>>> fuga
100

複数の返り値!!!

def multiReturn():
  return 10, 100, 1000

>>> a, b, c = multiReturn()
>>> a
10
>>> b
100
>>> c
1000

【比較演算子編】python での特殊な書き方。@phper の驚き!

ちょっと今日は2記事書いてみる。 元気があったら、fc2の通常日記も書くね。 ※ 精神薬等飲んだのでふわふわしてます。

PHPだと

if (hoge > 1 and hoge < 20 ) {
  echo '1より大きくて20より小さいよ';
}

Pythonだと

if 1 < hoge < 20:
  print u'PHPとおなじだよ!!!!!'

演算子はつなげることができ、解釈としては間に「and」が入るのですね。

a is b is c is None

# 解釈

a is b and b is c and c is None

TestCaseの使い方。 @django

最近Laravelではなく、pythondjangoに浮気しています。

import datetime

from django.utils import timezone
from django.test import TestCase

from .models import Question

class QuestionModelTests(TestCase):
  def hoge(self):
    self.assertIs(fuga, false)

これはね、assertIsでね、 fuga is false を判定するやつやねー。中々面白いよpython!

引用: 26.4. unittest — ユニットテストフレームワーク — Python 3.6.4 ドキュメント

faviconがsessionにいるせいで半日潰れた

■現象

hoge.com/[controller]/[action]/[parameter]

でGETパラメーターでアクセス。 入力フォームで登録情報を入力してもらうページ。

何も入力せずEnter。

リダイレクト先が

hoge.com/[controller]/[action]/favicon.ico

になってた。

■追求

validationを掛けているので、FormRequestを継承したrequestのphpファイルを

php artisan make:request CompanyRequest

みたいに作るのよ。

ははーん、validateが失敗したときのリダイレクト先が変なんだな??

これを機会にちょっとソースをほじくるぞ。

まず、 vender/laravel/framework/src/illuminate/Foundation/Http/FormRequest.php が元だね。こんなに階層潜るのか。

protected function failedValidation(Validator $validator)
    {
        throw (new ValidationException($validator))
                    ->errorBag($this->errorBag)
                    ->redirectTo($this->getRedirectUrl());
    }

はいはい、 getRedirectUrl() ね。。

protected function getRedirectUrl()
    {
        $url = $this->redirector->getUrlGenerator();
        
        if ($this->redirect) {
            return $url->to($this->redirect);
        } elseif ($this->redirectRoute) {
            return $url->route($this->redirectRoute);
        } elseif ($this->redirectAction) {
            return $url->action($this->redirectAction);
        }
        
        return $url->previous();
    }

...redirector ?????

vender/laravel/framework/src/illuminate/Routing/UrlGenerator.php

にいるね、うんうん。このクラスだね。

getPreviousUrlFromSession

ここらへんから怪しいよね、session???って。 都度都度dd()で吐き出してるけど、結局パラメータがfavicon.icoになってる。

■解決?

なんでfaviconがSessionにいるんだよおあああああああああああああああああああああああああああああ

まさか、まさか、と思い、htmlのheadタグ内からfavicon.icoを消したら 正しいURLになってた…

はあ?!って叫びました。

もう嫌!ってなりかけてたけど、ここで諦めたら駄目だと無駄なプライドが意地張ってました。

■解決!

…。

<link rel="shortcut icon" href="favicon.ico">

…。…これが悪い…?…パス…?でもブラウザには表示されてるし…、firefoxだと平気だし、問題はchoromeちゃんだけだし…

<link rel="shortcut icon" href="/favicon.ico">

…ああああああああああああ!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!できた!!!!!!!!!!

■根本解決? には至らず。

調べたところ、Chromeだけの現象のようです。

faviconのパスをちゃんと「頭から」指定してあげないと、sessionに上書きされて、laravelやcakePHPのsessionにある _previous というリダイレクト先が上書きされてしまう様子。 また、favicon.icoのみならず、ドキュメントルート以下の画像、css、jsファイルも同様の現象が起きている模様です。

はあ…疲れた。寝ます。

いい機会でした。

見てくれた皆さんは、くれぐれもパスには注意しましょう。

P.S. 仲間がいました。

Laravel バリデーションが変な場所へリダイレクトしてしまう – console dot log

www.kaasan.info

ほーらやっぱり!!!!!!!!!

OGP

OGPってなんぞ?

まさに↓のようにリンクを貼ると任意の画像やコメントが表示される技術のことですねえ。

Open Graph Protcol

だそうです。

もし今後SNSを利用し広める場合は設定したほうが良さそうです。

設定内容も特に難しくはなく、headタグとhtmlタグにちょいちょい記載するのみのようですし。

www.creative-web.co.jp

ferret-plus.com

外部キーが貼られているテーブルをtruncate

こんばんは。 新年早々酒を飲みながら開発してます。

いやはや、一からきっちり設計しつつ開発しつつ‥はぶつかる壁も多いです。

さて、laravelのmigrationにて外部キーも貼りつつ、seederも作っていると、 migrationの度に外部キーの貼ったテーブルをリセットしてやりたいなあと思いますよね。

でもそれできないんですよね、mysqlの設定を弄らいない限り。

外部キー貼ったテーブルはtruncateできんのじゃ!って怒られます。

調べても、やはりmysqlへの命令を投げて上げる必要があるらしい。

参考にしたURLは以下です。

私のブログは一向に調べたリンクしか貼らない。クソブログです(鬱)

qiita.com