ralphmorris

Experience

22,110

1 Best Reply Awards

  • Member Since 2 Years Ago
  • 187 Lessons Completed
  • 0 Favorites

9th June, 2018

ralphmorris started a new conversation Failed Job Delay - Queue Settings. New Field. Not Sure What It Is • 1 week ago

Hey all,

I've updated my Queue config and upped my ttr to 60 seconds in my queue beanstalkd config.

I went into my Forge queue settings to change the Timeout field to 60 also but noticed a new field that I'm not sure what is does.

Failed Job Delay

What does this do/should I set it to?

Also noticed 'Rest Seconds When Empty' which I'm not sure if I remember, but it has a default of 10 which I assume is ok?

Thanks as always :)

Ralph

3rd May, 2018

ralphmorris left a reply on Query With Conditional Logic In Relationship Has() Method Always Returning True • 1 month ago

Hi @36864 ,

Thanks for your reply.

The only trouble is the $date is different for each job so I'm not sure how I can get to it from inside the whereHas?

ralphmorris started a new conversation Query With Conditional Logic In Relationship Has() Method Always Returning True • 1 month ago

I have the following relationship set up to show me new applications compared to when a summary of new applications was last sent out..

    // Job Model

    public function applications()
    {
        return $this->belongsToMany('App\Professional', 'applications_pivot')
                    ->withPivot('message')
                    ->withTimestamps()
                    ->with('user.professional')
                    ->orderBy('message', 'desc');
    }

    public function newApplications()
    {
        if (!$this->last_summary_sent_out_at) 
        {
            $date = Carbon::now()->subDays(30);
        }
        else
        {
            $date = $this->last_summary_sent_out_at;
        }

        return $this->applications()->whereDate('applications_pivot.created_at', '>=', $date );
    }

This works well for instances like the below. Showing me only the applications that have been created since the last summary send out.

$job = \App\Job::findOrFail(1);

dd($job->newApplications);

However when I try to use the newApplications in the has() method it seems to return all jobs that have applications, not NEW applications.

$jobs = \App\Job::has('newApplications')->get();

This seems to have something todo with $this->last_summary_sent_out_at returning false in the query builder. This makes sense but not sure how to get what I want.

Any ideas? Let me know if this isn't clear enough.

Thanks!

Ralph

ralphmorris left a reply on Query Two Different Models And Merging With Pagination • 1 month ago

Thanks very much for everyones input. Direct Enquiries were a separate table with no relationship to conversations. hence I was trying to Union them somehow. However following from your comments I realised there was no reason why a direct enquiry couldn't be a child of a conversation as a conversation already hasMany messages so I created a hasOne directEnquiry and now only need to query the one table.

Not sure who to mark as best answer but all good advice thank you!

30th April, 2018

ralphmorris started a new conversation Query Two Different Models And Merging With Pagination • 1 month ago

I have two Models Conversation and DirectEnquiry that I would like to query together and show in the same list of results with pagination.

This is where I am at:

        $conversations = $user->conversations()
                                ->inbox($filters)
                                ->with('job')
                                ->paginate(20);

        $directEnquiries = $user->directEnquiries()->paginate(20);

        $conversations = $conversations->merge($directEnquiries)->sortBy(function($item) {
            
            return $item->updated_at;

        })->reverse();

This works fine until it hits the pagination method at the bottom of the view

{!! $conversations->links() !!}

I am getting the following error message:

ErrorException in Macroable.php line 74:
Method links does not exist.

I've tried playing with unions also but as these are two different models that won't work.

Any ideas?

Thanks!

Ralph

23rd April, 2018

ralphmorris started a new conversation Storing An Email Address In Session Data - File Driver, Unencrypted • 1 month ago

I have a contact form on a users profile that any visitor can fill out to send an enquiry. They then have to confirm they're email address/enquiry before the message gets sent to the user who's profile it is.

There is a chance that a visitor might want to contact a few other users via their profile contact form. I don't want to create an account for the visitor as I don't want to store the data for a one off enquiry but don't want the visitor to have to confirm their email address each time they submit an enquiry.

I have thought of two options:

  1. Store the email they confirm in a session variable so that if they send a second enquiry I simply check to see if they have already confirmed the email address.

  2. Simply lookup in the db to see if that email already exists in the enquiries table where it would be stored for a short while.

With option 1, I am using the file session driver, encryption set to false. Is this an issue if I were to be storing an email address?

With option 2, I guess the only thing would be that once that email address has been confirmed any body could submit an enquiry with that email address which would automatically be confirmed. But the likelihood of that is minimal.

What would anybody suggest?

Thanks!

Ralph

16th April, 2018

ralphmorris left a reply on Input Field Unable To Edit Or Made Changes In Sweet Alert • 2 months ago

I think for Sweet alert you need to create the inputs in a slightly different way.

Example:

swal({
  content: {
    element: "input",
    attributes: {
      placeholder: "Type your password",
      type: "password",
    },
  },
});

See here: https://sweetalert.js.org/docs/

ralphmorris left a reply on I Have A Bit Of Issues On My Laravel Project, My Jobs Run With Wrong Code. • 2 months ago

Do you by any chance have multiple queues running on the one server? For instance staging and production? If so you'd want to configure them to have different queue names.

31st March, 2018

ralphmorris left a reply on Updating Multiple Rows Ignoring SetAttribute • 2 months ago

