ElijahPaul

ElijahPaul

London

Member Since 3 Years Ago

Experience Points 1,320
Experience
Level
Lessons Completed 0
Lessons
Completed
Best Reply Awards 1
Best Answer
Awards
  • Start Your Engines Achievement

    Start Your Engines

    Earned once you have completed your first Laracasts lesson.

  • First Thousand Achievement

    First Thousand

    Earned once you have earned your first 1000 experience points.

  • One Year Member Achievement

    One Year Member

    Earned when you have been with Laracasts for 1 year.

  • Two Year Member Achievement

    Two Year Member

    Earned when you have been with Laracasts for 2 years.

  • Three Year Member Achievement

    Three Year Member

    Earned when you have been with Laracasts for 3 years.

  • Four Year Member Achievement

    Four Year Member

    Earned when you have been with Laracasts for 4 years.

  • Five Year Member Achievement

    Five Year Member

    Earned when you have been with Laracasts for 5 years.

  • School In Session Achievement

    School In Session

    Earned when at least one Laracasts series has been fully completed.

  • Welcome To The Community Achievement

    Welcome To The Community

    Earned after your first post on the Laracasts forum.

  • Full Time Learner Achievement

    Full Time Learner

    Earned once 100 Laracasts lessons have been completed.

  • Pay It Forward Achievement

    Pay It Forward

    Earned once you receive your first "Best Reply" award on the Laracasts forum.

  • Subscriber Achievement

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • Lifer Achievement

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • Laracasts Evangelist Achievement

    Laracasts Evangelist

    Earned if you share a link to Laracasts on social media. Please email [email protected] with your username and post URL to be awarded this badge.

  • Chatty Cathy Achievement

    Chatty Cathy

    Earned once you have achieved 500 forum replies.

  • Laracasts Veteran Achievement

    Laracasts Veteran

    Earned once your experience points passes 100,000.

  • Ten Thousand Strong Achievement

    Ten Thousand Strong

    Earned once your experience points hits 10,000.

  • Laracasts Master Achievement

    Laracasts Master

    Earned once 1000 Laracasts lessons have been completed.

  • Laracasts Tutor Achievement

    Laracasts Tutor

    Earned once your "Best Reply" award count is 100 or more.

  • Laracasts Sensei Achievement

    Laracasts Sensei

    Earned once your experience points passes 1 million.

  • Top 50 Achievement

    Top 50

    Earned once your experience points ranks in the top 50 of all Laracasts users.

08 Jan
1 week ago

ElijahPaul left a reply on Reload Form And Script Via AJAX

This is what loads when the register view is loaded via its URL:

<script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>
<div id="_g-recaptcha"></div>
<div class="g-recaptcha" data-sitekey="6LeIxAcTA_MXjiI" data-size="invisible" data-callback="_submitForm" data-badge="bottomright"></div><script src="https://www.google.com/recaptcha/api.js?hl=en" async defer></script>
<script>var _submitForm,_captchaForm,_captchaSubmit,_execute=true;</script><script>window.addEventListener('load', _loadCaptcha);
function _loadCaptcha(){_captchaForm=document.querySelector("#_g-recaptcha").closest("form");_captchaSubmit=_captchaForm.querySelector('[type=submit]');_submitForm=function(){if(typeof _submitEvent==="function"){_submitEvent();grecaptcha.reset();}else{_captchaForm.submit();}};_captchaForm.addEventListener('submit',function(e){e.preventDefault();if(typeof _beforeSubmit==='function'){_execute=_beforeSubmit(e);}if(_execute){grecaptcha.execute();}});}</script>

This is what loads when I reload the id="content" DIV via jQuery .load() :

<div id="_g-recaptcha"></div>
<div class="g-recaptcha" data-sitekey="6LeIxAcTA_MXjiI" data-size="invisible" data-callback="_submitForm" data-badge="bottomright"></div>

As you can see the script tags aren't executed/loaded.

I'm not sure how to refresh the both the form and the @captcha via AJAX?

