Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
0zzyRocks
Jul 10, 2001

Lord of the broken bong

stoops posted:

I"m using the framework, CAKEPHP. I work on a dev environment. When its good to go, my boss pushes the pages up to production.

Sometimes, I'll make a database change (add a column, change a field type), and with these db changes, I have to tell my boss what to add to the production database.

Is there something I can use, or something php does, like a script, that will automatically update the db with my dev changes?

My boss said to look into "migration", but i couldn't really find anything.

It's a very small team, but I don't think we are using our environments as well as we should. I just want to make sure our "dev to production" can be an easier process.

Any help is appreciated.

Oh god, this was me like 4 years ago. It sucked. Newer versions of cake should have migrations built in, like Laravel and Magento do. This way the DB changes are version controlled with the rest of your code changes, and a simple script call on the command line activates them (Magento does part this automatically) or reverts them.

Adbot
ADBOT LOVES YOU

karms
Jan 22, 2006

by Nyc_Tattoo
Yam Slacker
If that's not possible you can getto it by creating .sql files and put those along side your code in your versioning system.

stoops
Jun 11, 2001


Thanks for the help. I started this job a couple years ago as a very novice php programmer and worked with Cake immediately since it was what they used.

I picked up on both php and the framework, and i think i'm comfortable with them, but I know Laravel is the most popular.

Would that be as easy to pick up as well?

We aren't married to Cake, but I just don't want to introduce something new and fall behind. But i guess just learning new stuff is always good.

revmoo
May 25, 2006

#basta
Laravel is pretty easy coming from cake. I recommend trying to find someone to teach you the ropes; the Laravel docs are crap.

Depressing Box
Jun 27, 2010

Half-price sideshow.
The Laravel From Scratch series on Laracasts is free. I haven't watched it yet, but Laracasts is usually pretty good quality.

poxin
Nov 16, 2003

Why yes... I am full of stars!
Definitely can recommend Laracasts, it's paid but $9 isn't terrible. Some of the best money I've spent in my opinion. They let you download the videos from the site and save them locally too without any hassle.

They have a decent amount of free videos.

Centripetal Horse
Nov 22, 2009

Fuck money, get GBS

This could have bought you a half a tank of gas, lmfao -
Love, gromdul

stoops posted:

I"m using the framework, CAKEPHP. I work on a dev environment. When its good to go, my boss pushes the pages up to production.

Sometimes, I'll make a database change (add a column, change a field type), and with these db changes, I have to tell my boss what to add to the production database.

Is there something I can use, or something php does, like a script, that will automatically update the db with my dev changes?

My boss said to look into "migration", but i couldn't really find anything.

It's a very small team, but I don't think we are using our environments as well as we should. I just want to make sure our "dev to production" can be an easier process.

Any help is appreciated.

http://www.sqitch.org

It's super simple, and works great. It's probably still got some growing to do, but I seriously doubt you're going to have any needs it can't handle.

Centripetal Horse fucked around with this message at 04:47 on Mar 11, 2016

Aniki
Mar 21, 2001

Wouldn't fit...
I am using Eloquent and I have two models Addresses and AddressType (e.g. Billing, Shipping, etc). Between those two models, I set up a 1 Address Type: Many Addresses relationship and I would like to run a command to get all of the fields from Address along with the type field from AddressType. If I use the query builder, then it would like something like this:

DB::table('addresses')->join('address_types','address_type_id','=','address_types.id')->select('addresses.*','address_types.type')->first();

However, this is a common enough scenario that I feel like I should be able to handle it using the models, so what would be the best way of approaching this?

For reference, this is the migration I am using to create those two tables:

php:
<?
public function up()
{
    Schema::create('address_types', function (Blueprint $table) {
        $table->increments('id')->unsigned();
        $table->string('type');
        $table->timestamps();
    });

    Schema::create('addresses', function (Blueprint $table) {
        $table->increments('id')->unsigned();
        $table->string('address1');
        $table->string('address2')->nullable();
        $table->string('city');
        $table->string('postal_code')->nullable();
        $table->string('state',2)->nullable();
        $table->string('country',2)->nullable();
        $table->integer('address_type_id')->unsigned();
        $table->foreign('address_type_id')->references('id')->on('address_types');
        // Polymorphic relationship so that I can reuse a single address table across
        // tables instead of having tables like company_addresses or customer_addresses
        // I do think the name could be confusing, since it is close to address_type,
        // which I hadn't noticed until now.
        $table->integer('addressable_id')->unsigned();
        $table->string('addressable_type');
        $table->timestamps();
    });
}
?>
Here is how I defined the relationships in the models:

php:
<?
// AddressType.php
public function addresses()
{
    return $this->hasMany(Address::class);
}

// Address.php
public function addressTypes()
{
    return $this->belongsTo(AddressType::class);
}
?>
I did seed these tables with test data and have been experimenting with them in Tinker. What I have noticed is that if I run these commands, then I can get a list of Addresses that are associated with the provided AddressType:

php:
<?
$addressType = App\AddressType::first();
$addressType->addresses->all();
?>

Then if I run these commands, I would expect it to give me the associated type record for the provided address, but instead it returns null. I know this is slightly different than the question I was asking, but it was part of my process of trying to work towards getting the same/similar result to the query I listed at the start:

php:
<?
$address = App\Address::first();
$address->addressTypes->all();
?>
I feel like this should be simple, but I'm obviously missing something here.

Depressing Box
Jun 27, 2010

Half-price sideshow.
Laravel's automatic column name guesser is seeing your addressTypes (plural) method and looking for an address_types_id field. If you change the method name to addressType:

php:
<?
public function addressType()
{
    return $this->belongsTo(AddressType::class);
}
?>
or manually specify the foreign key:

php:
<?
public function addressTypes()
{
    return $this->belongsTo(AddressType::class, 'address_type_id');
}
?>
it'll start working. Also, the belongsTo relationship only returns a single record, so you only need to use $address->addressType.

Depressing Box fucked around with this message at 23:05 on Mar 11, 2016

bigmandan
Sep 11, 2001

lol internet
College Slice
Since an address only has one type, it would seem more correct to change the method name to be singular as it better represents what is actually happening.

Depressing Box
Jun 27, 2010

Half-price sideshow.

bigmandan posted:

Since an address only has one type, it would seem more correct to change the method name to be singular as it better represents what is actually happening.

Agreed, the second example is more to show what Laravel is doing internally, and provide a workaround if there's some reason you can't change the method's name.

Aniki
Mar 21, 2001

Wouldn't fit...

Depressing Box posted:

Agreed, the second example is more to show what Laravel is doing internally, and provide a workaround if there's some reason you can't change the method's name.

Both methods worked, I do agree that going with addressType, since it is returning a singular value makes more sense as a naming convention. I had just been naming all of my functions in models as plural, which makes sense most of the time.

Another odd thing that I noticed is that when I pull an address record, it does not include the foreign key (address_type_id):

code:
// Expected to see address_type_id: 1
>>> $address = App\Address::first();
=> App\Address {#725
     address1: "8097 Casper Lodge",
     address2: "Apt. 053",
     city: "New Desireemouth",
     postal_code: "66855-4852",
     state: "IL",
     country: "US",
     created_at: "2016-03-11 21:18:12",
     updated_at: "2016-03-11 21:18:12",
   }
That just seems odd to me, since I thought foreign keys would be returned like any other row.

Changing topics slightly, if I want to get a dataset that involves a join, like getting the address fields along with type (from address_types), then I can use the query builder:

php:
<?
DB::table('addresses')->join('address_types','address_type_id','=','address_types.id')->select('addresses.*','address_types.type')->first();
?>
Or I can do a half model/half query builder like this:

php:
<?
App\Address::join('address_types', 'addresses.address_type_id','=','address_types.id')->first();
?>
But is there another way that I should approach, where I leverage the relationships I created in the models or is that not what models are for? The last time I used Eloquent for something like this, I used the query builder heavily and now I am trying to pull data from models as much as possible. Admittedly, more as a learning experience than for practical purposes.

Aniki fucked around with this message at 23:58 on Mar 11, 2016

Depressing Box
Jun 27, 2010

Half-price sideshow.

Aniki posted:

Another odd thing that I noticed is that when I pull an address record, it does not include the foreign key (address_type_id)

What else is in your model? Here's my model and result:

php:
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Address extends Model
{
    public function addressType()
    {
        return $this->belongsTo(AddressType::class);
    }
}

code:
>>> $address = App\Address::first();
=> App\Address {#630
     id: 1,
     address1: "Foo",
     address2: null,
     city: "",
     postal_code: null,
     state: null,
     country: null,
     address_type_id: 1,
     addressable_id: 0,
     addressable_type: "",
     created_at: "2016-03-11 18:46:20",
     updated_at: "2016-03-11 18:46:20",
   }
It seems like something is hiding fields.

Aniki posted:

Changing topics slightly, if I want to get a dataset that involves a join, like getting the address fields along with type (from address_types), then I can use the query builder:

[ . . . ]

But is there another way that I should approach, where I leverage the relationships I created in the models or is that not what models are for? The last time I used Eloquent for something like this, I used the query builder heavily and now I am trying to pull data from models as much as possible. Admittedly, more as a learning experience than for practical purposes.

If you just want the relationship as-is, you could eager load it:

code:
>>> $address = App\Address::with('addressType')->first();
=> App\Address {#653
     id: 1,
     address1: "Foo",
     [...]
     created_at: "2016-03-11 18:46:20",
     updated_at: "2016-03-11 18:46:20",
     addressType: App\AddressType {#660
       id: 1,
       type: "Billing",
       created_at: "2016-03-11 23:34:12",
       updated_at: "2016-03-11 23:34:12",
     },
   }
If you want it "aliased" to a different property, add an accessor to the model:

php:
<?
public function getTypeAttribute()
{
    return $this->addressType ? $this->addressType->type : null;
}
?>
code:
>>> $address = App\Address::first();
>>> $address->type;
=> "Billing"

Depressing Box fucked around with this message at 01:08 on Mar 12, 2016

Aniki
Mar 21, 2001

Wouldn't fit...

Depressing Box posted:

What else is in your model? Here's my model and result:

php:
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Address extends Model
{
    public function addressType()
    {
        return $this->belongsTo(AddressType::class);
    }
}

code:
>>> $address = App\Address::first();
=> App\Address {#630
     id: 1,
     address1: "Foo",
     address2: null,
     city: "",
     postal_code: null,
     state: null,
     country: null,
     address_type_id: 1,
     addressable_id: 0,
     addressable_type: "",
     created_at: "2016-03-11 18:46:20",
     updated_at: "2016-03-11 18:46:20",
   }
It seems like something is hiding fields.


If you just want the relationship as-is, you could eager load it:

code:
>>> $address = App\Address::with('addressType')->first();
=> App\Address {#653
     id: 1,
     address1: "Foo",
     [...]
     created_at: "2016-03-11 18:46:20",
     updated_at: "2016-03-11 18:46:20",
     addressType: App\AddressType {#660
       id: 1,
       type: "Billing",
       created_at: "2016-03-11 23:34:12",
       updated_at: "2016-03-11 23:34:12",
     },
   }
If you want it "aliased" to a different property, add an accessor to the model:

php:
<?
public function getTypeAttribute()
{
    return $this->addressType ? $this->addressType->type : null;
}
?>
code:
>>> $address = App\Address::first();
>>> $address->type;
=> "Billing"

Yeah, you are right. I had defined hidden fields, but had forgotten about it. Those two methods of setting up joins look good, I'll test them out tonight. Thank you, I really appreciate the help.

Experto Crede
Aug 19, 2008

Keep on Truckin'
I'm starting a new project which will basically aggregate data from various APIs, store it in the database and then combine it into a PDF for the user to download.

I've never used a framework before but thought this was as good a time to learn about it. What would the general recommendation be for a framework that is good from a user friendliness/beginner's perspective? I know based on previous discussion that Zend is basically out, but I'm open to input!

Depressing Box
Jun 27, 2010

Half-price sideshow.

Experto Crede posted:

I'm starting a new project which will basically aggregate data from various APIs, store it in the database and then combine it into a PDF for the user to download.

I've never used a framework before but thought this was as good a time to learn about it. What would the general recommendation be for a framework that is good from a user friendliness/beginner's perspective? I know based on previous discussion that Zend is basically out, but I'm open to input!