Thanks @Snapey - ended up encrypting the string first as you said.

30th March, 2018

ralphmorris started a new conversation Updating Multiple Rows Ignoring SetAttribute • 2 months ago

I'm using L5.2 and on deletion of a user am removing the content of the users messages but keeping the rows in the db so as not to ruin the thread for other users.

I am using the following trait to encrypt/decrypt the message field which works well.

<?php

namespace App\Traits;

use Crypt;

trait EncryptableTrait
{
    public function getAttribute($key)
    {
        $value = parent::getAttribute($key);

        if (in_array($key, $this->encryptable)) {
            $value = Crypt::decrypt($value);
        }

        return $value;
    }

    public function setAttribute($key, $value)
    {
        if (in_array($key, $this->encryptable)) {
            $value = Crypt::encrypt($value);
        }

        return parent::setAttribute($key, $value);
    }
}

When updating each row separately inside a foreach loop the new string gets encrypted perfectly as per normal.

foreach ($this->messages as $message) 
{
        $message->update(['message' => 'This content is no longer available.']);
}

However there could be many messages that the user might have sent and so would rather update them all in one query. I tried the below however it skips the setAttribute.

$this->messages()->update(['message' => 'This content is no longer available.']);

Is that expected behaviour? I'd like to keep the encrypting/decrypting only in the EncryptableTrait rather than wrap "This content is no longer available" in the encrypt method if possible.

Thanks!

Ralph

13th March, 2018

ralphmorris left a reply on Order By Count This Month • 3 months ago

Hi @bashy

Thanks for your reply.

Typically, an idea came to me just after posting this question and think I've got it working now!

I created a new relationship with the added thisMonth query scope.

    public function referralsThisMonth()
    {
        return $this->referrals()->thisMonth('referral_activated');
    }

And then modified the controller method as follows:

    public function getTopReferrersThisMonth()
    {
        return User::has('referralsThisMonth')
                    ->withCount('referralsThisMonth')
                    ->orderBy('referrals_this_month_count', 'desc')
                    ->take(3)
                    ->get();
    }

ralphmorris started a new conversation Order By Count This Month • 3 months ago

Hi there,

I have a referral system where users can refer other users.

Relationships

    public function referredBy()
    {
        return $this->belongsTo('App\User', 'referred_by');
    }

    public function referrals()
    {
        return $this->hasMany('App\User', 'referred_by');
    }

There is also a 'referral_activated' dateTime field which gets set once the user is confirmed which is the point when the referrer gets their reward.

In our admin interface I am trying to get the top 3 referrers this month and order them by their referrals count that month.

My code so far.

    // Controller
    public function topReferrersThisMonth()
    {
        return User::whereHas('referrals', function ($query) {
                        $query->thisMonth('referral_activated');
                    })
                    ->withCount('referrals')
                    ->orderBy('referrals_count', 'desc')
                    ->take(3)
                    ->get();
    }

    // Model
    public function scopeThisMonth($query, $field = 'created_at')
    {
        return $query
            ->whereDate($field, '>=', Carbon::now()->startOfMonth())
            ->whereDate($field, '<=', Carbon::now()->endOfMonth());
    }

This almost does what I want apart from it is ordering by the total count, not the count this month. Can anyone point me in the right direction?

Thanks :)

Ralph

18th January, 2018

ralphmorris left a reply on Queues On Forge • 5 months ago

Thanks @bobbybouwmann for your reply. It was really helpful.

Can I just double check question 1 though? If I set the ttr in my config/queue.php to 10, do I then need to set my Timeout config to 10 also? Or does the timeout need to be larger?

I updated my forge queues to have more workers and all has been fine for a few days sending quite a few emails until just now i've had this:

Pheanstalk\Exception\ServerException: Cannot delete job 16309: NOT_FOUND 

I think this is because I still had no Timeout set in Forge, but did have the ttr set to 10 in my config. Does that sound right?

My app sent out about 40 emails and I had 3 of those exceptions. From looking at my mail logs, I can see a few of the emails look like they got sent twice.

Thanks again

16th January, 2018

ralphmorris left a reply on Chart Js Multiple Chart On A Page. Filtering/Reloading Chart • 5 months ago

@ejdelmonico Yeah, I'm thinking about bringing vue into it as have been keen to start playing with it anyway. But the app has been live for a little while now and there's not much more development that's planned yet so might feel like overkill to bring it in so late?

Correct, all 4 charts work perfectly until I filter. The filter works fine too for the last chart that is created. It's just getting multiple filters working with the same code.

ralphmorris left a reply on Chart Js Multiple Chart On A Page. Filtering/Reloading Chart • 5 months ago

Thanks @ejdelmonico,

It definitely is something to do with that.

Essentially I am initialising 4 charts on the page, the second one is currently the only with a filter but need to add it to all of them.

What I've noticed is that if I initialise the one with the filter last it works fine, but if I initialise another chart after this one, the performanceChart.chart variable is changed to the latest instance of the chart. So I am losing the instance of the chart as it is I guess being overridden.

I thought the way it worked was that each object call would have its own scope somehow but it seems that calling performanceChart.init($('#mysecondid')); a second time overwrites the performanceChart.chart variable instance.

Does anyone know how I can get around/fix this?

ralphmorris started a new conversation Chart Js Multiple Chart On A Page. Filtering/Reloading Chart • 5 months ago