ElijahPaul left a reply on Reload Form And Script Via AJAX

@JLRDW - My dropdown selector sets the locale and reloads the form via AJAX. When the form is loaded via URL (http://myapp.com/register) the scripts via the @captcha() directive load fine.

However, if you change the locale via my dropdown which also reloads the form via:

$('#content ').load(location.href + ' #content>*', '');

the @captcha() scripts don't execute. So submitting the form fails.

ElijahPaul left a reply on Reload Form And Script Via AJAX

@JLRDW - @jlrdw I think I'm missing something. I only see a jQuery example for submitting a form via AJAX. Not loading one via AJAX. Do correct me if I'm wrong.

ElijahPaul started a new conversation Reload Form And Script Via AJAX

I have a dropdown selector in my register view (Laravel 5.7) that allows users to change the locale when signing up. This reloads the form (inside id="content") via AJAX.

......
$.ajax({  
  data: {locale: lang_prefix},  
  type: 'GET',  
  url: '/locale/' + lang_prefix,  
  success: function (result) {        
  $('#content ').load(location.href + ' #content>*', '');
  }  
});
......

I'm also using the albertcht/invisible-recaptcha reCaptcha package with my form which renders via the @captcha blade directive.

register.blade.php

......
<div id="content">
    <form method="POST" action="{{ secure_url('register') }}">
        @csrf
        <input id="name" class="form-control" autocomplete="name" type="text" name="name" value="{{ old('name') }}" required autofocus>
        <input id="email" class="form-control" autocomplete="email address" type="email" name="email" value="{{ old('email') }}" required>
        <input id="password" class="form-control" autocomplete="new-password" type="password" name="password" required>
        <button id="submit-btn" type="submit" class="btn">
        @captcha
    </form>
</div>
......

The problem I'm facing is how to have the @captcha directive execute when the form is reloaded via AJAX?

I've read that jQuery .load() doesn't execute scripts with a selector expression appended to the URL. Which is how I'm refreshing my form:

$('#content ').load(location.href + ' #content>*', '');

So I'm assuming that that is what's causing the failure of reCaptcha script to execute when the form reloads?

How can I reload the form and have the @captcha execute via AJAX?

Thanks.

24 Nov
1 month ago

ElijahPaul started a new conversation Advice On Loop Of A Large Array Of IPs

I'm using the torann/geoip package to lookup ISO country codes for IPs in a large array and then count & format them to plot a highmaps map bubble chart:

foreach ($ip_array as $d) {
            $highmaps_array[] = [
                'code' => geoip($d['ip'])->iso_code,
            ];
        }

.......     

The function does cache (I'm using Redis) locations which helps performance with repeat requests.

For example, looking up 30,000 IPs takes ~30secs with no cached locations and ~4.5secs with (VPS node: 1vCPU 2.2GHz, 2GB RAM).

My question is how to manage when/if the array contains millions (or even a billion+) IPs? What can I do to reduce inevitably long loop times that ultimately slows down the chart render?

10 Nov
2 months ago

ElijahPaul left a reply on Add & Populate New UUID Column In Existing Users Table

Replacing the schema:

Schema::table('users', function (Blueprint $table) {
            $table->uuid('uuid')->nullable(false)->change();
        });

with a raw query:

DB::statement('ALTER TABLE users ALTER COLUMN uuid SET NOT NULL;');

seems to have done the trick.

Thanks again for your help @bobbybouwmann

ElijahPaul left a reply on Add & Populate New UUID Column In Existing Users Table

@BOBBYBOUWMANN - Thank you. That makes sense, I understand now.

I'm now running into the following error when trying to modify the column back to not nullable:

 Unknown column type "uuid" requested. Any Doctrine type that you use has to be registered with \Doctrine\DBAL\Types\Type::addType(). You can get a list of all the known types with \Doctrine\DBA
  L\Types\Type::getTypesMap(). If this error occurs during database introspection then you might have forgotten to register all database types for a Doctrine Type. Use AbstractPlatform#registerDo
  ctrineTypeMapping() or have your custom types implement Type#getMappedDatabaseTypes(). If the type name is empty you might have a problem with the cache or forgot some mapping information.

Any ideas on how I can resolve this?

ElijahPaul started a new conversation Add & Populate New UUID Column In Existing Users Table

How would I go about adding and populating a new (not nullable) UUID column in my existing users table?

My guess is to use a migration that creates a nullable UUID column, populates each user with a UUID and then modifies the column back to not nullable.

My current migration:

class AddUuidToUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->uuid('uuid')->nullable();
        });

        //  Insert UUIDs for each user here

        Schema::table('users', function (Blueprint $table) {
            $table->uuid('uuid')->nullable(false)->change();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('uuid');
        });
    }

