Buy your loved one the ultimate gift. Lifetime gift certificates are $100 off.

sanuglia

Experience

7,700

0 Best Reply Awards

  • Member Since 8 Months Ago
  • 64 Lessons Completed
  • 0 Favorites

10th August, 2017

sanuglia left a reply on Laravel 5.4 Doesn't Return Json 422 If There's A Custom Validator? • 4 months ago

I've discovered that axios wasn't actually sending an ajax request, thus causing the redirect response.

Is there a way to delete the original post?

sanuglia started a new conversation Laravel 5.4 Doesn't Return Json 422 If There's A Custom Validator? • 4 months ago

Using Laravel 5.4, I've defined a custom validator in my AppServiceProvider:

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
    
        // Custom validators
        Validator::extend('greater_than_field', function($attribute, $value, $parameters, $validator) {
            $min_field = $parameters[0];
            $data = $validator->getData();
            $min_value = $data[$min_field];
            return $value > $min_value;
        });
        
        Validator::replacer('greater_than_field', function($message, $attribute, $rule, $parameters) {
            return str_replace(':field', $parameters[0], $message);
        });

    }

And I have a Form Request:

class ClientAttachBusinessRequest extends FormRequest
{
    
    
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return TRUE;
    }
    
    
    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'businessName' => 'required',
            'fromDate'     => 'sometimes|nullable|date',
            'toDate'       => 'sometimes|nullable|date|greater_than_field:fromDate',
        ];
    }
    
    
    public function messages()
    {
        return [
            'toDate.greater_than_field' => 'The TO date must come AFTER the FROM date',
        ];
    }
    
    public function withValidator( $validator )
    {
    
        $this->validator = $validator;
    
        if ( $this->validator->fails() ) {

            // This doesn't work. The redirect response still gets sent.
            //return response()->json( [ 'error' => 'Business already attached.' ], 422 );

            // Here, I can see the error: {\"toDate\":[\"The TO date must come AFTER the FROM date\"]})
            Log::write( 'event', "Error(s)", [ __LINE__, $this->validator->errors() ] );
            
            return;
        }
        
    
        $this->validator->after(
            function ( $validator ) {
    
                // Check to see if the business has already been attached.

            } );
    }   
}

Finally, the controller:

    public function attachBusiness( $client_id, ClientAttachBusinessRequest $request )
    {
    
    
        
        if ( $request->ajax() ) {
        
            if ( $request->businessAlreadyAttached )
                return response()->json( [ 'error' => 'Business already attached.' ], 422 );
            
            if ( $request->invalidBusiness )
                return response()->json( [ 'error' => 'Invalid business.' ], 422 );
            
            if ( $request->invalidBusinessString )
                return response()->json( [ 'error' => 'Invalid business string.' ], 422 );
            }
        }
        
        $this->client_id = $client_id;
        $this->attachEntity( $client_id, 'businesses', 'business', $request );
        
        if ( $request->ajax() ) {
            $client     = Client::withTrashed()->find( $client_id );
            $businesses = $client->businesses()->get();
        
            return view(
                'business.table', [
                'businesses'          => $businesses,
                'detachBusinessRoute' => route(
                    'client.detachEntity', [
                    'client_id' => $client->id,
                ] ),
        
            ] );
        }
        
        
        return redirect( route( 'client.show', [ 'id' => $client_id, '#allBusinesses' ] ) );
    }

This setup works, unless using ajax/axios. From the documentation, if there are any validation errors, " Laravel will not generate a redirect response. Instead, Laravel generates a JSON response containing all of the validation error."

And that's true if I submit an invalid businessName. But if I submit an invalid toDate (e.g. it's greater than the fromDate), Laravel generates a redirect, and my page refreshes.

I can see that the withValidator() method gets invoked, and it does log the error:

{\"toDate\":[\"The TO date must come AFTER the FROM date\"]}

... and returns. But it does NOT generate a JSON response.

As you can

The only difference that I can see between the businessName and the toDate fields is that the latter uses a custom validator.

Is this expected behavior?

How can I force a JSON response instead of a redirect?

9th August, 2017

sanuglia left a reply on Axios To Catch Custom Validation Rule Error Message? • 4 months ago

Indeed, when I have a custom rule as defined in my AppServiceProvider (as above), and the validation of such rule fails, it appears that Laravel DOES generate a redirect response instead of generating a JSON response containing all of the validation errors when using AJAX.

Has anyone else experienced this?

sanuglia left a reply on Axios To Catch Custom Validation Rule Error Message? • 4 months ago

Wellllll,....now that I've fixed the js to send the toDate values correctly, the validation now fails correctly when the toDate is less than fromDate.

But instead of returning a 422 with JSON of the message, the page gets redirected (refreshed).

Might anyone have an idea of why it's not returning a JSON with error message instead?

sanuglia left a reply on Axios To Catch Custom Validation Rule Error Message? • 4 months ago

Orrrr,...maybe not. I just noticed that those fields aren't being passed to the controller. Thanks for pointing me that way! I can take it from here.

sanuglia left a reply on Axios To Catch Custom Validation Rule Error Message? • 4 months ago

Oh, yes, I neglected to say that I do include the 'fromDate' when testing the 'toDate', so that sometimes does trigger.

sanuglia started a new conversation Axios To Catch Custom Validation Rule Error Message? • 4 months ago

Using Laravel 5.4, I've set up a custom validation rule:

class AppServiceProvider extends ServiceProvider
{
    
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        
        // Custom validators
        Validator::extend(
            'greater_than_field', function ( $attribute, $value, $parameters, $validator ) {
            $min_field = $parameters[ 0 ];
            $data      = $validator->getData();
            $min_value = $data[ $min_field ];
            
            return $value > $min_value;
        } );
        
        Validator::replacer(
            'greater_than_field', function ( $message, $attribute, $rule, $parameters ) {
            return str_replace( ':field', $parameters[ 0 ], $message );
        } );
    ...

And I have a Form Request class:

class ClientAttachBusinessRequest extends FormRequest
{
    
    public $business;
    public $validator;
    public $businessAlreadyAttached = FALSE;
    public $invalidBusiness         = FALSE;
    public $invalidBusinessString   = FALSE;
    
    
    public function __construct( array $query = array(), array $request = array(), array $attributes = array(),
                                 array $cookies = array(), array $files = array(), array $server = array(),
                                 $content = NULL
    )
    {
        parent::__construct( $query, $request, $attributes, $cookies, $files, $server, $content );
    }
    
    
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return TRUE;
    }
    
    
    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'businessName' => 'required',
            'fromDate'     => 'sometimes|nullable|date',
            'toDate'       => 'sometimes|nullable|date|greater_than_field:fromDate',
        ];
    }
    
    
    public function messages()
    {
        return [
            'businessName.required' => 'Nyet.',
            'toDate.greater_than_field' => 'The TO date must come AFTER the FROM date',
        ];
    }
}