I've got the following code which has worked well with multiple charts on one page until now when I have tried to add some range options which then reloads the chart.

Code:

var performanceChart = {

    chart: '',

    type: '',

    datasetValue: [],

    target: '',

    init: function(target, type) {

        performanceChart.type = type || 'bar';
        
        performanceChart.target = target;

        performanceChart.datasetValue = performanceChart.prepareDataset();
        
        performanceChart.createChart();

        performanceChart.onChange();

    },

    prepareDataset: function() {

        var label = performanceChart.target.attr('data-label');
        var data = JSON.parse(performanceChart.target.attr('data-data'));

        var datasetValue = [];

        datasetValue[0] = {
            label: label,
            data: data,
            backgroundColor: 'rgba(168, 212, 210, .6)',
            borderColor: 'rgba(168, 212, 210, 1)',
            borderWidth: 1
        }

        if (performanceChart.target.attr('data-label-2')) {

            var label2 = performanceChart.target.attr('data-label-2');
            var data2 = JSON.parse(performanceChart.target.attr('data-data-2'));

            datasetValue[1] = {
                label: label2,
                data: data2,
                backgroundColor: 'rgba(215, 190, 126, .6)',
                borderColor: 'rgb(215, 190, 126)',
                borderWidth: 1
            }

        }

        return datasetValue;

    },

    createChart: function() {

        performanceChart.chart = new Chart(performanceChart.target, {
            type: performanceChart.type,
            data: {
                labels: JSON.parse(performanceChart.target.attr('data-MonthLabels')),
                datasets: performanceChart.datasetValue
            },
            options: {
                maintainAspectRatio: false,
                responsive: true,
                scales: {
                    yAxes: [{
                        ticks: {
                            beginAtZero:true,
                            min: 0,
                            // autoSkip: true,
                            maxTicksLimit: 6,
                            // stepSize: 1
                            callback: function(value, index, values) {
                                if (Math.floor(value) === value) {
                                    return value;
                                }
                            }
                        }
                    }]
                },
            }
        });

    },

    onChange: function() {

        performanceChart.target.closest('.js-chart-container').find('.select2').change(function() {

            performanceChart.loadData($(this).closest('form'));

        });

    },

    loadData: function(form) {

        $.ajax({
            type: "POST",
            url: form.attr('action'),
            data: form.serialize(),
            success: function(result) {

                performanceChart.target.attr("data-monthLabels", JSON.stringify(result.monthLabels));
                performanceChart.target.attr("data-data", JSON.stringify(result.count));

                performanceChart.chart.destroy();

                var datasetValue = performanceChart.prepareDataset();

                performanceChart.createChart(datasetValue);
                
            },
            error: function(data){

                var errors = data.responseJSON;

                console.log(errors);
                
                return false;
            },
        });

    },

};

I can then call it multiple time with:

performanceChart.init($('#myfirstid'));
performanceChart.init($('#mysecondid'));

I am trying to store the variables in global variables inside the object like performanceChart.chart for instance. But when I try updating the first chart it ends up reloading the last chart.

I think I need to somehow scope this but not sure how.

Forgive me I'm still working on my js skills.

Thanks!

14th January, 2018

ralphmorris started a new conversation Queues On Forge • 5 months ago

2 quick questions on if anyone can clear this up for me?

  1. Should the Maximum Seconds per job in the Forge settings match the TTR in my config/queue.php? I currently have a limit of 10 in my TTR config but 0 (No timeout) in Forge. I'm not sure if these are related? I see other people are setting to 90, so is my 10 a little low. I am mainly just queue mail.

  2. Are 'Processes' in Forge the equivalent of logging in in the terminal with two different tabs and running php artisan queue:listen twice on the same site? Probably a stupid question but have anyone to ask!

Thanks!

31st December, 2017

ralphmorris started a new conversation Scope Subscribed To Plan - Laravel Cashier • 5 months ago

I have written this query scope to filter users that are subscribed to a particular plan in Laravel Cashier.

    /**
     * Scope subscribed to given plan
     * 
     * @param  $query builder
     * @param  $plan string/array
     * @return builder
     */
    public function scopeWhereSubscribedToPlan($query, $plan)
    {
        return $query
            ->active()
            ->whereHas('subscriptions', function ($s) use ($plan) {
                $s->whereNested(function ($t) use ($plan) {
                    $t->whereIn('stripe_plan', (array) $plan)
                        ->whereNull('ends_at')
                        ->orWhere('ends_at', '>', Carbon::now())
                        ->orWhereNotNull('trial_ends_at')
                        ->where('trial_ends_at', '>', Carbon::today());
                });
            });
    }

However I have noticed if the if the ends_at column is is not null and has a date in the future, it ignores the whereIn clause and shows users in the wrong plan.

Where am I going wrong?

30th December, 2017

ralphmorris left a reply on Updated Homestead To Latest - L5.2, Need Php7.0, Command Line Still Using Php7.2 - ErrorException: Count(): Parameter Must Be An Array Or An Object That Implements Countable • 5 months ago

Ah finally got it. I had to move my homestead.yaml back to the .homestead folder as it's now using the older version again.

I have php7.0 back!

2.20am here. I can now go to bed...

ralphmorris left a reply on Updated Homestead To Latest - L5.2, Need Php7.0, Command Line Still Using Php7.2 - ErrorException: Count(): Parameter Must Be An Array Or An Object That Implements Countable • 5 months ago