How would I go about inserting a UUID for each existing user in this case?

I've tried:

$users = DB::table('users')->get();

        foreach ($users as $user) {
            $user->uuid = Str::uuid()->toString();
            $user->save();
        }

which results in:

Call to undefined method stdClass::save()
07 Sep
4 months ago

ElijahPaul left a reply on SSH Error.

@malico I guessed your hosting provider. Try connecting to SSH on port 722.

06 Sep
4 months ago

ElijahPaul left a reply on SSH Error.

@malico Have you contacted your service provider about the issue?

SSH'ing to your domain times out.

Host 'daughtersmh.com' resolved to 77.72.0.102.
Connecting to 77.72.0.102:22...
Could not connect to 'daughtersmh.com' (port 22): Connection failed.
03 Sep
4 months ago

ElijahPaul left a reply on GroupBy & Count Records (Laravel 5.6, PostgreSQL 9.6)

@bobbybouwmann Thank you.

I understand now I wasn't counting the results.

Your first example works (with count() instead of sum())

.
.
.
    })->map(function ($spamLog) {
        return $spamLog->count();  
    });

With your second example I receive the following error:

SQLSTATE[42803]: Grouping error: 7 ERROR: column "spamlog.timestamp" must appear in the GROUP BY clause or be used in an aggregate function LINE 1: select DATE(timestamp) as date, count(*) as count from "spam... ^ (SQL: select DATE(timestamp) as date, count(*) as count from "spamlog" group by "date")

I'm wondering if it has anything to do with https://stackoverflow.com/questions/46909307/laravel-groupby-doesnt-work-properly-with-postgresql

Thanks again for your help.

ElijahPaul started a new conversation GroupBy & Count Records (Laravel 5.6, PostgreSQL 9.6)

I have a Spam Log table (Laravel 5.6, PostgreSQL 9.6):

| id | isspam | timestamp | score | |----|------|---------------------|-------| | 1 | t | 2018-09-01 08:43:25 | 10.12 | | 2 | f | 2018-09-02 02:42:42 | -0.52 | | 3 | t | 2018-09-03 00:39:39 | 8.71 |

I'm trying to produce an array containing a count of spam = true grouped by day for the last 'x' number of days. e.g.

{
    "03": 1,
    "02: 0,
    "01" 1
}   

I've tried:

$now = Carbon::now();  
$daily_spam_count = SpamLog::where('timestamp', '>=', $now->subDays(7))  
 ->where('isspam', true)  
 ->get()  
 ->groupBy(function($date){  
  return Carbon::parse($date->timestamp)->format('d');  
  });

But instead of the count, this gives me:

{
    "01": [
        {
        "id": 1,
        "isspam": true,
        "timestamp": "2018-09-01 08:43:25",
        "score": "10.12"
        }
    ],
    "02: [
        {
        "id": 2,
        "isspam": false,
        "timestamp": "2018-09-02 02:42:42",
        "score": "-0.52"
        }
    ],
    "03: [
        {
        "id": 3,
        "isspam": true,
        "timestamp": "2018-09-03 00:39:39",
        "score": "8.71"
        }
    ]
}   

What am I missing in my query?

26 Aug
4 months ago

ElijahPaul left a reply on [5.4] Npm Run Watch Not Working