For a user-friendly framework I'd recommend Laravel (though I also don't have a ton of experience with other frameworks, so anyone else feel free to weigh in). From having written several sync systems, I can say aggregating API data should be pretty straightforward in Laravel, and there are a few good Composer packages out there for generating PDFs.

Depressing Box fucked around with this message at 21:41 on Mar 14, 2016

v1nce
Sep 19, 2004

Plant your brassicas in may and cover them in mulch.

Experto Crede posted:

I've never used a framework before
Seconding Laravel. Unless you have a Java background you won't be comfortable in Symfony or Zend's "enterprise" scale, especially not if frameworks are a new thing for you. With Laravel a lot of people here can give you advice.

DarkLotus
Sep 30, 2001

Lithium Hosting
Personal, Reseller & VPS Hosting
30-day no risk Free Trial &
90-days Money Back Guarantee!
I have a Laravel app and want to send data to a couple of remote webservers (also on Laravel 5.2) when a user updates a form.
I was thinking of using a message queue or service but also thought I could essentially create a webhook and post data using a stateless api / token setup.

Is there a better or preferred way to immediately share data updates from one laravel app to another when they don't share any infrastructure or services?
If it matters, the data will be used to update a local cache on the remote servers.

v1nce
Sep 19, 2004

Plant your brassicas in may and cover them in mulch.

DarkLotus posted:

Is there a better or preferred way to immediately share data updates from one laravel app to another when they don't share any infrastructure or services?
If it matters, the data will be used to update a local cache on the remote servers.

I don't see any specific problem with that technique. You can use something like JWT (Laravel tutorial) to verify the update payload with a shared secret between your servers.

You can either have the clients request an update from the master server periodically (cron) which may end up making redundant requests, or you can push the update from the master to the clients when changes are made. If you're pushing, I'd recommend to back it with a queue, like you said.

I'm interested to see if anyone else has an opinion on this.

Blinkz0rz
May 27, 2001

MY CONTEMPT FOR MY OWN EMPLOYEES IS ONLY MATCHED BY MY LOVE FOR TOM BRADY'S SWEATY MAGA BALLS

DarkLotus posted:

I have a Laravel app and want to send data to a couple of remote webservers (also on Laravel 5.2) when a user updates a form.
I was thinking of using a message queue or service but also thought I could essentially create a webhook and post data using a stateless api / token setup.

Is there a better or preferred way to immediately share data updates from one laravel app to another when they don't share any infrastructure or services?
If it matters, the data will be used to update a local cache on the remote servers.

A message queue for sure. What you're talking about is the archetype pub/sub pattern.

DarkLotus
Sep 30, 2001

Lithium Hosting
Personal, Reseller & VPS Hosting
30-day no risk Free Trial &
90-days Money Back Guarantee!

v1nce posted:

I don't see any specific problem with that technique. You can use something like JWT (Laravel tutorial) to verify the update payload with a shared secret between your servers.

You can either have the clients request an update from the master server periodically (cron) which may end up making redundant requests, or you can push the update from the master to the clients when changes are made. If you're pushing, I'd recommend to back it with a queue, like you said.

I'm interested to see if anyone else has an opinion on this.


Blinkz0rz posted:

A message queue for sure. What you're talking about is the archetype pub/sub pattern.

Thanks guys, this is for something new I've been working on and have been trying plan the implementation of a new feature.
It helps to hear that I was on the right track ;)

DarkLotus
Sep 30, 2001

Lithium Hosting
Personal, Reseller & VPS Hosting
30-day no risk Free Trial &
90-days Money Back Guarantee!
I want to validate a FQDN, not a URL, so FILTER_VAR doesn't work for me.
code:
[url]www.domain.com[/url]
domain.com
53dw4vbsf3yf53nnc7yq7fijlp7ymnbx.dkim.amazonses.com
53dw4vbsf3yf53nnc7yq7fijlp7ymnbx._domainkey.domain.com (damnit amazon, underscores are not part of RFC1035)
All should be valid.

I can't seem to find a good working regex that works with php and javascript that simply verifies that the following rules are met:

Total string length is 1-255 characters
each label is 1-63 characters
The final label is at least 2 characters (the TLD)
cannot begin or end with a dash

This is for DNS management, so I just want to be sure the FQDN is properly formatted.