Hi @shez1983 - yeah I've been following the docs here:

https://laravel.com/docs/5.4/homestead#old-versions

But it still says 7.2 when I run php -v

Steps I've taken:

Top of my homestead.yaml I've added the version

---
box: laravel/homestead
version: 0.6.0
ip: "192.168.10.10"
memory: 2048
cpus: 4
provider: virtualbox

vagrant destroy --force

vagrant box add laravel/homestead --box-version 0.6.0

Reset the Homestead repo to this commit for php7.0

https://github.com/laravel/homestead/releases/tag/v3.1.0

git reset --hard 7924ab4

But then after running vagrant up, ssh'ing in and running php -v it still says php 7.2.0-1

Am I missing something? I thought this was going to fix it.

ralphmorris started a new conversation Updated Homestead To Latest - L5.2, Need Php7.0, Command Line Still Using Php7.2 - ErrorException: Count(): Parameter Must Be An Array Or An Object That Implements Countable • 5 months ago

I've updated my Laravel Homestead to the latest version where I can now control the php versions of each dev site.

I have added the php: "7.0" to my yaml however this doesn't effect the command line php version. I can see in the docs that I can do something like php7.0 artisan ... but I need phpunit to run php7 also but is running 7.2 and so am getting this error.

ErrorException: count(): Parameter must be an array or an object that implements Countable

How can I get round this? Do I have to use an older version of homestead? Or update my app to L5.5? Though I could update my app quite yet.

Thanks

ralphmorris left a reply on Hospital Management • 5 months ago

Something like this on your Bed model perhaps?

    public function assignPatient($id)
    {
        $this->patient_id = $id;
        $this->save();
    }

ralphmorris left a reply on Shared Hosting Run Php Artisan Command • 5 months ago

Do you have ssh access?

22nd December, 2017

ralphmorris left a reply on Send Form Cross-domain • 5 months ago

You could disable CSRF for only this specific route but then create your own middleware where you could do your own validation/check the referrer etc?

Just an idea.

ralphmorris left a reply on How To Navigate To Next Form In Next Tab After Saving Current Form ? • 5 months ago

You could try this I think

return redirect('/transfer-request#complete')->with('message', 'Success!');

18th December, 2017

ralphmorris started a new conversation Phpunit Really Slow With Mysql. Tried Sqlite. Throws Null Errors On Migration/saving • 6 months ago

Completely new to testing.

My production db is on MariaDB and locally I'm using MySQL on Homestead.

I've written a few very basic tests following tutorials to get started, connecting to a local mysql db.

However have noticed that to run these tests it literally takes 45 seconds. I've read that sqlite is a lot faster but is 45 seconds still normal for tests with mysql?

These are my tests. Some of them are probably a bit stupid but I'm learning ;)


use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class PagesTest extends TestCase
{
    /** @test */
    function browse_main_pages_to_artist_profile()
    {
        $this->visit('/')
            ->see('The smarter way to book hair and makeup artists for your wedding day.')
            ->click('Inspiration Board')
            ->see('Need some inspiration?')
            ->click('Browse Artists')
            ->see('Search for')
            ->select('berkshire', 'location')
            ->press('SEARCH')
            ->see('Artists In Berkshire')
            ->click('VIEW PROFILE')
            ->see('Contact Artist');
    }

    /** @test */
    function footer_pages()
    {
        $this->visit('/')
            ->click('SIGN UP')
            ->see('Request availability')
            ->click('LOGIN')
            ->see('Login')
            ->click('FAQs')
            ->see('FAQs')
            ->click('JOIN US')
            ->see('Artist Registration')
            ->click('OUR MISSION')
            ->see('Our Mission')
            ->click('TERMS OF USE')
            ->see('Terms of Use')
            ->click('PRIVACY POLICY')
            ->see('Privacy Policy')
            ->click('COOKIE POLICY')
            ->see('Use of Cookies')
            ->click('CONTACT US')
            ->see('Contact us');
    }
}

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use App\User;

class ProfessionalRegistrationTest extends TestCase
{
    /** @test */
    function a_user_fills_out_the_application_form_and_gets_a_success_message()
    {
        $email = str_random(10) . '@test-professional.com';

        $this->visit('/professional-registration')
            ->type('Ralph', 'first_name')
            ->type('Morr', 'last_name')
            ->type($email, 'email')
            ->type($email, 'email_confirmation')
            ->type('Ralphs Business name', 'business_name')
            ->type('qqqqqqQ1', 'password')
            ->type('qqqqqqQ1', 'password_confirmation')
            ->select('1', 'insurance')
            ->select('1', 'services')
            ->type('Example postal code', 'postal_code')
            ->type('some town', 'town')
            ->type('Hampshire', 'county')
            ->select('1', 'locations')
            ->type('5', 'years_experience')
            ->type('www.google.com', 'website')
            ->type('ralphyinsta', 'instagram_username')
            ->check('accept_terms')
            ->press('Sign Up')
            ->see('Email confirmation sent!');
    }

    /** @test */
    function a_professional_confirms_their_email_address()
    {
        $user = User::orderBy('created_at', 'desc')->first();

        $this->visit(route('professional.registration.confirm', $user->confirmation_code))
            ->see('Thanks for confirming!');
    }
}

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use App\User;