I was looking for some visual indication that recompiling was taking place, but in my case (like @mcraz says) it was happening in the background without issue.

11 Jul
6 months ago

ElijahPaul left a reply on Validate Form Served Via AJAX Call Using JQuery Validation

I had to also re-initialise my jQuery validation plugin, but this worked great.

Thank you.

09 Jul
6 months ago

ElijahPaul left a reply on Laravel 5.5 - Redis Queue Logs

No answer. :( Have since moved queues for this app to amazon SQS.

08 Jul
6 months ago

ElijahPaul started a new conversation Validate Form Served Via AJAX Call Using JQuery Validation

can't seem to figure this one out.

I've configured my login form to submit via AJAX. My LoginController.php checks to see if the user has 2FA enabled, and if so pulls the form from the @section('content) section of the 2FA blade template and loads it (via AJAX) into the @section('content') section of the existing layout:

layouts/auth.blade.php

<html>
    <head>
        ...
    </head>
    <body>
        <div id="content">
            @yield('content')
        </div>
        <script src="{{ secure_asset('js/jquery.min.js') }}"></script>
        <script src="{{ secure_asset('js/jquery.validate.min.js') }}"></script>
        <script src="{{ secure_asset('js/login.js') }}"></script>
    </body>
</html>

login.blade.php

@extends('layouts.auth')

@section('content')
    <form id="loginForm" class="js-validation">
        <div class="form-group">
            <input id="email" name="email" type="email">
        </div>
        <div class="form-group">
            <input id="password" name="password" type="password">
        </div>
        <button id="login-submit-btn" class="btn"></button>
    </form>
@endsection

2fa.blade.php

@extends('layouts.auth')

@section('content')
    <form id="2faLoginForm" class="js-validation">
        <div class="form-group">
            <input id="passcode" type="tel" name="passcode">
        </div>
        <button id="submit-btn" class="btn"></button>
    </form>
@endsection

login.js

....
// login form jQuery
$(document).on('click', '#login-submit-btn', function (e) {
    e.preventDefault();
    if ($('.js-validation').valid()) {
        var formData;
        formData = $('#loginForm').serialize();
        var validator = $(".js-validation").validate();
        $.ajax({
            url: '/login',
            type: 'POST',
            data: formData,
            dataType: 'JSON',
            success: function(data) {
                console.log(data);
                if (data.intended) {
                    window.location.href = data.intended;
                } else {
                    $("#content").html(data.content);
                }
            },
            error: function(data){
                var errors = $.parseJSON(data.responseText).errors;
                if (errors.email) {
                    validator.showErrors({
                        "email": errors.email[0]
                    });
                }
                if (errors.password) {
                    validator.showErrors({
                        "password": errors.password[0]
                    });
                };
            }
        });
    }
})

// 2fa form jQuery
$(document).on('click', '#submit-btn', function (e) {
    e.preventDefault();
    if ($('.js-validation').valid()) {
        var validator = $(".js-validation").validate();
            $.ajax({
                url: "/login/2fa",
                type: 'POST',
                data: {
                    "_token": $('input[name="_token"]').val(),
                    "passcode": $('#passcode').val(),
                },
                error: function (data) {
                    var error;
                    var message;
                    if (data.responseJSON.errors) {
                        error = data.responseJSON.errors.passcode[0];
                        validator.showErrors({
                            "passcode": error
                        });
                    }
                },
                success: function (data) {
                    window.location.href = data.intended;
                }
            });
    }
});

LoginController.php

private function authenticated(Request $request, Authenticatable $user)
    {
        if ($request->ajax()) {
            if (!empty($user->google2faSecurity->google2fa_enable)) {
                Auth::logout();
                $request->session()->put('2fa:user:id', $user->id);
                $twoFactorLogin = view('login.2fa')->renderSections();
                return response()->json([
                    'content' => $twoFactorLogin['content'],
                ]);
            }
            return response()->json([
                'intended' => $this->redirectPath(),
            ]);
        }
    }