If I submit a form with an invalid toDate "normally", the $errors is populated, and I'm able to display the message in my view using {{ $errors->first('toDate') }}.

Now use ajax/axios:

If I submit a form with an empty string for the businessName, I do get an HTTP 422 response with the contents of:

{"businessName":["Nyet."]}

If I submit a form with an empty string for the toDate, I do NOT get an HTTP 422 response. Instead, my controller continues processing as if nothing was invalidated.

Is this a feature? a bug? My goal here is to return an error message to the axios POST.

8th August, 2017

sanuglia left a reply on Form Request Validation; WithValidator() To Check If Any Rules() Have Already Failed? • 4 months ago

Ah, never mind. I found this nifty little method:

    public function withValidator( $validator )
    {
    
        if ( $validator->fails() ) {
            // Handle errors
        }
        ...
    }

...that I can use at the beginning of the withValidator() method.

sanuglia started a new conversation Form Request Validation; WithValidator() To Check If Any Rules() Have Already Failed? • 4 months ago

In Laravel 5.4, it appears that the withValidator() method gets executed even if the validation rules fail. Example:

class ClientAttachBusinessRequest extends FormRequest
{
    public function rules()
    {
        return [
            'businessName' => 'required',
            'fromDate'     => 'sometimes|nullable|date',
            'toDate'       => 'sometimes|nullable|date|greater_than_field:fromDate',
        ];
    }

    
    /**
     * Configure the validator instance.
     *
     * @param  \Illuminate\Validation\Validator $validator
     *
     * @return void
     */
    public function withValidator( $validator )
    {
        
        $validator->after(

            function ( $validator ) {
                
                // Extract the business id from the string.
                $businessString = $this->request->get( 'businessName' );  // Start with "Murazik-Swaniawski (ID: 30)"
                $businessString      = explode( "ID:", $businessString ); // Now have "30)"
                $businessId     = rtrim( $businessString[ 1 ], ")" ); // Now have "30"
                
                // Find the business Record 
                $this->business = Business::where( 'id', $businessId )->get()->first();
                
                if ( $this->business ) {
                    
                    $businessName = $this->business->businessName;
                    
                    $client = Client::find( $this->client_id );
                    
                    if ( $client->businesses->contains( $this->business->id ) ) {
                        
                        $validator->errors()->add(
                            'businessName',
                            "The business: <strong>$businessName</strong> is already attached to this Client (See above ⬆ ). Please select another." )
                        ;
                    }
                }
                $validator->errors()->add( 'businessName', 'Invalid business.' );
            }
        );
    }

}

The documentation indicates that the withValidator() method is used as an "AFTER hook to a form request".

Now, if the businessName submitted is empty (""), then withValidator() will fail with this code because it can't extract the businessId from the submitted string.

Sure, I could check for a valid businessName string before I do that, but I'm curious to know how I could check for any validation rules that have already failed upon entering withValidator()?

24th July, 2017

sanuglia left a reply on Softdelete On ManyToMany Polymorphic Relations. • 4 months ago

I'm kind of in the same boat right now. Anyone?

27th June, 2017

sanuglia left a reply on Laravel And X-editable, Ajax Not Being Validated • 5 months ago

Yes, well, sort of.

To the extent of validating a single field, I created a ("form request")[https://laravel.com/docs/5.4/validation#form-request-validation] and then I applied conditionals in the rules() method.

In the following example, I have a table with a client's Contact info, so I want to validate firstName, lastName, and email.

First, you'll note that x-editable sends the fieldname as the name parameter. Here's a dd() of the request:

ParameterBag {#389
  #parameters: array:4 [
    "name" => "email"
    "value" => "[email protected]"
    "pk" => "110"
    "_token" => "ex6Cs1tcdHboHjO55qvclomcc8hKgj0YUNLqBHUb"
  ]
}

So we just have to see what name (field) is being passed, and make an appropriate rule for it. Something along the lines of:

<?php namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class ContactUpdateFieldRequest extends FormRequest
{
    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
       
        switch ( $this->request->get( 'name' ) ) {
            case "firstName":
            case "lastName":
                $validationRules[ 'value' ] = 'required|min:3';
                break;
            case "email":
                $validationRules[ 'value' ] = 'required|email';
                break;
            default:
                $validationRules[ 'value' ] = 'required';
        
        }
    
        return $validationRules;
    }
}

It works. And probably there's a better way. Please let me know if that helped.

26th June, 2017

sanuglia left a reply on How To Get The Pivot_id Value? • 5 months ago

Well, the first consequence is that detach() needs a string, and furthermore, it needs the value in the business_id field. And that won't work if I have two records with the same business_id:

mysql> select * from business_pcontact where pcontact_id=12;
+----------+-------------+-------------+----------+--------+------------+------------+
| pivot_id | business_id | pcontact_id | fromDate | toDate | created_at | updated_at |
+----------+-------------+-------------+----------+--------+------------+------------+
|       39 |           4 |          12 | NULL     | NULL   | NULL       | NULL       |
|       40 |           4 |          12 | NULL     | NULL   | NULL       | NULL       |
+----------+-------------+-------------+----------+--------+------------+------------+