Any regex experts care to provide some insight?

I have the following examples that don't offer the full coverage I need.

This one works well for some but not all.
code:
function validateFqdn($value)
{
    return (preg_match('/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i', $value) //valid chars check
        && preg_match('/^.{1,255}$/', $value) //overall length check
        && preg_match('/^[^\.]{1,63}(\.[^\.]{1,63})*$/', $value)); //length of each label
}
This one works great for 3 or less labels, but as we all know, some FQDNs consist of many labels and should be considered valid as long as the length is less than 255.
code:
^((?!-))(xn--)?[a-z0-9][a-z0-9-_]{0,63}[a-z0-9]{0,1}\.(xn--)?([a-z0-9\-]{1,63}|[a-z0-9-]{1,32}\.[a-z]{2,})$
Please note, I am not trying to validate the TLD, I just want to focus on the total length, label length and allowed characters.

DarkLotus fucked around with this message at 03:40 on Mar 22, 2016

v1nce
Sep 19, 2004

Plant your brassicas in may and cover them in mulch.
I was going to suggest you just prepend 'http://' to your domain and use filter_var, but on closer inspection, filter_validate_url is a massive piece of poo poo:

code:
$x = [
    'm',
    'my',
    'my.example.com',
    '://my.example.com',
    'http://my.example.com',
    'x://my.example.com',
    'x://my',
    'x://m',
    '1://1'
];

foreach($x as $y) {
    echo "\n".filter_var($y, FILTER_VALIDATE_URL);
}

// 
//
//
//
// http://my.example.com
// x://my.example.com
// x://my
// x://m
// 1://1
It's supposed to validate against the format specified in RFC2396, and unless I'm mistaken 1://1 isn't a valid anything.

Anyway, back to regex. How about this:
code:
^(?:([[:alnum:]_]{1,63})\.)*(?:[[:alpha:]][[:alnum:]]{1,63})(?:\.[[:alpha:]]{1,63})+$
Exploded version:
code:
^(?:([[:alnum:]_]{1,63})\.)*         // Subdomain: Any alphanumeric. Length 1-63. Repeat 0-infinity times.
(?:[[:alpha:]][[:alnum:]]{1,62})     // Domain: Must start with alpha character, then alphanum thereafter (1-62 chars). Required once.
(?:\.[[:alpha:]]{1,63})+$            // TLD: Match 1-63 occurrences of alpha. Must match at least once.
Regex101 Link for testing

Probably needs refining, but it worked for your examples.
Also, try to do that full-length check with strlen() not regex.

Edit: Alright so I missed a bunch of valid characters, but it's my lunch break.
https://regex101.com/r/bP2jX5/2

Edit2: Added the length check, because why not:
https://regex101.com/r/bP2jX5/3

v1nce fucked around with this message at 05:32 on Mar 22, 2016

DarkLotus
Sep 30, 2001

Lithium Hosting
Personal, Reseller & VPS Hosting
30-day no risk Free Trial &
90-days Money Back Guarantee!
Thanks v1nce, I'll try them out in the morning.
As for the examples I provided, they are likely from stackoverflow or some place so I can't take credit for checking string length with regex :q:

Heskie
Aug 10, 2002
Would parse_url help you do what you'd want? I've used it before when implementing a custom router/dispatcher and validating requests etc.

DarkLotus
Sep 30, 2001

Lithium Hosting
Personal, Reseller & VPS Hosting
30-day no risk Free Trial &
90-days Money Back Guarantee!
v1nce, almost there.
Seems to allow a hyphen as a first character, also doesn't validate a.com
While it's unlikely I'll see that domain in the DNS manager, I'd still like to support it.

Add these to your test strings

-0-0O.COM
0-0O_.COM
a.net
-a.dot
0-0O.COM
0-OZ.CO.uk
0-TENSION.COM.br
0-WH-AO14-0.COM-com.net
a-1234567890-1234567890-1234567890-1234567890-1234567890-1234-z.eu.us
a-1234567890-1234567890-1234567890-1234567890-1234567890-12345-z.eu.us


What would the regex look like if I just wanted to validate the actual domain name (for a different input)?
domain.co.uk
domain.co
domain.us
a.co
b.net
b.co.uk