class BrideSignUpTest extends TestCase
{
    /** @test */
    function a_bride_fills_out_the_enquiry_form_on_the_home_page()
    {
        $email = str_random(10) . '@test-bride.com';

        $input = [
            'first_name'                        => 'Lucy',
            'last_name'                         => 'Bradd',
            'email'                             => $email,
            'email_confirmation'                => $email,
            'client[job][wedding_date]'         => '25-12-2020',
            'client[job][location_id]'          => '3',
            'client[job][bride_makeup]'         => 1,
            'client[job][bride_hair]'           => 1,
            'client[job][bridesmaids_makeup]'   => 1,
            'client[job][bridesmaids_hair]'     => 1,
            'client[job][mothers_of_hair]'      => 0,
            'client[job][mothers_of_makeup]'    => 0,
            'client[job][flower_girls_makeup]'  => 0,
            'client[job][flower_girls_hair]'    => 0
        ];

        $this->visit('/')
            ->submitForm('Send now!', $input)
            ->see('Set your password!');
    }

    /** @test */
    function a_bride_then_confirms_their_email_address()
    {
        $user = User::orderBy('created_at', 'desc')->first();

        $this->visit(route('client-dashboard.confirm', $user->confirmation_code))
            ->see('Your enquiry has been sent!');
    }
}

One thing I've also noticed is that emails are getting sent out when I run the test even though I don't have my queue worker running locally when running the tests which is kinda cool! But probably slowing down things?