Getting the record using:

$pivotRecord = $contact->businesses()->where('pivot_id','=',39)->first();

...doesn't do me much good if I want to use detach(). Well, it's late now, I'll pick this up tomorrow.

sanuglia left a reply on How To Get The Pivot_id Value? • 5 months ago

The main issue that I was running into when I was trying to access the id field in the business_pcontact table using $contact->businesses()->where('pivot_id','=',39)->first(); was that the SQL rightly complained that Column 'id' in where clause is ambiguous.

So my work-around to this was to change the name of the auto-increment field to pivot_id in the migration so that it yields:

mysql> desc business_pcontact;
+-------------+------------------+------+-----+---------+----------------+
| Field       | Type             | Null | Key | Default | Extra          |
+-------------+------------------+------+-----+---------+----------------+
| pivot_id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| business_id | int(10) unsigned | NO   | MUL | NULL    |                |
| pcontact_id | int(10) unsigned | NO   | MUL | NULL    |                |
| fromDate    | datetime         | YES  |     | NULL    |                |
| toDate      | datetime         | YES  |     | NULL    |                |
| created_at  | timestamp        | YES  |     | NULL    |                |
| updated_at  | timestamp        | YES  |     | NULL    |                |
+-------------+------------------+------+-----+---------+----------------+

This way, I can now specify the relationship as such:

    public function businesses()
    { return $this->belongsToMany( 'Archie\Model\Entity\Business')
        ->withTrashed()
        ->withPivot('pivot_id','fromDate', 'toDate')
        ->withTimeStamps();
    }

And then finally, I can find the specific record in the pivot table by pivot_id by using:

$contact->businesses()->where('pivot_id','=',39)->first();

I don't know what consequences this is going to have in the future, but it's one way to skin a cat.

sanuglia started a new conversation How To Get The Pivot_id Value? • 5 months ago

I've got many-to-many relationships between my Business and Pcontact models, both ways, in a pivot table business_pcontact, where the table structure is:

mysql> desc business_pcontact;
+-------------+------------------+------+-----+---------+----------------+
| Field       | Type             | Null | Key | Default | Extra          |
+-------------+------------------+------+-----+---------+----------------+
| id          | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| business_id | int(10) unsigned | NO   | MUL | NULL    |                |
| pcontact_id | int(10) unsigned | NO   | MUL | NULL    |                |
| fromDate    | datetime         | YES  |     | NULL    |                |
| toDate      | datetime         | YES  |     | NULL    |                |
| created_at  | timestamp        | YES  |     | NULL    |                |
| updated_at  | timestamp        | YES  |     | NULL    |                |
+-------------+------------------+------+-----+---------+----------------+

And in my models I have the relationships defined as:

    public function businesses()
    { return $this->belongsToMany( 'App\Model\Entity\Business')
        ->withTrashed()
        ->withPivot('id','fromDate', 'toDate')
        ->withTimeStamps();
    }

Now I'm setting up the method to detach that record, but I can't figure out how to reference the id field in the business_pcontact table with something along the lines of:

    public function detachEntity( $contact_id, $pivot_id )
    {
        $contact = Pcontact::find( $contact_id );
        $contact->businesses()->detach( [ $pivot_id ] );
    }

Now, I could do something like:

$businesses  = $contact->businesses()->get();
foreach($businesses as $business){
    if ($business->pivot->id == $pivot_id){}; 
}

But there's got to be a better way to do this, right? Could someone please point me in the right direction to find a single record in a pivot table by the pivot table's id field?

16th June, 2017

sanuglia started a new conversation Dusk Testing Templates With @stack And @push • 5 months ago

Once I discovered the awesomeness of @stack and @push, I was able to streamline and standardize my views.

However, it seems that dusk might be having some difficulty with these, and I can't imagine why.

For example, I have a few elements that I check for in every Page:

abstract class Page extends BasePage
{
    public static function siteElements()
    {
        return [
            '@appDiv' => '#app',
            '@pagename' => '#page-name',
        ];
    }

After I segregated a view into component templates, and implemented @stack and @push , dusk now errors out with:

Unable to locate element: {"method":"css selector","selector":"body #app"}

I checked the resultant HTML, and <div id="app"> is indeed there.

Note that these tests were ran successfully before I implemented @stack and @push, so I can only imagine that dusk isn't "seeing" a fully-rendered page,....or something.

Has anyone else come across a similar situation? If so, might you know what's causing this, or better yet, how you got the dusk tests to work?

7th June, 2017

sanuglia left a reply on Join Tables Or Something Else? • 6 months ago

@jimmck Heh, thanks. I've already ordered a few, but they're still on back-order.

In any event, I re-read the docs, and I think that perhaps I was getting ahead of myself. Setting up many to many relationships, one at a time would work.

6th June, 2017

sanuglia started a new conversation Join Tables Or Something Else? • 6 months ago

I'm hoping that someone could help me out with a strategy here.

I have an Account model, and a Client model, and there's a many-to-many relationship between those two. An account may have many clients, and a client may have many accounts. So far, so good.

But as I delve deeper into the details, I realize that an Account may have one or more email addresses. Likewise for a Client. Fine, so I abstract out an Email model. Then it dawns on me that I can abstract out a Phone Number, and maybe even an IM address. And now I have three more tables.

The emphasis here is that an Account can have zero or many emails, phone numbers, and/or IM addresses.

Well, I do see that there's a commonality between those three; namely that they're "Digital addresses" of sorts. So I could abstract out to a single table like this:

digital_contacts
=============
id
contact_type (maybe an enum of ["phone", "email", "fax", "im"] as an EXAMPLE?)
contact_value (varchar 100 or something)

Hmm, not bad. But now, how to relate the data. Well, a pretty good solution would be to have a "join table" of sorts. Something along the lines of:

account_emails
=============
id
account_id
digital_contact_id

And then another for phone numbers:

account_phones
=============
id
account_id
digital_contact_id

And another for fax, im, and anything else that might come up in the future. Now I have a whole bunch of tables and models. It works, but it's starting to get uglier.

An alternative might be to ALTER the digital_contacts table so it looks something like:

digital_contacts
=============
id
contact_value
model_name
field_name

Where the field_name is the property of the class that it's relating. Ie. Account model, and primary_phone property. Yeaaaah,,...now we're going to have a whole bunch of methods to get at the data. E.g.

pub function getPrimaryEmailAddresses($id){
}
pub function getSecondaryEmailAddresses($id){
}
pub function getPrimaryPhone($id){
}

Again, it could work, and it feels like we're now loosing cohesion.

Then I go looking at Eloquent to see what it can help with, but I'm not finding much inspiration there either. I do see polymorphic relations, and that seems kind of what I think I need, and it may work for some of these relationships. In fact, the section on Polymorphic Many To Many Relations looks close, .. but i'm not convinced that's the most efficient/proper/correct way to do this.

So I'd like to ask for anyone's thoughts on this, and maybe suggest a good enough strategy to tackle these many, many-to-many relationships (pun intended.)

30th May, 2017

sanuglia started a new conversation How To Use The Window.app Object? • 6 months ago

In a Laravel 5.4 install, the examples show an app object created in r/a/js/app.js:

const app = new Vue({
    el: '#app'
});

And I've built a few components which work fine.

But now, I'm trying to implement an "object oriented form", as described in the (Vue video series) [ https://laracasts.com/series/learn-vue-2-step-by-step ], into this form I have, which already includes some of these custom components I made.

My blade looks something like:

    <div id="app">
        <h1 class="contract-header-h1">
            Edit a {{ trans('contracts.contract_short') }}
        </h1>
        <form action="{{ route('contract.update', ['id' => $contract->id]) }}" @onSubmit.prevent="onSubmit" class="" method="POST">

            <div class="form-group">
                <username-list field_name="securedBy" user_id="{{$contract->securedBy_user->id}}">
                </username-list>
            </div>
        </form>
    </div>

Now, I wouldn't want to create a new div#app2 for this form, so I'm thinking that maybe I ought to use the already-existing app object, and simply add properties. Something along the lines of:

<script>
            window.app.methods = {
                onSubmit() {
                    alert('Submitted');
                }
            }
</script>

But that yields:

Property or method "onSubmit" is not defined 

So my questions are:

  • Am I going about this the right way? I mean, should I try to re-use that app object?

  • If so, or not, then how would I include a one-off vue in a form/page that already includes vue components without creating a separate el: binding?

29th May, 2017

sanuglia left a reply on Unix Timestamp For Deleted_at Field And Soft Deletes • 6 months ago

Thank you both for your suggestions.

@Stratos: It's not the migration that's giving me trouble, it's the actual deletions. When I have the column set up as an INT, and when I attempt to delete a row, I get prompted with the error I described in my 4th code paste.

@Snapey: Ultimately, you're right in that it doesn't REALLY matter which format I save the datetime in the database. For this project, it's just much easier that it does so. However, you do bring up a good point in your last sentence; namely that I'd be missing out on a number of those helper functions.

I will admit that I hadn't considered that.

Now that I do, and in combination with the lack of a firm answer to my original question, it may prove easier in the long run to keep things "native." In other words, it sounds like storing those datetimes as INTs would be working "against the grain" of Laravel, so to speak.

At this point, having soft deletes, along with all of those helper functions seems like it would be more fruitful than having those dates in INT columns.

By the way, I did find this morning that someone that wrote a class to get me to where I want(ed?) to go (https://github.com/al-one/laravel-soft-deletes-unix) My initial go at it failed, but I'm no longer convinced that having those datetimes stored as INTs.

Either way, I want to thank you both for your patience, and your advice.

28th May, 2017

sanuglia left a reply on Unix Timestamp For Deleted_at Field And Soft Deletes • 6 months ago

I am appreciative of you trying to help me, and I don't mean to be argumentative.

If I understand you right, you're describing how a default Laravel is set up; that the 3 fields we're discussing are all timestamps by default. And that the $dateFormatAnd that if I want something other than a timestamp field, that I should create a mutator. Is that approximately correct?

Although, I would disagree with you that the "$dateFormat property allows you to pass a different format to, or get a different format from, the model. "

Maybe that's true in a more general sense, and I won't argue that.

But, two paragraphs after https://laravel.com/docs/5.4/eloquent-mutators#date-mutators, there's a section titled 'Date Formats', which explicitly says "If you need to customize the timestamp format, set the $dateFormat property on your model. " And I have done that, and indeed that is reflected in my table definition (4th code paste)

With that aside, the default setup isn't what I need. The created_at and updated_at fields are working perfectly: the data for the front-end gets converted to an 'mm-dd-yy' format, and the data is stored as an integer. Just how it's supposed to be for this project.

If I hadn't wanted/needed to keep the data stored as an integer, I'd be very happy with using Laravel's defaults with all three fields stored as timestamps. But this is not the case, not in this project.

Now, I would presume that the deleted_at field would behave similarly.

But it doesn't.

Which brings me to here; to ask 'If I needed to store the deleted_at values as unix timestamps (i.e. int) in the database, how would I go about doing that?"

Again, I do appreciate you explaining to me how things are set up as default. But I need to do something a little different here.

27th May, 2017

sanuglia left a reply on Unix Timestamp For Deleted_at Field And Soft Deletes • 6 months ago

By default, you're absolutely correct, created_at, and updated_at are timestamps.

However, that can be changed according to the (docs)[https://laravel.com/docs/5.4/eloquent-mutators] by doing adding a mutator:

class Flight extends Model
{
    /**
     * The storage format of the model's date columns.
     *
     * @var string
     */
    protected $dateFormat = 'U';
}

As to why I want/need to use them, well I REALLY, REALLY hope that this does not come across as rude, but that's completely beside the point. Suffice it that the project I'm working on has a design requirement that needs to store datetimes in unix timestamp.

It doesn't matter why I need to change them; all I'm asking for is how to change the deleted_at field.

sanuglia left a reply on Unix Timestamp For Deleted_at Field And Soft Deletes • 6 months ago

Thank you so much for the reply, but the created_at, and updated_at columns are not timestamps, only the deleted_at is. And with all due respect, that doesn't answer my question; it only describes how I could do things differently (or perhaps "normally", in this case.)

One of the design requirements for this project is to store our datetime fields as unix timestamps in the database. Even if it wasn't a requirement, I very much prefer to do so anyway.

I do see what you mean, though, and I suppose that I could work around the deleted_at being different.

See, I have many other datetime fields in the table (that were not shown here) and they're all unix timestamps. So this work-around will mean that I'll have to treat this field differently than I do all of the other date/time fields:

  • a different function in the javascript datetime pickers.
  • a different validation for this field only.
  • addition of Carbon where it wasn't needed before
  • probably affects other areas that I can't think of right now.

Granted, all of these issues aren't a very big deal, and I could implement them without too much trouble. But it sure would be nice to have the flexibility to have all of my datetime fields to be treated similarly.

sanuglia started a new conversation Unix Timestamp For Deleted_at Field And Soft Deletes • 6 months ago

I apologize if this is not the correct Channel, and if it isn't could I please ask that this question be moved to a more correct one?

The (instructions)[https://laravel.com/docs/5.4/eloquent#soft-deleting] for setting up soft deletes in Laravel 5.4 are rather straight-forward.

Except that I need to use unix timestamps for all three (created_at, updated_at, deleted_at) fields.

Now, I have in my model:

use Illuminate\Database\Eloquent\SoftDeletes;

class Term extends Model
{
    
    use SoftDeletes;
    
    /**
     * The storage format of the model's date columns.
     *
     * @var string
     */
    protected $dateFormat = 'U';
    
 
    
    /**
     * The attributes that should be mutated to dates.
     *
     * @var array
     */
    protected $dates = ['created_at', 'updated_at', 'deleted_at'];

    . . . 

}

Following the docs: "Of course, you should add the deleted_at column to your database table. " So I diligently do.

$table->unsignedInteger('created_at');
$table->unsignedInteger('updated_at');
$table->unsignedInteger('deleted_at');

But the migration errors out with:

Duplicate column name 'deleted_at'

Fine. I remove that and I'm able to migrate.

However, the field now is a timestamp field. Ugh:

+--------------+------------------+------+-----+---------+
| Field        | Type             | Null | Key | Default |
+--------------+------------------+------+-----+---------+
| deleted_at   | timestamp        | YES  |     | NULL    |
| created_at   | int(10) unsigned | NO   |     | 1       |
| updated_at   | int(10) unsigned | NO   |     | 1       |
+--------------+------------------+------+-----+---------+

Consequently, when I go to delete a record, I'm busted with an error of:

Invalid datetime format: 1292 Incorrect datetime value: '1495872563' for column 'deleted_at' at row 1

So how could I make it so that the deleted_at field is an int(10) unsigned, or at least not a timestamp ?

24th May, 2017

sanuglia left a reply on Specify Files For Npm To Watch • 6 months ago

I suppose another way to post this question would be:

What I'm looking for is the list of files and/or directories that npm run watch watches to TRIGGER a (re)compile all assets; and how to edit that list.

23rd May, 2017

sanuglia left a reply on Sorting Relationship For Select Element • 6 months ago

Wellll, I'm not sure. I've read that previously, and I'll admit that while I'm not totally clear on the term 'eager loading', I don't think that's what I'm doing here. See, my controller calls the edit form like so:

    /**
     * @param \Archie\Components\Contract\Contract $contract
     *
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function edit(Contract $contract) {
        return view('contracts.edit' ,compact('contract'));
    }

And then my custom component looks like this:

                                    <username-list
                                            field_name='securedBy'
                                            user_id="{{$contract->securedBy_user->id}}"></username-list>

So instead of trying to sort this at the back-end, I scoured around for for a vue solution. It appears that the orderBy filter is no more in Vue 2, so I found something that fits the bill:

<template>

    <div>

        <select
                class="selectpicker form-control"
                data-style="btn-primary"
                :name="field_name"
                :id="field_name"
                style="width:100%;"
                v-model="selected">
            <option v-for="username in sortedUsers" v-bind:value="username.id">
                {{ username.username }}
            </option>
        </select>

    </div>

</template>


<script>

    export default {
        props   : {
            user_id   : {},
            field_name: {},
        },
        data(){
            return {
                usernames: [],
                selected : this.user_id,
            }
        },
        filters : {},
        methods : {},
        computed: {
            sortedUsers: function () {
                function compare(a, b) {
                    if (a.username < b.username) 
                        return -1;
                    if (a.username > b.username) 
                        return 1;
                    return 0;
                }

                return this.usernames.sort(compare);
            }
        },

        created() {
            axios.get('/api/usernames').then(response => this.usernames = response.data);
        },
    }
</script>

I'd still be curious to know if there's a way to do this in the controller.

sanuglia started a new conversation Sorting Relationship For Select Element • 6 months ago

In my Contract model, I specify that the securedBy field contains the user id

// Contract.php
use Illuminate\Database\Eloquent\Model;
use App\Auth\User;

class Contract extends Model {
   /**
     * Get the user (rep) for this contract
     */
    public function securedBy_user()
    { return $this->belongsTo(User::class,'securedBy')->select(array('id', 'username')); }
}

And I'm able to get a select element in blade (via a vue component).

<select>
<option value="15">sid85</option>
<option value="21">rosana.stark</option>
<option value="7">rgutowski</option>
</select>

My goal here is to sort by username. I've tried variations on this theme:

    public function securedBy_user()
    { return $this->belongsTo(User::class,'securedBy')->select(array('id', 'username')->orderBy('username','asc')); }

But I'm not having much luck with that.

Does anyone have a reference that you could point me to, or know how this could be done?

22nd May, 2017

sanuglia started a new conversation Specify Files For Npm To Watch • 6 months ago

The docs indicate that npm run watch will run "all relevant files for changes." But where do I see which files are relevant?

Specifically, I have some files in resources/assets/js/components that I'd like to have compiled. But say I had an arbitrary file that I also wanted to include.

How would one specify that?

20th May, 2017

sanuglia left a reply on Webpack And Mix, Either Or? • 6 months ago

Heh, I suppose like many students, I overcomplicated this more than I absolutely needed to.

Here's the webpack.mix.js that ended up working for what I needed:

mix.js('resources/assets/js/app.js', 'public/js').extract(['vue', 'axios'])
    .sass('./resources/assets/sass/app.scss', 'public/css')
    .sass('./resources/assets/sass/dashboard.scss', 'public/css');

mix.combine([
    './resources/assets/vendor/bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css'
], 'public/css/vendor.css');

mix.js([
    'resources/assets/vendor/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js'
], 'public/js/vendor.js');


sanuglia started a new conversation Webpack And Mix, Either Or? • 6 months ago

I must be missing something, and maybe I'm approaching this all wrong. So I'm hoping that someone could shed some light on this.

I want to use https://github.com/smalot/bootstrap-datetimepicker, and so I cloned it to my resources/assets/vendors directory.

My goal here is to have something like this:

public
├── css
│   ├── app.css
│   └── vendor.css
└── js
    ├── app.js
    └── vendor.js

Taking notes from the documentation as well as Jeffrey's webpack video and the associated example webpack config, I ended up with a webpack.mix.js that looks like this:

const {mix} = require('laravel-mix');

mix.js('resources/assets/js/app.js', 'public/js')
   .sass('resources/assets/sass/app.scss', 'public/css')
   .sass('resources/assets/sass/dashboard.scss', 'public/css');


mix.combine([
    'resources/assets/vendor/bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css'
], 'public/css/vendor.css');


mix.webpackConfig({

    entry: {
        app   : './resources/assets/js/app.js',
        vendor: [
            'vue',
            'axios',
            './resources/assets/vendor/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js'
        ]
    },

    output: {
        path      : path.resolve(__dirname, 'public/js'),
        filename  : '[name].js',
        publicPath: '/'
    }

});

The package.jsonis not using a custom webpack.config.js:

config=node_modules/laravel-mix/setup/webpack.config.js",

Now, the result of npm run dev gives me a structure of

public
├── css
│   └── vendor.css
├── favicon.ico
├── index.php
├── js
│   ├── app.js
│   ├── css
│   │   ├── app.css
│   │   └── dashboard.css
│   ├── js
│   │   └── app.js
│   ├── mix-manifest.json
│   └── vendor.js
├── mix-manifest.json
└── robots.txt

So it seems to me that the output.path (which is set to path.resolve(__dirname, 'public/js')) is being used for both js and css stuff — sort-of.

Fine. I then:

  1. Comment out the whole mix.webpackConfig block in webpack.mix.js
  2. Copy node_modules/laravel-mix/setup/webpack.config.js to ./webpack.config.js
  3. Change the package.json to use my custom webpack.config.js`, which now has this:
// module.exports.entry = Mix.entry().get();
module.exports.entry = {
    app   : './resources/assets/js/app.js',
    vendor: [
        'vue',
        'axios',
        './resources/assets/vendor/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js'
    ]
};


// module.exports.output = Mix.output();
module.exports.output = {
    path      : path.resolve(__dirname, 'public/js'),
    filename  : '[name].js',
    publicPath: '/'
};

Run npm run dev, and I now get a tree that's closer, but blatantly missing the css/app.css and css/dasbhoard.css files. It's as if webpack.mix.js wasn't even employed.

public
├── css
│   └── vendor.css
├── favicon.ico
├── index.php
├── js
│   ├── app.js
│   ├── mix-manifest.json
│   └── vendor.js
├── mix-manifest.json
└── robots.txt

I AM sort-of successful when I do NOT use a custom webpack.config.js, and my webpack.mix.js looks like this:

const {mix} = require('laravel-mix');

mix.js('resources/assets/js/app.js', 'public/js')
   .sass('resources/assets/sass/app.scss', 'public/css')
   .sass('resources/assets/sass/dashboard.scss', 'public/css');

mix.combine([
    'resources/assets/vendor/bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css'
], 'public/css/vendor.css');


mix.js([
    'resources/assets/vendor/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js'
], 'public/js/vendor.js');

But now my vue and axios are compiled into app.js.

I have tried extracting vue and axios from app.js using:

mix.js('resources/assets/js/app.js', 'public/js')
    .extract(['vue'])
    .extract(['axios'])
;

But then the compile hangs at 76% basic chunk optimization and turns my macbook into a lap warmer.

So I suppose that my question is: How do I specify the output path for CSS files to be different than the JS files (as is configured using path.resolve(__dirname, 'public/js') in the mix.webpackConfig() method?.....while also keeping vue and axios out of app.js

Or, maybe instead: How do I add a non-npm-installed vendor package?

Which, by the way, I'm also still confused about how to include an npm-installed package (js, or otherwise), but that's a different topic.

I'd really appreciate any insights on this.

18th May, 2017

sanuglia started a new conversation How Would I Use JWT For "regular" Web Routes? • 6 months ago

Maybe I'm missing the point, but I believe that JWT can be used to send tokens along with "regular" Views. Is this not correct?

If not, then you can ignore the remainder of this.

If so, then I'm having difficulty understanding, or finding a good tutorial on how to do this. I mean, I'm finding tons of resources on how to implement JWT with an API, and they all end with sending a response of:

return Response::json(compact('token'));

Now, I've been able to implement JWT, and authenticate with curl/Postman, but I need my method to return a view:

return view('terms.index', compact('terms'));

Maybe the first step in understanding this would be a tutorial on how to use the existing Laravel 5.4 login form to authenticate using JWT, and then return the welcome view.

Could someone point me to a resource for this? Again, I'm NOT looking for another post on how to build an API. I'll keep searching in the meantime.

17th May, 2017

sanuglia left a reply on Getting False Positive Failures On Unique Fields • 6 months ago

EXCELLENT! Thanks so very much!

sanuglia started a new conversation Getting False Positive Failures On Unique Fields • 6 months ago

Perhaps the issue is more about my workflow setup, rather than the test itself.

See, I seed the terms table in my dev database to have data to work with something like:

'term'         => $faker->unique()->words($faker->numberBetween(1, 7), 1)

And I've been generating 500 records to get a good variety of values.

Next, I'm having gulp run phpunit on every file save, and with a somewhat surprising frequency, my can_create_term() fails with:

Integrity constraint violation: 1062 Duplicate entry 'aut' for key 'terms_term_unique'

For reference:

    use DatabaseTransactions;

    public function can_create_term() {
        // Given we don't already have a Term
        
        // When we create a Term
        $newTerm=factory('App\Components\Term\Term')->create();
        
        // Then the Term is in the database
        $gotTerm = Term::find($newTerm->id);

        $this->assertEquals(
            [
                $newTerm->term,
            ],
            [
                $gotTerm->term,
            ]
        );
    }

Now, I totally understand WHY this happens.

...And I can't really have the method delete, and then re-seed all of the data when its done because I have other tables that have an explicit foreign key to this table, so I'd have to destroy and re-seed those tables in the correct order when this test is done.

...And the problem with the delete/re-seed other tables is that it's going to take longer and longer for each test to execute as I keep adding new tables and necessary relationships to this table. (I think that I'm going to need to have about 5 related tables) What if I save the file twice before phpunit is done I wonder . . .

...And I save files often, triggering a test each time.

So for now, I've decreased the seeding to add only 25 records, and I'll see how often I run into these false errors. I know that'll ameliorate this a lot.

ON THE OTHER HAND, all I really need to do is to save the file again, which will trigger another test, generate a new (this time unique) record, and the test will pass. So this isn't a critical flaw; more of an annoyance.

My question then is: what might be a better strategy for setting up the test, or changing my workflow to account for these possible failures?

sanuglia left a reply on Laravel And X-editable, Ajax Not Being Validated • 6 months ago

Well, I should've KNOWN that if my validation setup didn't work using x-editable, it also wouldn't work using axios.

It appears that validation is done on a Request object, but when sending the array:

array:3 [▼
  "name" => "country"
  "value" => "foobarazilongword"
  "pk" => "1"
]

. . . via ajax, I'm not passing a Request object.

And indeed validation rules would be inherently difficult to implement for these single-field (i.e. UPDATE terms SET country= foobarazilongword where id=1) queries.

By that, I mean, even if I knew how to pass a Request object via ajax, a rule like this wouldn't be helpful:

                $this->validate($request, [
                    'term'       => 'required',
                    'country'    => 'required',
                    'assignedTo' => 'required',
                ]);

For if I want to update only the country field, I'd fail the validation because the term and assignedTo fields would be empty/non-existent.

So unless someone has ideas on how to efficiently validate fields for single-field updates before it hits the database, it looks like the alternative might be some sort of switch/case dealio and validate accordingly depending on which field gets sent through the method.

I'll post back with any updates or huge leaps of insight.

11th May, 2017

sanuglia left a reply on How Would I Get Blade To Display Values From Multiple Relations. • 7 months ago

I guess I wrote this too soon. This was a matter of

  1. Setting up the relationship in the migration
  2. Defining that relationship in the model, with a second argument
    public function user_assigned()
    {
        return $this->belongsTo(User::class,'assignedTo');
    }
  1. Using that relationship in the template:
<td>{{ $term->user_assigned->first_name}}</td>

sanuglia started a new conversation How Would I Get Blade To Display Values From Multiple Relations. • 7 months ago

Well, I'm not even sure where this question belongs, so please let me know if this isn't the place.

My Term model has fields similar to this:

$table->string('term');
$table->integer('reservedBy')->unsigned()->references('id')->on('users')->default(0);
$table->integer('assignedTo')->unsigned()->references('id')->on('users')->default(0);
$table->integer('recordedBy')->unsigned()->references('id')->on('users')->default(0);

// with about 5 other similar fields.

Right now, the index page shows userIDs for each of those fields, but I can't conjure up how to set this up so that it display the first_name in each of those fields.

I need more than a single relationship to the same users table, so would I do something along the lines of:

class Term extends Model
{
    /**
     * Get the user that reserved the term.
     */
    public function user_reserved()
    {
        return $this->belongsTo(Term::class);
    }
    /**
     * Get the user that is assigned for the term.
     */
    public function user_assigned()
    {
        return $this->belongsTo(Term::class);
    }
    // etc?

But then how do I specify that the user_assigned relationship references the assignedTo field?

Alternately, the other approach would be to send a mega-object of ALL the users to the template, but that sounds like it would be taxing the system.

    public function index(Term $term) {
        
        $users = \App\Auth\User::all();
        
        return view('terms.index', compact('term'))->with(compact('users'));
    }

But if that wasn't too taxing, I would think that I'd need some sort of lookup syntax in the template, something along the lines of:

<td> 
    @lookup $user->first_name where id = $term->updatedBy
</td>

I'll keep reading the docs, but if anyone could point me to a references that discusses this, I'd really appreciate any help!

sanuglia left a reply on Laravel And X-editable, Ajax Not Being Validated • 7 months ago

Actually . . . the example at https://vuejs.org/v2/examples/todomvc.html looks like it'll be close enough for me to make a go at using Vue for this project.

Still, I'd like to know what might have been causing the effects I described, if only for posterity.

10th May, 2017

sanuglia started a new conversation Laravel And X-editable, Ajax Not Being Validated • 7 months ago

Laravel 5.4.

I've managed to get x-editable (https://vitalets.github.io/x-editable/) to work with a page, in so far as when I click on a field, I get a popover, and I'm able to successfully submit to a PATCH URI. Also works with a POST.

The idea here is that I'm sending three key-value pairs:

array:3 [▼
  "name" => "country"
  "value" => "foobarazilongword"
  "pk" => "1"
]

and my updateField method catches the array, and it succesfully updates the record in the database.

But I'm failing to validate the data. I went so far as to require the field name being sent (ie 'country') to be required, and it errors out with "The country field is required."; which isn't correct because I did supply a value for the 'country' field.

   public function updateField(Request $request, $id) {
    
    //dd($request) // see result above

        if ($request->ajax()) {

            // Fails correctly, I'm not sending a 'body' field.
            $this->validate($request, [
                'body' => 'required',
            ]);

        // When submitting value 'foobarazilongword', it passes the validation. Yikes!
            $this->validate($request, [
                'country' => 'max:3',
            ]);

            // When passing its own field name to be required (ie 'country') it fails validation.
            // Responds with {"country":["The country field is required."]} But I just *sent* 
            // a value for 'country'!
            $this->validate($request, [
                $name => 'required',
            ]);


            $pk     = $request->get('pk');
            $name   = $request->get('name');
            $value  = $request->get('value');
            
            $term        = Term::findOrFail($id);
            $term->$name = $value;
            $term->save();
            
            return response()->json(['success' => TRUE]);
        }
        else {
            return 'Verbotten!';
        }
    }

So it's as if I'm somehow not passing the "correct" Request object to validate()? There is no form submission, but the documentation clearly states that "Laravel generates a JSON response containing all of the validation errors. This JSON response will be sent with a 422 HTTP status code."

Maybe I'm supposed to send something other than that array of 3 elements? But it's just ajax. . . what could be simpler?

And I do get a 422, when it fails the requirement of a value for a 'body' field. I'm just not getting it to validate the fields that are being sent.

Does anyone have a thought as to what might be going on here? I'd really appreciate any suggestions.

For reference:


Route::patch ('/terms/{term}/{fieldname}', '[email protected]');        // Update a specific field

<a href="#" id="country" >{{$term->country}}</a>
. . .


<script>
        $('#country').editable({
            ajaxOptions: {
                type: 'patch',
                dataType: 'json'
            },
            type: 'text',
            pk: '{{$term->id}}',
            url: '/terms/{{$term->id}}/country',
            title: 'Enter Country',
            success: function(response, newValue) {
                 return response.msg
            },
            error: function(response, newValue) {
                return response.msg
            },

        });

</script>

Maybe I'm going about this all wrong with using x-editable...I'd like to have "inline editing", and all of the js libs out there have been practically abandoned, so I'm open to any other suggestions; I've tried the gamut of what I've found on Google (jeditable, jinplace, etc.) with various degrees of success. x-editable has been the first to be documented well enough to make it work. And rolling out my own .vue version sounds like it'd be a bigger project than I have time for.

9th May, 2017

sanuglia left a reply on Migrated "boolean" Type, Checkbox Submits "on" Instead Of 1 • 7 months ago

Excellent! Thanks so very much!

sanuglia started a new conversation Migrated "boolean" Type, Checkbox Submits "on" Instead Of 1 • 7 months ago

In a Laravel 5.4 install, I created a migration with a boolean (turned tinyint(1)) field named "enabled".

$table->boolean ('enabled');

My "create new record" form has a checkbox:

<input type="checkbox" class="form-check-input" name="enabled" id="enabled"   />
                    Enabled

I would have expected the form to submit an integer 1, but instead it submits the string "on":

array:7 [▼
  "_token" => "vPW9k6xFelFzzAXefesxUqGZgBx7dFIMBVdKyE2s"
  "term" => "Another Term"
  "enabled" => "on"
]

Which naturally would fail an INSERT statement:

SQLSTATE[HY000]: General error: 1366 Incorrect integer value: 'on' for column 'enabled' at row 1 
``

Now, I could do something like:

$enabled=0; if (request('enabled') == 'on') $enabled=1;


... but that seems kinda hokey.  Surely there's a more elegant solution, but I haven't been able to find it.  Could someone please point me to a resource that discusses this or maybe provide what the solution might be?

13th April, 2017

sanuglia left a reply on Run Phpunit On Save • 8 months ago

nod thanks, ... yah, I saw that one, and that's a bit overkill with the BrowserSyncPlugin. But again, that was trying to make the square peg (phpunit) fit into the round hole (mix).

I'm running gulp now, and it does the job fine. I suppose that this question was more about: "what's any/everyone else doing if you want to run phpunit on save"?

12th April, 2017

sanuglia started a new conversation Run Phpunit On Save • 8 months ago

Elixir had a way to trigger phpunit (https://laravel.com/docs/5.0/elixir). Granted that was a while back. Now that Mix has assumed many of Elixir's functions, and that it's not planned to have a mix.phpunit() (https://github.com/JeffreyWay/laravel-mix/issues/531), what's the best practice of running phpunit on save?

Is it to go "back to" using gulp? I'd prefer to have fewer ancillary tools, but if that's what everyone's doing, I'll play.

4th April, 2017

sanuglia started a new conversation Index() Generates KEY Instead Of INDEX • 8 months ago

At first, I thought that this my be a 'mariadb thing', but the same thing happens in mysql.

According to the docs (https://laravel.com/docs/5.4/migrations), I should be able to add an index by using the index method. Specifically, my migration loos like:

            $table->unsignedInteger('accounts_id')->length(10);
            $table->unsignedInteger('clients_id')->length(10) ;
            $table->index('accounts_id','fk_accounts_has_clients_accounts1_idx');

Which works, buuuuut, when I take a look at that table, I see that it's been created as a KEY rather than an INDEX:


show create table accounts_has_clients;

...
CREATE TABLE `accounts_has_clients` (
  `accounts_id` int(10) unsigned NOT NULL,
  `clients_id` int(10) unsigned NOT NULL,
  KEY `fk_accounts_has_clients_accounts1_idx` (`accounts_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

Did I miss(read) something along the way? Any hints/thoughts would be helpful!

I have mysql 5.7.17, and mariadb 10.1.21, if that makes a difference.

Edit Your Profile
Update

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