Just to clarify what all this is for. I'm completely revamping and rebranding https://wtfdns.com to https://lidns.net and have completely redone the interface and rewritten the entire codebase.
I want to add some frontend validation via javascript and then validate it on the backend.
I hope to go live with the new site in the next few weeks but need to fix some validation issues I'm having.

DarkLotus
Sep 30, 2001

Lithium Hosting
Personal, Reseller & VPS Hosting
30-day no risk Free Trial &
90-days Money Back Guarantee!

Heskie posted:

Would parse_url help you do what you'd want? I've used it before when implementing a custom router/dispatcher and validating requests etc.

I considered parse_url, but it's been a while since I tested it and decided against it so I can't really tell you why...
Also, it can't help with client-side validation like this:
code:
<input class="form-control rec-data" required="required" name="data[en6i4q]" type="text" 
value="nqlhowgckr7lckd4d35simmflrksy2ep.dkim.amazonses.com" 
pattern="^(?=(?:(?:([a-z0-9_-]{1,63}).)*(?:[a-z0-9-]{2,63})(?:.[a-z0-9]{2,63})+)).{3,255}$" 
title="Please enter a valid Hostname">
A reusable regex that works with javascript, html5 and php seems like a win-win for me.

v1nce
Sep 19, 2004

Plant your brassicas in may and cover them in mulch.

Heskie posted:

Would parse_url help you do what you'd want? I've used it before when implementing a custom router/dispatcher and validating requests etc.

It looks like parse_url is equally dumb as filter_validate_url; it'll happily split the string and return whatever is in the "domain" portion, without following the rules about what is and isn't actually a host. Great for validating string structure, rubbish for validating it's a domain.

For example:
code:
var_dump(parse_url('http://&', PHP_URL_HOST));
// string(1) "&"

DarkLotus posted:

Seems to allow a hyphen as a first character, also doesn't validate a.com
I want to add some frontend validation via javascript and then validate it on the backend.
I know where you got that test data :v:

On the front-end you probably want to use a loose regex just to ensure the formatting is vaguely within the RFCs (952, 1123).
On the backend you can do some harder checking. Most people would use checkdnsrr() if they wanted to ensure the domain existed; but if you're using this in the context of establishing DNS.. that's a bit more difficult.

We're also forgetting about Internationalised Domain Names (IDN) (RFC 3492) with this regex. These are unicode in user-land, but punycode in DNS-land. See all the "XN" entries in the iana.org TLD list.

We've assumed so far that users might be inputting crap, so we should probably assume they're expecting to input the unicode TLD, which our regex would reject. Even with the "loose" regex I linked, which is a favourite of stackoverflow, it rejects both punycode and unicode IDN TLDs.

Ignoring the regex, on the PHP side you can use idn_to_ascii() to convert all elements in the URL to punycode, but again, this does no validation.

DarkLotus posted:

What would the regex look like if I just wanted to validate the actual domain name (for a different input)?
Are you talking, like, validate it's a domain, and strip subdomains? That's pretty tricky, because:
police.uk is a valid domain, (.uk TLD)
college.police.uk is a valid domain (.police.uk is the TLD).

I'm pretty sure there's got to be some rule in the RFC about parse order and TLDs, but I haven't been over the rules that strongly.
Presumably, you'd need to match right-to-left from the TLD (eg .com - or any registered TLD) until you either encounter a string which isn't a TLD, or use the last item when there's more than one TLD in the string. The last item you find would be the domain.

For instance:
police.uk would resolve to {domain:police tld:uk}. Two TLDs were found, so the second one "police" is the domain.
college.police.uk would resolve to {domain:college tld:police.uk} because it found a non-TLD name.
uk would be invalid, because it only found the one TLD.

Now, I'm pretty sure "police.uk" could have a subdomain of "college." which would cause a conflict in DNS, so I don't know what the gently caress.
You might want to take a look at the Mozilla TLD list which includes all the nth-level TLDs that the iana list omits. There's also the PublicSuffix.org effective TLD list which is more machine-readable and explicit.

I'd suggest you come up with a group of "expected pass" and "expected fail" strings. Consider everything in the TLD list, and how you want to handle user input of IDNs. We can fix the regex later.