Lastly, I tried using sqlite for test but got loads of errors with the migrations to do with making all fields nullable when adding to an existing table. I added nullable to get around this but then got syntax errors on the below method even this works fine with mysql. Just wondering if maintaining two database types is going to be more of a pain than it's worth?

    {
        $slug = str_slug($slug, '-');

        $count = Professional::whereRaw("slug RLIKE '^{$slug}(-[0-9]+)?$'")->count();

        return $count ? "{$slug}-{$count}" : $slug;
    }```


Appreciate any advice!

13th December, 2017

ralphmorris left a reply on Send Notification 'exactly' 1 Hour After DateTime Field • 6 months ago

Awesome. That is exactly what I want thanks.

Out of interest do you know what the limit might be of Beanstalkd/Redis? Just for future.

ralphmorris left a reply on Send Notification 'exactly' 1 Hour After DateTime Field • 6 months ago

Thanks for your responses.

I didn't know about about the delay method. Sounds awesome.

I see this as a note: "The Amazon SQS queue service has a maximum delay time of 15 minutes.".

Does the delay method work with Beanstalkd? As that is what I am currently using.

ralphmorris left a reply on Eloquent API Resources - Nested Relationship? • 6 months ago

You could add the id of the School to your students table? Then create another relationship.

ralphmorris started a new conversation Send Notification 'exactly' 1 Hour After DateTime Field • 6 months ago

I have a Job model which has a last_sent_out_at field which stores a timestamp of the last time a notification was sent. ry I have created an artisan command which I could call every minute which would query the Job model by that last_sent_out_at and send the notification if found as per the below.

        $jobs = Job::whereDate('last_sent_out_at', '=', Carbon::now()->subHour(1)->format('Y-m-d H'))->get();

        foreach ($jobs as $job) 
        {
            $job->sendNotification();
        }

However:

a) This seems like a lot of db calls for one simple occasional task. Can anyone suggest a better way?

b) the $jobs var is constantly returning 0 when I dd($jobs->count()) even when I run date in the terminal, quickly add the correct minute 1 hour ago and run the command.

Thanks

ralphmorris left a reply on 'Return Ajax' Printing The Code? • 6 months ago

Try returning your array with something like.

return response()->json(['success'=>1, 'msg'=> trans('app.payment_received_msg'), 'response' => $this->payment_success_html()]);

https://laravel.com/docs/5.5/responses#json-responses

ralphmorris left a reply on How Do You Get The Updated_at Date For Only Certain Fields • 6 months ago

Try adding another dateTime field where you would store the timestamp of when you updated your specific information?

I'd probably leave the actual updated_at field as it can sometimes come in handy down the line.

1st November, 2017

ralphmorris left a reply on Export Table To CSV - Escaping Commas • 7 months ago

Just trying to add the ability to remove certain keys from the exported csv, like 'id' etc.

I've tried adding the following line at the top of the above method.

$collection = $collection->forget($collection->first()->notExportable);

But has it has no effect?

On my model I have for example:

    public $notExportable = [
        'id',
        'some_other_protected_field'
    ];

My controller:

    public function exportToCsv(UserFilters $filters)
    {
        $users = User::filter($filters)->new()->get();

        $exporter = new Exporter;

        return $exporter->exportToCsv($users);
    }

29th October, 2017

ralphmorris left a reply on Order By Tag Priority • 7 months ago

@tisuchi I have the longitude and latitude of the users on a separate professionals table which is where I am storing all their profile information. I'm unsure how I can order the users by the lng and lat of their values on the professional table.

These are my relationships:

Location Model

    public function users()
    {
        return $this->belongsToMany('App\User');
    }

User Model

    public function professional()
    {
        return $this->hasOne('App\Professional');
    }

My query currently is:

        $professionalUsers = $location->users()->active();

        $professionalUsers->has('portfolio');

        $professionalUsers = $professionalUsers->paginate(20);

To add the orderBy nearest longitude and latitude login I want to add something like:

        $professionalUsers = $location->users()->active();

        $professionalUsers->has('portfolio');

        // Example location. Hardcoded for now.
        $lat = '50.842991';
        $lng = '50.842991';

        $professionalUsers = $professionalUsers
        ->orderBy(\DB::raw('ABS(lat - '.(float)$lat.') + ABS(lng - '.(float)$lng.')'),'ASC' )
        ->paginate(20);

But this is looking for lat and lng columns on the users table.

I found that orderBy line here:

https://stackoverflow.com/questions/28601607/laravel-orderby-calculated-value

I think I need to do a join but not sure where/how?

Thanks

25th October, 2017

ralphmorris started a new conversation Beanstalkd Error - Job 4058 NOT_FOUND: Does Not Exist Or Is Not Reserved By Client / Queue/Forge Tip • 7 months ago

Hi,

I've just had a notification from Sentry on my new app. A new post has just been sent out and so about 42 emails were added to the queue.

The error is:

Beanstalkd Error - Job 4058 NOT_FOUND: does not exist or is not reserved by client

I have found a few forum discussions suggesting to up the ttr. Mine is currently set to only 10 in my config/queue.php which I'm discovering sounds very low?

I can see in the mailgun logs one temporary failed message: "Service closing transmission channel - command timeout" which I guess might be where the response from mailgun took too long and so hit the ttr?

I think there might also be a slight issue with my Forge config not matching my config/queue.php - does the timeout section have to match the ttr?

In my config/queue.php I have:

        'beanstalkd' => [
            'driver' => 'beanstalkd',
            'host' => 'localhost',
            'queue' => env('QUEUE_NAME'),
            'ttr' => 10,
        ],

And in my Forge settings I have one queue set up as the following:

Connection: beanstalkd Queue: queue-production Timeout: 0 Processes: 1 Tries: 3 Daemon: No

Can someone just confirm that my set up looks ok and suggest a more appropriate ttr/timeout in Forge?

Thanks

ralphmorris left a reply on Order By Tag Priority • 7 months ago

Hi @tisuchi

Sorry I should have mentioned. The Locations are UK counties that a user can choose to cover or not.

Some users may only want to cover one county while others might choose to cover 10.

However they may still want to prioritise certain counties over others.

There's likely to be some restriction as to how many counties a user can cover based on subscription level in the future.

Thanks

ralphmorris started a new conversation Order By Tag Priority • 7 months ago

Hi,

I have a many to many relationship between Users and Locations so that users can tag themselves to certain locations they want to show up in.

I need to somehow order the results by the priority of their tag (Location). I am imagining making my select2 drag and drop sortable so that they can put preferred locations higher up to be prioritised more. However how this could be implemented on the server side I am not sure.

Possibly by adding an integer field to the users_locations table?

Does anyone have any idea how I could do this? And then be able to order the Users on the frontend?

I hope this is clear. It's confusing me a little!

Thanks

Ralph

22nd October, 2017

ralphmorris left a reply on Occasional TokenMismatch Error - Is That Normal? • 7 months ago

Thanks guys for your responses. Congrats @Snapey on the 1000 best answers!

@ejdelmonico - Just to double check. My forms all contain the _token hidden input and all I'm doing is serialising the form with something like:

        $.ajax({
            type: "POST",
            url: $('form').attr('action'),
            data: $('form').serialize(),

So the token is inside with the form data.

In parts where I am sending an ajax request without the use of a form I use

        $.ajaxSetup({
            headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
            }
        });

@Snapey - would you mind expanding on why the CSRF isn't needed on the login form? One of the forms is located on the homepage so it's very possible that the user has left and come back later. The other is the login page so this would be possible also. The third is a logged in profile page where they can add/update bits of info.

Thanks!

21st October, 2017

ralphmorris started a new conversation Occasional TokenMismatch Error - Is That Normal? • 7 months ago

Hi,

I launched my first Laravel app about 4 months ago with Laravel 5.2, Forge & Digital Ocean. All is going well so far but have noticed Sentry has flagged the TokenMismatch error 5 times since October 3rd. We have 225 users so far, approx 1000 users a month, average duration on the site is 5 mins.

It looks like 3 separate occasions though in 3 different parts of the site. I haven't found any issue when using those sections myself.

3rd Oct - Creating a resource. The user does not have to be logged in but has an account created after creating the resource. Many users have since created the same resource just fine.

10 Oct - 3 errors on the same user action. Update another resource with ajax. I have tested this but all seems to work fine for me. The user must be logged in to get to this page.

21 Oct - postLogin method when logging in.

I have read other posts where the TokenMismatch error is happening multiple times a day. Is it normal to get a few of these errors here and there?

Thanks!

Ralph

18th October, 2017

ralphmorris left a reply on Export Table To CSV - Escaping Commas • 8 months ago

Thanks both for your replies :)

I initially tried @Cronix's suggestion as it was closest to what I already had which worked well for the escaping of commas but when I tried it on some live data I discovered there were more characters that needed escaping. I then tried @robrogers3's suggestion and integrated it into my class. It worked great with all data I tested it with.

Here is the full code incase it helps anyone else in the future.

<?php

namespace App\Exporter;

class Exporter
{
    /**
     * Export any collection to CSV. All fields exported.
     * 
     * @param  Collection $collection
     * @return Response downloads CSV
     */
    public function exportToCsv($collection)
    {
        $f = fopen('php://memory', 'w+');
        
        $header = array_keys($collection->first()->toArray());

        fputcsv($f, $header);
        foreach ($collection as $thread)
            fputcsv($f, $thread->toArray());

        rewind($f);

        $headers = [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => 'attachment; filename="export.csv"',
        ];

        return \Response::make(stream_get_contents($f), 200, $headers);
    }
}

17th October, 2017

ralphmorris started a new conversation Export Table To CSV - Escaping Commas • 8 months ago

Hi there,

I wonder if anyone can help me.

I am working on creating an export to CSV function for any collection I pass to it.

I have created the following class.

<?php

namespace App\Exporter;

class Exporter
{
    
    public function exportToCsv($collection)
    {
        $first = $collection->first();

        $output = implode(", ", array_keys($first['attributes']))."\n";

        foreach ($collection as $row) 
        {
            $output .= implode(", ",$row['attributes'])."\n";
        }

        $headers = [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => 'attachment; filename="export.csv"',
        ];

        return \Response::make($output, 200, $headers);
    }
}

This works well if there are no commas, but one field on say the Users table contains a description where the user can easily enter commas. These commas are breaking the layout of my csv export. I know I need to escape the commas I think by wrapping each field in double quotes but can't figure out how to achieve this with the implode function.

Any help appreciated!

18th September, 2017

ralphmorris left a reply on Messaging System. Should Encrypt Messages In Db? • 9 months ago

Thanks @kobear for your advice.

The application is marketed at mostly self employed/small businesses selling their services.

I did end up adding the trait and writing a migration to update all the current messages just to be safe.

16th September, 2017

ralphmorris started a new conversation Scope Orderby Subscription Level - Cashier • 9 months ago

I have 3 subscription levels with Laravel Cashier and Stripe.

Free - no customer/subscription created. Pro Member - monthly subscription Pro Plus member - monthly subscription

I have been tasked with ordering Users by subscription like so.

Pro Plus Member - Priority 1 Pro Member - Priority 2 Free - Priority 3

The only idea I have is to have an integer 'order' field on the user model and create a global scope to order by this field.

But I am wondering if there is a tidier way that I can do the calculation based on the stripe_plan itself?

Stripe Plans Ids are as above:

Pro Plus Member Pro Member Free (no stripe plan created)

Thanks in advance

Ralph

2nd September, 2017

ralphmorris started a new conversation JOB_TOO_BIG: Job Data Exceeds Server-enforced Limit • 9 months ago

I have just added encryption to my messages model on the message field.

All is working well with standard size messages but when adding 1000 words as a bit of a stress test. I start to get JOB_TOO_BIG: job data exceeds server-enforced limit.

It is failing when I try to add a new message notification onto the Mail queue. I am using Pheanstalk.

I've just tested it again but removing the encryption and restoring the database. It still happens but it takes a few more large messages for it to overload the queue so I guess this issue was still here before encryption it's just the messages haven't been long enough to cause any issue. So my concern is that when I release the encryption on messages the message field will become larger and this may become an issue on production?

How can I ensure that I don't overload the queue?

After the queue has been overloaded, it seems to crash as even small messages get the same error after. However no more messages are sent with the Mail queue. I have to literally delete the rows that are too big from the database for the queue to begin working again. Is there another way to manage this?

Thanks

29th August, 2017

ralphmorris started a new conversation Messaging System. Should Encrypt Messages In Db? • 9 months ago

Hoping for some good advice here.

I have recently launched my first web app which includes a messaging system between two different user roles - professional, client.

Currently the messages in the database are not encrypted. However I recently had a conversation with a friend that suggested that I maybe should consider it with new rules that are coming in like GDPR. Not that I can find much information at all on GDPR at this point.

I have found a good post below that I would use to encrypt the data if starting from scratch but don't really like the idea of creating some kind of migration to loop through all the current unencrypted messages, encrypting them and then re-saving.

https://laracasts.com/discuss/channels/laravel/encrypting-model-data

The content of the messages aren't likely to be very personal at all, however it did occur to me that a professional may give their account number and sort code if asking for a deposit for a job. Not a requirement at all but possible. Not hugely sensitive either.

I do have it in the terms of use to not submit anything that they consider to be confidential to the site which I have been assured does cover me in the event that anything happened. However I am wondering what others might do, what the standard is and if there is anything else I should know. Is there anything that suggests it is mandatory? The site uses SSL.

Thanks in advance.

Ralph

20th August, 2017

ralphmorris left a reply on IE Conditionals Removing Head Tag • 10 months ago

Turned out to be Cloudflare HTML auto minify causing the issue. It was removing the last closing for some reason, completely breaking the site from ie9 and below. I have temporarily disabled HTML auto minify and it is all working again.

I've contacted Cloudflare support also to ask if there is a fix for this.

19th August, 2017

ralphmorris started a new conversation IE Conditionals Removing Head Tag • 10 months ago

Apologies, this seems really trivial but is driving me up the bend.

I have the following ie conditionals around my html tag. However in ie9 the head completely disappears meaning css isn't brought among everything else!. This is only happening however on my Forge, Digital Ocean, Lets Encrypt, Cloudflare staging and production site. I have the site set up on an older server still running php7 on webfaction.com and it displays fine in ie9.

As soon as I remove the conditionals the head appears and styles are brought in. I've tried adding the conditionals to the body tag but it looks like the whole body then goes inside a comment.

I've also tried copy and pasting other examples but none of them seem to work here. For example:

https://css-tricks.com/snippets/html/add-body-class-just-for-ie/

But still doesn't work.

This is my head.

<!DOCTYPE html>

<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en"> <![endif]-->
<!--[if IE 7]>    <html class="no-js ie7 oldie" lang="en"> <![endif]-->
<!--[if IE 8]>    <html class="no-js ie8 oldie" lang="en"> <![endif]-->
<!--[if IE 9]>    <html class="no-js ie9" lang="en"> <![endif]-->
<!--[if gt IE 9]><!-->
<html class="no-js" lang="en">
<!--<![endif]-->

<head>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title>@yield('title')</title>

    <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700,900" rel="stylesheet">

    <link href="{{ elixir('css/app.css') }}" rel="stylesheet">

    <!--[if lt IE 9]>
        <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->

</head>

Does anyone have any idea what it could be?

Thanks

Ralph

16th August, 2017

ralphmorris left a reply on Display Profile Views By Month • 10 months ago

Thanks @paschal ,

Nice and clean solution. Thats pretty much what I was imagining.

I'm gonna go ahead and implement!

12th August, 2017

ralphmorris started a new conversation Display Profile Views By Month • 10 months ago

I need to implement a profile view counter that can also group the views by month so as to give a little graph on the users dashboard.

I have found a tutorial like this one which seems good but it just increments a value on the model which would mean I couldn't group by month.

http://blog.stidges.com/post/implementing-a-page-view-counter-in-laravel

I am tempted to make a table named profileviews with timestamps and simply create a row for each view but I'm wondering if this could be overkill or if it wouldn't be a great idea baring in mind a user would end up having a lot of views?

The only other option i've thought of is incrementing a view_count value on the profile table and having a scheduled job at the end of each month to create a row in the profileviews table. But this might again be a bit overkill/complicated for what I'm trying to achieve.

Can anyone point me to the most suitable solution?

Thanks

Ralph

1st August, 2017

ralphmorris started a new conversation Unable To Read Image From File. How To Catch If Image Upload Is Unsuccessful • 10 months ago

I have just had a notification from Sentry with the following error on my new app:

Intervention\Image\Exception\NotReadableException Unable to read image from file (/tmp/phpS1aKpd).

            $rawImage = $file;
        } else
        {
            $imagePath = $file->getRealPath();
            $rawImage = \Image::make($imagePath); // this line is highlighted as the error
        }
        $rawImage->orientate();
        $rawImage->resize(1000, null, function ($constraint) {```