While jQuery Validate works with the initial loaded login.blade.php form, it doesn't with the AJAX served 2fa.blade.php form added to the DOM that replaces it. So no client side validation is performed on the newly displayed 2fa form.

How can I get jQuery validation to work on the AJAX served 2fa form?

After a fair bit of Googling (and tinkering) I've come up with nothing that works. :(

Thanks.

P.S. If I'm going about this all wrong or there are mistakes please do let me know.

16 Jun
7 months ago

ElijahPaul left a reply on Reload DIV

Thanks.

I ended up having to change a bunch of other additional DIV's, so this method is a lot more efficient.

11 Jun
7 months ago

ElijahPaul started a new conversation Reload DIV

I'm using the following button to launch a modal which allows the user to enable or disable 2FA in my app:

<div id="2fa-modal-btn">
@if(!empty(Auth::user()->google2fa_enabled))
    <button class="btn btn-danger" data-target=".2fa-modal" data-toggle="modal" type="button">Disable 2FA</button>
@else
    <button class="btn btn-primary" data-target=".2fa-modal" data-toggle="modal" type="button">Enable 2FA</button>
@endif
</div>

Once 2FA is enabled/disabled I reload the DIV using AJAX via its id like so:

$.ajax(
    {
        url: "/2fa/enable",
        type: 'GET',
        dataType: "JSON",
        data: {
            "verify-code": $('#verify-code').val(),
        },
        success: function (data)
        {
            console.log(data.success);            
            $("#2fa-modal-btn").load(location.href+" #2fa-modal-btn>*","");                                   
        }
    });

Is there a better/more efficient way of achieving this? I'm wondering if it may be better to change the class and text of the button rather than reload the DIV?

16 Apr
9 months ago

ElijahPaul left a reply on PostgreSQL Connection Via Environment Variables For Local And Production Environments.

@Cronix I feel stupid for not thinking of that. So simple! Thank you.

ElijahPaul started a new conversation PostgreSQL Connection Via Environment Variables For Local And Production Environments.

How would i configure the config/database.php file to account for an unsecured local PostgreSQL connection and a secure production one?

My current config:

'pgsql' => [
            'driver' => 'pgsql',
            'host' => env('DB_HOST', 'localhost'),
            'port' => env('DB_PORT', '5432'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'charset' => 'utf8',
            'prefix' => '',
            'schema' => 'public',
            'sslmode' => 'prefer',
        ],

If I add the following to the database.php config file...

.....
'sslcert' => env('DB_SSLCERT', ''),
'sslkey' => env('DB_SSLKEY', ''),
'sslrootcert' => env('DB_SSLROOTCERT', ''),
.....

And set the environment variables (only in production)...

DB_SSLMODE=verify-full
DB_SSLCERT=/path/to/mycert.pem
DB_SSLKEY=/path/to/mykey.pem
DB_SSLROOTCERT=/path/to/myrootcert.pem

The local connection (without adding the corresponding environment variables) fails, but the production environment (with the variables set) connects successfully.

So how should i configure config/database.php to accommodate both local (unsecured) and production (secure) database connection requirements?

12 Mar
10 months ago

ElijahPaul started a new conversation Laravel 5.5 - Redis Queue Logs

Are the Redis (4.0.8) logs below normal behaviour/expected? (My queues are processing normally)

1520861326.143064 [0 lua] "lpop" "queues:default"
1520861329.143602 [0 10.42.197.60:54104] "GET" "app_cache:illuminate:queue:restart"
1520861329.144294 [0 10.42.197.60:54104] "EVAL" "-- Get all of the jobs with an expired \"score\"...\nlocal val = redis.call('zrangebyscore', KEYS[1], '-inf', ARGV[1])\n\n-- If we have values in the array, we will remove them from the first queue\n-- and add them onto the destination queue in chunks of 100, which moves\n-- all of the appropriate jobs onto the destination queue very safely.\nif(next(val) ~= nil) then\n    redis.call('zremrangebyrank', KEYS[1], 0, #val - 1)\n\n    for i = 1, #val, 100 do\n        redis.call('rpush', KEYS[2], unpack(val, i, math.min(i+99, #val)))\n    end\nend\n\nreturn val" "2" "queues:default:delayed" "queues:default" "1520861329"
1520861329.144615 [0 lua] "zrangebyscore" "queues:default:delayed" "-inf" "1520861329"
1520861329.145030 [0 10.42.197.60:54104] "EVAL" "-- Get all of the jobs with an expired \"score\"...\nlocal val = redis.call('zrangebyscore', KEYS[1], '-inf', ARGV[1])\n\n-- If we have values in the array, we will remove them from the first queue\n-- and add them onto the destination queue in chunks of 100, which moves\n-- all of the appropriate jobs onto the destination queue very safely.\nif(next(val) ~= nil) then\n    redis.call('zremrangebyrank', KEYS[1], 0, #val - 1)\n\n    for i = 1, #val, 100 do\n        redis.call('rpush', KEYS[2], unpack(val, i, math.min(i+99, #val)))\n    end\nend\n\nreturn val" "2" "queues:default:reserved" "queues:default" "1520861329"
1520861329.145370 [0 lua] "zrangebyscore" "queues:default:reserved" "-inf" "1520861329"
1520861329.145913 [0 10.42.197.60:54104] "EVAL" "-- Pop the first job off of the queue...\nlocal job = redis.call('lpop', KEYS[1])\nlocal reserved = false\n\nif(job ~= false) then\n    -- Increment the attempt count and place job on the reserved queue...\n    reserved = cjson.decode(job)\n    reserved['attempts'] = reserved['attempts'] + 1\n    reserved = cjson.encode(reserved)\n    redis.call('zadd', KEYS[2], ARGV[1], reserved)\nend\n\nreturn {job, reserved}" "2" "queues:default" "queues:default:reserved" "1520861419"
23 Feb
10 months ago

ElijahPaul left a reply on 'Method WhereBetween Does Not Exist' When Using Cached Query.

@m-rk yeah, I'm slowly figuring that out.

The DB (postgres) has ≈ 20,000 records at the moment, and all the 'fiddling' I've done so far regarding caching + filtering has negatively impacted performance.

Overall query and filtering performance is actually pretty good as it is. So I may just leave this one alone for now.

Still learning, so I appreciate the input.

ElijahPaul left a reply on 'Method WhereBetween Does Not Exist' When Using Cached Query.

@m-rk I believe you're right.

I don't think I will end up using this, but still wanted to understand why it wasn't working.

Looking at various ways of reducing DB queries and caching whatever possible (if it improves overall performance and scales of course).

ElijahPaul left a reply on 'Method WhereBetween Does Not Exist' When Using Cached Query.

@tykus Awesome, thank you.

I need to read up on Collections again, the error seems so obvious now!

ElijahPaul started a new conversation 'Method WhereBetween Does Not Exist' When Using Cached Query.

Still relatively new to Laravel (5.5) so I think I'm not understanding this correctly.

I'm caching a database query in Redis using the following:

$log = Cache::remember('log'.auth()->id(), 10, function () {
                return log::select(['id', 'clientip', 'token', 'timestamp'])->get();
            });

I want to perform a whereBetween on the cached result and have tried:

$logquery = Cache::get('log'.auth()->id());
$now = Carbon::now();
$to = Carbon::parse($request->get('daterange'));
$logrange = $logquery->whereBetween('timestamp', [$to,$now]);

But this fails with Method whereBetween does not exist in my json response.

What am I doing wrong/not understanding?

Any help appreciated.

31 Jan
11 months ago

ElijahPaul started a new conversation Duplicate Queries., Different `where` Statements

I'm using clone in the following to perform multiple queries with different where statements.

$query = DB1::whereIn('email',$verified_user_domains);

        $total_clean_count = (clone $query)->where('isspam',false)->count();

        $total_spam_count = (clone $query)->where('isspam',true)->count();

I intend to run a whole bunch of additional where statements and was wondering if there was a more efficient way of achieving this.

Thanks.