Edit: The problem is; if ICANN are maintaining a list of valid TLD then there's no simple regex which can tell you if a domain string is valid, invalid, a domain or a subdomain. If they're using a list, then you have to parse against a list. You can use regex to say "yes that kinda looks like a domain", but it would still need to be backed by some much stronger parsing mechanism.

v1nce fucked around with this message at 00:54 on Mar 23, 2016

MrMoo
Sep 14, 2000

ha, I still see my domain 見.香港 listed in many articles on domain validation, also GitHub bugs.

It would be a HTTPS site, but surprise surprise Let's Encrypt have problems validating puny code domains.

Impotence
Nov 8, 2010
Lipstick Apathy
http://to/ is valid too!

DarkLotus
Sep 30, 2001

Lithium Hosting
Personal, Reseller & VPS Hosting
30-day no risk Free Trial &
90-days Money Back Guarantee!
drat v1nce, thorough post.

Forget about the domain only validation, I am already using a PSL validator in my code for that. Just thought Regex would be faster but for obvious reasons it's not.

What are your suggestions for the client-side loose validation?
Obviously on the server side I can convert IDN to Punycode and validate the xn-- domain instead.

By allowing hyphens in the labels, punycode will validate with a backend check.

Can you fix the other regex for the following? My regex skills are weak, and I don't need to use regex enough to spend time learning :( I appreciate your help!
https://regex101.com/r/bP2jX5/2

-0-0O.COM [FAIL]
0-0O_.COM [FAIL]
a.net [PASS]
-a.dot [FAIL]
0-0O.COM [PASS]
0-OZ.CO.uk [PASS]
0-TENSION.COM.br [PASS]
0-WH-AO14-0.COM-com.net [PASS]
a-1234567890-1234567890-1234567890-1234567890-1234567890-1234-z.eu.us [PASS]
a-1234567890-1234567890-1234567890-1234567890-1234567890-12345-z.eu.us [FAIL]
xn--nw2a.xn--j6w193g [PASS] ;)

DarkLotus fucked around with this message at 01:41 on Mar 23, 2016

v1nce
Sep 19, 2004

Plant your brassicas in may and cover them in mulch.
Edit: Moving the goalposts ^^ :bahgawd:


There's a lot that's valid for DNS, but I think we're talking strictly in terms of TLD and internet DNS ;)

http://a.com is technically valid, but nobody allows registration of single-character domains, so for the purposes of internet DNS it should probably be considered ~invalid~.

DarkLotus posted:

0-0O.COM [FAIL]
I think this was a mistake?

https://regex101.com/r/bP2jX5/4
https://regex101.com/r/bP2jX5/5
Notice the extra u modifier to make alnum match unicode characters.

v1nce fucked around with this message at 01:41 on Mar 23, 2016

DarkLotus
Sep 30, 2001

Lithium Hosting
Personal, Reseller & VPS Hosting
30-day no risk Free Trial &
90-days Money Back Guarantee!

v1nce posted:

Edit: Moving the goalposts ^^ :bahgawd:


There's a lot that's valid for DNS, but I think we're talking strictly in terms of TLD and internet DNS ;)

http://a.com is technically valid, but nobody allows registration of single-character domains, so for the purposes of internet DNS it should probably be considered ~invalid~.

I think this was a mistake?

https://regex101.com/r/bP2jX5/4
https://regex101.com/r/bP2jX5/5
Notice the extra u modifier to make alnum match unicode characters.

Derp!!! Yes, 0-0O.COM is valid.

As for all of this regex business. Absolutely none of it relates to registration. Strictly DNS management.
I might be going a little nuts on this, but I really want to prevent bad DNS records from being in the system.

Also, with the regex, I was having issues with the POSIX expressions in my input validation, is it possible to stick with the [a-z0-9] ???

Impotence
Nov 8, 2010
Lipstick Apathy

v1nce posted:

Edit: Moving the goalposts ^^ :bahgawd:


There's a lot that's valid for DNS, but I think we're talking strictly in terms of TLD and internet DNS ;)

http://a.com is technically valid, but nobody allows registration of single-character domains, so for the purposes of internet DNS it should probably be considered ~invalid~.

I think this was a mistake?