I was fortunate enough to be able to speak to the user who explained that they had uploaded an image on their phone from their icloud account when it threw the error. I realised that I didn't have mimes validation in place and now that it is the attempted image is not being accepted. My bad! :(

First question: in mimes validation, do I have to define jpg, jpeg, JPG etc or just jpg? Seems to work with but just wondering.

Secondly, is there a way to catch an error if the file does not get uploaded?

This is my code:

PortfolioController
```    public function store(Requests\StorePortfolio $request)
    {  
        $user = \Auth::user();

        $fileName = AssetManager::createFileName($user->publicName() . '-wedding-portfolio');

        $request->merge(['fileName' => $fileName]);

        $item = $user->professional->portfolio()->create($request->all());
        $this->syncTags($item, (array) $request->input('tag_list'));

        $path = $item->urlPath();

        $variations = config('imagesizes.portfolio');
        
        AssetManager::saveWithVariations($request->file, $path, $fileName, $variations);

        return redirect()->route('professional-dashboard.portfolio.index');
    }```

AssetManager class

``` public static function saveWithVariations($file, $path, $fileName, $imageVariations, $visibilty = 'public')
    {
        if (isset($file->mime)) // is Intervention object
        {
            $rawImage = $file;
        } else
        {
            $imagePath = $file->getRealPath();
            $rawImage = \Image::make($imagePath);
        }

        $rawImage->orientate();

        $rawImage->resize(1000, null, function ($constraint) {
            $constraint->aspectRatio();
            $constraint->upsize();
        })->encode('jpg', 80);

        $uploaded = AssetManager::saveToStorage(
            $rawImage->stream()->__toString(),
            $path . $fileName,
            $visibilty
        );

        if ($uploaded) 
        {
            foreach ($imageVariations as $key => $value) {

                $image = $rawImage;
                
                if ($uploaded) 
                {
                    if ($value['h'] == 'auto') 
                    {
                        $image->resize($value['w'], null, function ($constraint) {
                            $constraint->aspectRatio();
                            $constraint->upsize();
                        });
                    } else 
                    {
                        $image->fit($value['w'], $value['h']);
                    }
                    $uploaded = AssetManager::saveToStorage(
                        $image->stream()->__toString(),
                        $path . $key . '-' . $fileName,
                        $visibilty
                    );
                }    
            }
            return $uploaded;
        } else 
        {
            return false;
        }

    }```

I am thinking something like this in my PortfolioController which doesn't work for me.

```        try {
            
            AssetManager::saveWithVariations($request->file, $path, $fileName, $variations);
            
        } catch (Exception $e) {
            

            // redirect back with errors

        }```

This is my first Laravel app and have learn't loads but still feel like this area could be a lot better.

Any advice appreciated.
Edit Your Profile
Update

Want to change your profile photo? We pull from gravatar.com.