https://regex101.com/r/bP2jX5/4
https://regex101.com/r/bP2jX5/5
Notice the extra u modifier to make alnum match unicode characters.



tk has address 217.119.57.22
cf mail is handled by 0 mail.intnet.cf.
to has address 216.74.32.107
x.com has address 192.69.184.181
x.org has address 131.252.210.176
z.com has address 157.7.94.53
z.com mail is handled by 10 mx.z.com.
q.com has address 155.70.28.140
q.com mail is handled by 10 mx.quartz.synacor.com.
-.ph has address 45.79.222.138
___.ph has address 45.79.222.138
_-_.ws has address 64.70.19.202
-0.ws mail is handled by 1 mail.hope-mail.com.


:v:

e: there's also a ton of single-character domains on the newer trashy cash in tlds; they can also be single numbers.

Impotence fucked around with this message at 02:17 on Mar 23, 2016

v1nce
Sep 19, 2004

Plant your brassicas in may and cover them in mulch.

DarkLotus posted:

Also, with the regex, I was having issues with the POSIX expressions in my input validation, is it possible to stick with the [a-z0-9] ???

What's giving you jip, javascript? Unicode support is coming with ECMAScript6 but until then you're kinda screwed.

If you know the valid URI unicode ranges, you can use this regexp unicode block generator to get the unicode ranges that'll work with regular JS, and replace the broad ranges in here:
code:
var x = RegExp('^(?:([\u0000-\uFFFF_-]{1,63})\.)*(?:[\u0000-\uFFFF][\u0000-\uFFFF-]{0,62})(?:\.[\u0000-\uFFFF-]{2,63})+$', 'gi');
x.exec('unicode-domain-goes.here');
Or you can just stick with \\w for straight ascii:
code:
var x = RegExp('^(?:([\\w-]{1,63})\.)*(?:[\\w][\\w-]{0,62})(?:\.[\\w-]{2,63})+$', 'gi');
x.exec('abc.com');

Biowarfare posted:

to has address 216.74.32.107
x.com has address 192.69.184.181
x.org has address 131.252.210.176

Huh. mxtoolbox can see it

code:
nslookup to 208.67.222.222
Server:  resolver1.opendns.com
Address:  208.67.222.222

*** resolver1.opendns.com can't find to: Non-existent domain
But why can't I? :confused:

Impotence
Nov 8, 2010
Lipstick Apathy
edited post with some more examples of things that are actually live on the internet because real life

(also worksforme)

>nslookup to. 208.67.222.222
Server: resolver1.opendns.com
Address: 208.67.222.222

Non-authoritative answer:
Name: to
Address: 216.74.32.107

MrMoo
Sep 14, 2000

Wasn't there someone wanting to formalize plain TLDs with a dot like http://.to/ ?

v1nce
Sep 19, 2004

Plant your brassicas in may and cover them in mulch.

Biowarfare posted:


>nslookup to. 208.67.222.222

That's it. The "." on the end. Also: http://to./

Edit: https://regex101.com/r/bP2jX5/6 :eng99:

v1nce fucked around with this message at 02:59 on Mar 23, 2016

DarkLotus
Sep 30, 2001

Lithium Hosting
Personal, Reseller & VPS Hosting
30-day no risk Free Trial &
90-days Money Back Guarantee!

v1nce posted:

That's it. The "." on the end. Also: http://to./

Edit: https://regex101.com/r/bP2jX5/6 :eng99:

Looks good man, that's going to cover 99% of my use cases.

IDN will be converted to punycode before validation on the backend.

What's the trick to getting that to work in the <input pattern=""> attribute?
https://www.w3.org/TR/html5/forms.html#the-pattern-attribute

This is just an attempt to catch errors on the front-end before performing a full validation on the back-end.

Adbot
ADBOT LOVES YOU

v1nce
Sep 19, 2004

Plant your brassicas in may and cover them in mulch.

DarkLotus posted:

What's the trick to getting that to work in the <input pattern=""> attribute?
https://www.w3.org/TR/html5/forms.html#the-pattern-attribute

Support looks a bit sketchy for Safari and may not do exactly what you want. Wrapping it up in some JavaScript should be a more catch-all fix.

Maybe something like this (html5)?

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply