├── .gitignore ├── License.md ├── README.md ├── composer.json ├── composer.lock └── src ├── PhoneValidatorServiceProvider.php ├── TwilioCredentialsNotFoundException.php ├── config └── twilio.php └── lang └── en └── validation.php /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2016 Stuart Yamartino. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lavarel Phone Validator 2 | [![Packagist](https://img.shields.io/packagist/v/stuyam/laravel-phone-validator.svg)](https://packagist.org/packages/stuyam/laravel-phone-validator) 3 | [![Packagist](https://img.shields.io/packagist/dt/stuyam/laravel-phone-validator.svg)](https://packagist.org/packages/stuyam/laravel-phone-validator) 4 | 5 | A phone validator for Laravel using the FREE [Twilio phone lookup service](https://www.twilio.com/lookup) 6 | 7 | This custom validator validates that a phone number actual exists. Not just if it has a specific format or not, but if the phone number is a real registered phone number. It is smart enough to handle formated numbers like ```(123)-555-1234``` and unfromated numbers like ```1235551234``` so users can enter in a phone number however they are most comfortable. 8 | 9 | For a working example check out [Laravel Validator Example](https://github.com/stuyam/validators) project. 10 | 11 | Also see: [Laravel Kickbox Validator](https://github.com/stuyam/laravel-kickbox-validator) for email address validation. 12 | 13 | ### Step 1 14 | Install via composer: 15 | 16 | ``` 17 | composer require stuyam/laravel-phone-validator 18 | ``` 19 | 20 | ### Step 2 21 | Add to your ```config/app.php``` service provider list: 22 | 23 | ```php 24 | StuYam\PhoneValidator\PhoneValidatorServiceProvider::class 25 | ``` 26 | 27 | ### Step 3 28 | Add Twilio credentials to your .env file: 29 | 30 | (If you don't have a Twilio account you can go to [Twilio.com](https://www.twilio.com/) and make a free account) 31 | 32 | ``` 33 | TWILIO_SID=xxxxxxxx 34 | TWILIO_TOKEN=xxxxxxxx 35 | ``` 36 | 37 | 38 | ### Usage 39 | Add the string 'phone' to a form request rules or validator like so: 40 | 41 | ```php 42 | 'required|phone' 71 | ]; 72 | } 73 | } 74 | 75 | ``` 76 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stuyam/laravel-phone-validator", 3 | "description": "A phone validator for Laravel using the free Twilio phone lookup service.", 4 | "license": "MIT", 5 | "keywords": ["laravel", "phone", "twilio", "validator", "validation"], 6 | "authors": [ 7 | { 8 | "name": "Stuart Yamartino", 9 | "email": "stuartyamartino@gmail.com" 10 | } 11 | ], 12 | "minimum-stability": "dev", 13 | "require": { 14 | "illuminate/support": "^5.0|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", 15 | "twilio/sdk": "^5.0|^6.0|^7.0|^8.0" 16 | }, 17 | "autoload": { 18 | "psr-4": { 19 | "StuYam\\PhoneValidator\\": "src/" 20 | } 21 | }, 22 | "extra": { 23 | "laravel": { 24 | "providers": [ 25 | "StuYam\\PhoneValidator\\PhoneValidatorServiceProvider" 26 | ] 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "f3e894b6726cd4161f52bc87d0490b0b", 8 | "packages": [ 9 | { 10 | "name": "doctrine/inflector", 11 | "version": "dev-master", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/doctrine/inflector.git", 15 | "reference": "f2b6085fd68477a148e945dc5e1a0494ae6984a6" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/doctrine/inflector/zipball/f2b6085fd68477a148e945dc5e1a0494ae6984a6", 20 | "reference": "f2b6085fd68477a148e945dc5e1a0494ae6984a6", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": "^7.2 || ^8.0" 25 | }, 26 | "require-dev": { 27 | "doctrine/coding-standard": "^7.0", 28 | "phpstan/phpstan": "^0.11", 29 | "phpstan/phpstan-phpunit": "^0.11", 30 | "phpstan/phpstan-strict-rules": "^0.11", 31 | "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" 32 | }, 33 | "type": "library", 34 | "extra": { 35 | "branch-alias": { 36 | "dev-master": "2.1.x-dev" 37 | } 38 | }, 39 | "autoload": { 40 | "psr-4": { 41 | "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" 42 | } 43 | }, 44 | "notification-url": "https://packagist.org/downloads/", 45 | "license": [ 46 | "MIT" 47 | ], 48 | "authors": [ 49 | { 50 | "name": "Guilherme Blanco", 51 | "email": "guilhermeblanco@gmail.com" 52 | }, 53 | { 54 | "name": "Roman Borschel", 55 | "email": "roman@code-factory.org" 56 | }, 57 | { 58 | "name": "Benjamin Eberlei", 59 | "email": "kontakt@beberlei.de" 60 | }, 61 | { 62 | "name": "Jonathan Wage", 63 | "email": "jonwage@gmail.com" 64 | }, 65 | { 66 | "name": "Johannes Schmitt", 67 | "email": "schmittjoh@gmail.com" 68 | } 69 | ], 70 | "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", 71 | "homepage": "https://www.doctrine-project.org/projects/inflector.html", 72 | "keywords": [ 73 | "inflection", 74 | "inflector", 75 | "lowercase", 76 | "manipulation", 77 | "php", 78 | "plural", 79 | "singular", 80 | "strings", 81 | "uppercase", 82 | "words" 83 | ], 84 | "funding": [ 85 | { 86 | "url": "https://www.doctrine-project.org/sponsorship.html", 87 | "type": "custom" 88 | }, 89 | { 90 | "url": "https://www.patreon.com/phpdoctrine", 91 | "type": "patreon" 92 | }, 93 | { 94 | "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", 95 | "type": "tidelift" 96 | } 97 | ], 98 | "time": "2020-09-06T15:21:47+00:00" 99 | }, 100 | { 101 | "name": "illuminate/collections", 102 | "version": "8.x-dev", 103 | "source": { 104 | "type": "git", 105 | "url": "https://github.com/illuminate/collections.git", 106 | "reference": "28957388487b675b730ed8cb4e5f8ee5cd4b4d1d" 107 | }, 108 | "dist": { 109 | "type": "zip", 110 | "url": "https://api.github.com/repos/illuminate/collections/zipball/28957388487b675b730ed8cb4e5f8ee5cd4b4d1d", 111 | "reference": "28957388487b675b730ed8cb4e5f8ee5cd4b4d1d", 112 | "shasum": "" 113 | }, 114 | "require": { 115 | "illuminate/contracts": "^8.0", 116 | "illuminate/macroable": "^8.0", 117 | "php": "^7.3" 118 | }, 119 | "suggest": { 120 | "symfony/var-dumper": "Required to use the dump method (^5.1)." 121 | }, 122 | "type": "library", 123 | "extra": { 124 | "branch-alias": { 125 | "dev-master": "8.x-dev" 126 | } 127 | }, 128 | "autoload": { 129 | "psr-4": { 130 | "Illuminate\\Support\\": "" 131 | }, 132 | "files": [ 133 | "helpers.php" 134 | ] 135 | }, 136 | "notification-url": "https://packagist.org/downloads/", 137 | "license": [ 138 | "MIT" 139 | ], 140 | "authors": [ 141 | { 142 | "name": "Taylor Otwell", 143 | "email": "taylor@laravel.com" 144 | } 145 | ], 146 | "description": "The Illuminate Collections package.", 147 | "homepage": "https://laravel.com", 148 | "time": "2020-09-12T21:29:53+00:00" 149 | }, 150 | { 151 | "name": "illuminate/contracts", 152 | "version": "8.x-dev", 153 | "source": { 154 | "type": "git", 155 | "url": "https://github.com/illuminate/contracts.git", 156 | "reference": "8420ad4a55c85a106d560408239fd72a64057df6" 157 | }, 158 | "dist": { 159 | "type": "zip", 160 | "url": "https://api.github.com/repos/illuminate/contracts/zipball/8420ad4a55c85a106d560408239fd72a64057df6", 161 | "reference": "8420ad4a55c85a106d560408239fd72a64057df6", 162 | "shasum": "" 163 | }, 164 | "require": { 165 | "php": "^7.3", 166 | "psr/container": "^1.0", 167 | "psr/simple-cache": "^1.0" 168 | }, 169 | "type": "library", 170 | "extra": { 171 | "branch-alias": { 172 | "dev-master": "8.x-dev" 173 | } 174 | }, 175 | "autoload": { 176 | "psr-4": { 177 | "Illuminate\\Contracts\\": "" 178 | } 179 | }, 180 | "notification-url": "https://packagist.org/downloads/", 181 | "license": [ 182 | "MIT" 183 | ], 184 | "authors": [ 185 | { 186 | "name": "Taylor Otwell", 187 | "email": "taylor@laravel.com" 188 | } 189 | ], 190 | "description": "The Illuminate Contracts package.", 191 | "homepage": "https://laravel.com", 192 | "time": "2020-09-08T11:21:59+00:00" 193 | }, 194 | { 195 | "name": "illuminate/macroable", 196 | "version": "8.x-dev", 197 | "source": { 198 | "type": "git", 199 | "url": "https://github.com/illuminate/macroable.git", 200 | "reference": "561442f134eaf4d3f710bf523ecfe1537fa53f64" 201 | }, 202 | "dist": { 203 | "type": "zip", 204 | "url": "https://api.github.com/repos/illuminate/macroable/zipball/561442f134eaf4d3f710bf523ecfe1537fa53f64", 205 | "reference": "561442f134eaf4d3f710bf523ecfe1537fa53f64", 206 | "shasum": "" 207 | }, 208 | "require": { 209 | "php": "^7.3" 210 | }, 211 | "type": "library", 212 | "extra": { 213 | "branch-alias": { 214 | "dev-master": "8.x-dev" 215 | } 216 | }, 217 | "autoload": { 218 | "psr-4": { 219 | "Illuminate\\Support\\": "" 220 | } 221 | }, 222 | "notification-url": "https://packagist.org/downloads/", 223 | "license": [ 224 | "MIT" 225 | ], 226 | "authors": [ 227 | { 228 | "name": "Taylor Otwell", 229 | "email": "taylor@laravel.com" 230 | } 231 | ], 232 | "description": "The Illuminate Macroable package.", 233 | "homepage": "https://laravel.com", 234 | "time": "2020-06-08T14:13:16+00:00" 235 | }, 236 | { 237 | "name": "illuminate/support", 238 | "version": "8.x-dev", 239 | "source": { 240 | "type": "git", 241 | "url": "https://github.com/illuminate/support.git", 242 | "reference": "a7499132c366cf1c8ddfe6f26bba603767b1b560" 243 | }, 244 | "dist": { 245 | "type": "zip", 246 | "url": "https://api.github.com/repos/illuminate/support/zipball/a7499132c366cf1c8ddfe6f26bba603767b1b560", 247 | "reference": "a7499132c366cf1c8ddfe6f26bba603767b1b560", 248 | "shasum": "" 249 | }, 250 | "require": { 251 | "doctrine/inflector": "^1.4|^2.0", 252 | "ext-json": "*", 253 | "ext-mbstring": "*", 254 | "illuminate/collections": "^8.0", 255 | "illuminate/contracts": "^8.0", 256 | "illuminate/macroable": "^8.0", 257 | "nesbot/carbon": "^2.17", 258 | "php": "^7.3", 259 | "voku/portable-ascii": "^1.4.8" 260 | }, 261 | "conflict": { 262 | "tightenco/collect": "<5.5.33" 263 | }, 264 | "suggest": { 265 | "illuminate/filesystem": "Required to use the composer class (^8.0).", 266 | "ramsey/uuid": "Required to use Str::uuid() (^4.0).", 267 | "symfony/process": "Required to use the composer class (^5.1).", 268 | "symfony/var-dumper": "Required to use the dd function (^5.1).", 269 | "vlucas/phpdotenv": "Required to use the Env class and env helper (^5.0)." 270 | }, 271 | "type": "library", 272 | "extra": { 273 | "branch-alias": { 274 | "dev-master": "8.x-dev" 275 | } 276 | }, 277 | "autoload": { 278 | "psr-4": { 279 | "Illuminate\\Support\\": "" 280 | }, 281 | "files": [ 282 | "helpers.php" 283 | ] 284 | }, 285 | "notification-url": "https://packagist.org/downloads/", 286 | "license": [ 287 | "MIT" 288 | ], 289 | "authors": [ 290 | { 291 | "name": "Taylor Otwell", 292 | "email": "taylor@laravel.com" 293 | } 294 | ], 295 | "description": "The Illuminate Support package.", 296 | "homepage": "https://laravel.com", 297 | "time": "2020-09-09T15:54:22+00:00" 298 | }, 299 | { 300 | "name": "nesbot/carbon", 301 | "version": "dev-master", 302 | "source": { 303 | "type": "git", 304 | "url": "https://github.com/briannesbitt/Carbon.git", 305 | "reference": "6c7646154181013ecd55e80c201b9fd873c6ee5d" 306 | }, 307 | "dist": { 308 | "type": "zip", 309 | "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/6c7646154181013ecd55e80c201b9fd873c6ee5d", 310 | "reference": "6c7646154181013ecd55e80c201b9fd873c6ee5d", 311 | "shasum": "" 312 | }, 313 | "require": { 314 | "ext-json": "*", 315 | "php": "^7.1.8 || ^8.0", 316 | "symfony/polyfill-mbstring": "^1.0", 317 | "symfony/translation": "^3.4 || ^4.0 || ^5.0" 318 | }, 319 | "require-dev": { 320 | "doctrine/orm": "^2.7", 321 | "friendsofphp/php-cs-fixer": "^2.14 || ^3.0", 322 | "kylekatarnls/multi-tester": "^2.0", 323 | "phpmd/phpmd": "^2.9", 324 | "phpstan/extension-installer": "^1.0", 325 | "phpstan/phpstan": "^0.12.35", 326 | "phpunit/phpunit": "^7.5 || ^8.0", 327 | "squizlabs/php_codesniffer": "^3.4" 328 | }, 329 | "bin": [ 330 | "bin/carbon" 331 | ], 332 | "type": "library", 333 | "extra": { 334 | "branch-alias": { 335 | "dev-master": "2.x-dev", 336 | "dev-3.x": "3.x-dev" 337 | }, 338 | "laravel": { 339 | "providers": [ 340 | "Carbon\\Laravel\\ServiceProvider" 341 | ] 342 | }, 343 | "phpstan": { 344 | "includes": [ 345 | "extension.neon" 346 | ] 347 | } 348 | }, 349 | "autoload": { 350 | "psr-4": { 351 | "Carbon\\": "src/Carbon/" 352 | } 353 | }, 354 | "notification-url": "https://packagist.org/downloads/", 355 | "license": [ 356 | "MIT" 357 | ], 358 | "authors": [ 359 | { 360 | "name": "Brian Nesbitt", 361 | "email": "brian@nesbot.com", 362 | "homepage": "http://nesbot.com" 363 | }, 364 | { 365 | "name": "kylekatarnls", 366 | "homepage": "http://github.com/kylekatarnls" 367 | } 368 | ], 369 | "description": "An API extension for DateTime that supports 281 different languages.", 370 | "homepage": "http://carbon.nesbot.com", 371 | "keywords": [ 372 | "date", 373 | "datetime", 374 | "time" 375 | ], 376 | "funding": [ 377 | { 378 | "url": "https://opencollective.com/Carbon", 379 | "type": "open_collective" 380 | }, 381 | { 382 | "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", 383 | "type": "tidelift" 384 | } 385 | ], 386 | "time": "2020-09-11T19:00:58+00:00" 387 | }, 388 | { 389 | "name": "psr/container", 390 | "version": "dev-master", 391 | "source": { 392 | "type": "git", 393 | "url": "https://github.com/php-fig/container.git", 394 | "reference": "fc1bc363ecf887921e3897c7b1dad3587ae154eb" 395 | }, 396 | "dist": { 397 | "type": "zip", 398 | "url": "https://api.github.com/repos/php-fig/container/zipball/fc1bc363ecf887921e3897c7b1dad3587ae154eb", 399 | "reference": "fc1bc363ecf887921e3897c7b1dad3587ae154eb", 400 | "shasum": "" 401 | }, 402 | "require": { 403 | "php": ">=5.3.0" 404 | }, 405 | "type": "library", 406 | "extra": { 407 | "branch-alias": { 408 | "dev-master": "1.0.x-dev" 409 | } 410 | }, 411 | "autoload": { 412 | "psr-4": { 413 | "Psr\\Container\\": "src/" 414 | } 415 | }, 416 | "notification-url": "https://packagist.org/downloads/", 417 | "license": [ 418 | "MIT" 419 | ], 420 | "authors": [ 421 | { 422 | "name": "PHP-FIG", 423 | "homepage": "http://www.php-fig.org/" 424 | } 425 | ], 426 | "description": "Common Container Interface (PHP FIG PSR-11)", 427 | "homepage": "https://github.com/php-fig/container", 428 | "keywords": [ 429 | "PSR-11", 430 | "container", 431 | "container-interface", 432 | "container-interop", 433 | "psr" 434 | ], 435 | "time": "2019-10-04T14:07:35+00:00" 436 | }, 437 | { 438 | "name": "psr/simple-cache", 439 | "version": "dev-master", 440 | "source": { 441 | "type": "git", 442 | "url": "https://github.com/php-fig/simple-cache.git", 443 | "reference": "5a7b96b1dda5d957e01bc1bfe77dcca09c5a7474" 444 | }, 445 | "dist": { 446 | "type": "zip", 447 | "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/5a7b96b1dda5d957e01bc1bfe77dcca09c5a7474", 448 | "reference": "5a7b96b1dda5d957e01bc1bfe77dcca09c5a7474", 449 | "shasum": "" 450 | }, 451 | "require": { 452 | "php": ">=5.3.0" 453 | }, 454 | "type": "library", 455 | "extra": { 456 | "branch-alias": { 457 | "dev-master": "1.0.x-dev" 458 | } 459 | }, 460 | "autoload": { 461 | "psr-4": { 462 | "Psr\\SimpleCache\\": "src/" 463 | } 464 | }, 465 | "notification-url": "https://packagist.org/downloads/", 466 | "license": [ 467 | "MIT" 468 | ], 469 | "authors": [ 470 | { 471 | "name": "PHP-FIG", 472 | "homepage": "http://www.php-fig.org/" 473 | } 474 | ], 475 | "description": "Common interfaces for simple caching", 476 | "keywords": [ 477 | "cache", 478 | "caching", 479 | "psr", 480 | "psr-16", 481 | "simple-cache" 482 | ], 483 | "time": "2020-04-21T06:43:17+00:00" 484 | }, 485 | { 486 | "name": "symfony/polyfill-mbstring", 487 | "version": "dev-master", 488 | "source": { 489 | "type": "git", 490 | "url": "https://github.com/symfony/polyfill-mbstring.git", 491 | "reference": "48928d471ede0548b399f54b0286fe0d0ed79267" 492 | }, 493 | "dist": { 494 | "type": "zip", 495 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/48928d471ede0548b399f54b0286fe0d0ed79267", 496 | "reference": "48928d471ede0548b399f54b0286fe0d0ed79267", 497 | "shasum": "" 498 | }, 499 | "require": { 500 | "php": ">=5.3.3" 501 | }, 502 | "suggest": { 503 | "ext-mbstring": "For best performance" 504 | }, 505 | "type": "library", 506 | "extra": { 507 | "branch-alias": { 508 | "dev-master": "1.18-dev" 509 | }, 510 | "thanks": { 511 | "name": "symfony/polyfill", 512 | "url": "https://github.com/symfony/polyfill" 513 | } 514 | }, 515 | "autoload": { 516 | "psr-4": { 517 | "Symfony\\Polyfill\\Mbstring\\": "" 518 | }, 519 | "files": [ 520 | "bootstrap.php" 521 | ] 522 | }, 523 | "notification-url": "https://packagist.org/downloads/", 524 | "license": [ 525 | "MIT" 526 | ], 527 | "authors": [ 528 | { 529 | "name": "Nicolas Grekas", 530 | "email": "p@tchwork.com" 531 | }, 532 | { 533 | "name": "Symfony Community", 534 | "homepage": "https://symfony.com/contributors" 535 | } 536 | ], 537 | "description": "Symfony polyfill for the Mbstring extension", 538 | "homepage": "https://symfony.com", 539 | "keywords": [ 540 | "compatibility", 541 | "mbstring", 542 | "polyfill", 543 | "portable", 544 | "shim" 545 | ], 546 | "funding": [ 547 | { 548 | "url": "https://symfony.com/sponsor", 549 | "type": "custom" 550 | }, 551 | { 552 | "url": "https://github.com/fabpot", 553 | "type": "github" 554 | }, 555 | { 556 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 557 | "type": "tidelift" 558 | } 559 | ], 560 | "time": "2020-09-14T11:01:58+00:00" 561 | }, 562 | { 563 | "name": "symfony/polyfill-php80", 564 | "version": "dev-master", 565 | "source": { 566 | "type": "git", 567 | "url": "https://github.com/symfony/polyfill-php80.git", 568 | "reference": "c3616e7b303d0bd8c261de7921c72bf818b52b91" 569 | }, 570 | "dist": { 571 | "type": "zip", 572 | "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/c3616e7b303d0bd8c261de7921c72bf818b52b91", 573 | "reference": "c3616e7b303d0bd8c261de7921c72bf818b52b91", 574 | "shasum": "" 575 | }, 576 | "require": { 577 | "php": ">=7.0.8" 578 | }, 579 | "type": "library", 580 | "extra": { 581 | "branch-alias": { 582 | "dev-master": "1.18-dev" 583 | }, 584 | "thanks": { 585 | "name": "symfony/polyfill", 586 | "url": "https://github.com/symfony/polyfill" 587 | } 588 | }, 589 | "autoload": { 590 | "psr-4": { 591 | "Symfony\\Polyfill\\Php80\\": "" 592 | }, 593 | "files": [ 594 | "bootstrap.php" 595 | ], 596 | "classmap": [ 597 | "Resources/stubs" 598 | ] 599 | }, 600 | "notification-url": "https://packagist.org/downloads/", 601 | "license": [ 602 | "MIT" 603 | ], 604 | "authors": [ 605 | { 606 | "name": "Ion Bazan", 607 | "email": "ion.bazan@gmail.com" 608 | }, 609 | { 610 | "name": "Nicolas Grekas", 611 | "email": "p@tchwork.com" 612 | }, 613 | { 614 | "name": "Symfony Community", 615 | "homepage": "https://symfony.com/contributors" 616 | } 617 | ], 618 | "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", 619 | "homepage": "https://symfony.com", 620 | "keywords": [ 621 | "compatibility", 622 | "polyfill", 623 | "portable", 624 | "shim" 625 | ], 626 | "funding": [ 627 | { 628 | "url": "https://symfony.com/sponsor", 629 | "type": "custom" 630 | }, 631 | { 632 | "url": "https://github.com/fabpot", 633 | "type": "github" 634 | }, 635 | { 636 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 637 | "type": "tidelift" 638 | } 639 | ], 640 | "time": "2020-09-14T10:02:33+00:00" 641 | }, 642 | { 643 | "name": "symfony/translation", 644 | "version": "dev-master", 645 | "source": { 646 | "type": "git", 647 | "url": "https://github.com/symfony/translation.git", 648 | "reference": "834997294ad70740a6b376d666fce870e1297d78" 649 | }, 650 | "dist": { 651 | "type": "zip", 652 | "url": "https://api.github.com/repos/symfony/translation/zipball/834997294ad70740a6b376d666fce870e1297d78", 653 | "reference": "834997294ad70740a6b376d666fce870e1297d78", 654 | "shasum": "" 655 | }, 656 | "require": { 657 | "php": ">=7.2.5", 658 | "symfony/polyfill-mbstring": "~1.0", 659 | "symfony/polyfill-php80": "^1.15", 660 | "symfony/translation-contracts": "^2" 661 | }, 662 | "conflict": { 663 | "symfony/config": "<4.4", 664 | "symfony/dependency-injection": "<5.0", 665 | "symfony/http-kernel": "<5.0", 666 | "symfony/twig-bundle": "<5.0", 667 | "symfony/yaml": "<4.4" 668 | }, 669 | "provide": { 670 | "symfony/translation-implementation": "2.0" 671 | }, 672 | "require-dev": { 673 | "psr/log": "~1.0", 674 | "symfony/config": "^4.4|^5.0", 675 | "symfony/console": "^4.4|^5.0", 676 | "symfony/dependency-injection": "^5.0", 677 | "symfony/finder": "^4.4|^5.0", 678 | "symfony/http-kernel": "^5.0", 679 | "symfony/intl": "^4.4|^5.0", 680 | "symfony/service-contracts": "^1.1.2|^2", 681 | "symfony/yaml": "^4.4|^5.0" 682 | }, 683 | "suggest": { 684 | "psr/log-implementation": "To use logging capability in translator", 685 | "symfony/config": "", 686 | "symfony/yaml": "" 687 | }, 688 | "type": "library", 689 | "extra": { 690 | "branch-alias": { 691 | "dev-master": "5.2-dev" 692 | } 693 | }, 694 | "autoload": { 695 | "files": [ 696 | "Resources/functions/translatable.php" 697 | ], 698 | "psr-4": { 699 | "Symfony\\Component\\Translation\\": "" 700 | }, 701 | "exclude-from-classmap": [ 702 | "/Tests/" 703 | ] 704 | }, 705 | "notification-url": "https://packagist.org/downloads/", 706 | "license": [ 707 | "MIT" 708 | ], 709 | "authors": [ 710 | { 711 | "name": "Fabien Potencier", 712 | "email": "fabien@symfony.com" 713 | }, 714 | { 715 | "name": "Symfony Community", 716 | "homepage": "https://symfony.com/contributors" 717 | } 718 | ], 719 | "description": "Symfony Translation Component", 720 | "homepage": "https://symfony.com", 721 | "funding": [ 722 | { 723 | "url": "https://symfony.com/sponsor", 724 | "type": "custom" 725 | }, 726 | { 727 | "url": "https://github.com/fabpot", 728 | "type": "github" 729 | }, 730 | { 731 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 732 | "type": "tidelift" 733 | } 734 | ], 735 | "time": "2020-09-10T08:35:47+00:00" 736 | }, 737 | { 738 | "name": "symfony/translation-contracts", 739 | "version": "dev-master", 740 | "source": { 741 | "type": "git", 742 | "url": "https://github.com/symfony/translation-contracts.git", 743 | "reference": "77ce1c3627c9f39643acd9af086631f842c50c4d" 744 | }, 745 | "dist": { 746 | "type": "zip", 747 | "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/77ce1c3627c9f39643acd9af086631f842c50c4d", 748 | "reference": "77ce1c3627c9f39643acd9af086631f842c50c4d", 749 | "shasum": "" 750 | }, 751 | "require": { 752 | "php": ">=7.2.5" 753 | }, 754 | "suggest": { 755 | "symfony/translation-implementation": "" 756 | }, 757 | "type": "library", 758 | "extra": { 759 | "branch-alias": { 760 | "dev-master": "2.2-dev" 761 | }, 762 | "thanks": { 763 | "name": "symfony/contracts", 764 | "url": "https://github.com/symfony/contracts" 765 | } 766 | }, 767 | "autoload": { 768 | "psr-4": { 769 | "Symfony\\Contracts\\Translation\\": "" 770 | } 771 | }, 772 | "notification-url": "https://packagist.org/downloads/", 773 | "license": [ 774 | "MIT" 775 | ], 776 | "authors": [ 777 | { 778 | "name": "Nicolas Grekas", 779 | "email": "p@tchwork.com" 780 | }, 781 | { 782 | "name": "Symfony Community", 783 | "homepage": "https://symfony.com/contributors" 784 | } 785 | ], 786 | "description": "Generic abstractions related to translation", 787 | "homepage": "https://symfony.com", 788 | "keywords": [ 789 | "abstractions", 790 | "contracts", 791 | "decoupling", 792 | "interfaces", 793 | "interoperability", 794 | "standards" 795 | ], 796 | "funding": [ 797 | { 798 | "url": "https://symfony.com/sponsor", 799 | "type": "custom" 800 | }, 801 | { 802 | "url": "https://github.com/fabpot", 803 | "type": "github" 804 | }, 805 | { 806 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 807 | "type": "tidelift" 808 | } 809 | ], 810 | "time": "2020-09-07T11:33:47+00:00" 811 | }, 812 | { 813 | "name": "twilio/sdk", 814 | "version": "6.10.1", 815 | "source": { 816 | "type": "git", 817 | "url": "https://github.com/twilio/twilio-php.git", 818 | "reference": "1fc7b861f0df7302554a88f2c03b2d76ab184dd0" 819 | }, 820 | "dist": { 821 | "type": "zip", 822 | "url": "https://api.github.com/repos/twilio/twilio-php/zipball/1fc7b861f0df7302554a88f2c03b2d76ab184dd0", 823 | "reference": "1fc7b861f0df7302554a88f2c03b2d76ab184dd0", 824 | "shasum": "" 825 | }, 826 | "require": { 827 | "php": ">=7.1.0" 828 | }, 829 | "require-dev": { 830 | "guzzlehttp/guzzle": "^6.3 || ^7.0", 831 | "phpunit/phpunit": ">=4.5", 832 | "theseer/phpdox": "^0.12.0" 833 | }, 834 | "suggest": { 835 | "guzzlehttp/guzzle": "An HTTP client to execute the API requests" 836 | }, 837 | "type": "library", 838 | "autoload": { 839 | "psr-4": { 840 | "Twilio\\": "src/Twilio/" 841 | } 842 | }, 843 | "notification-url": "https://packagist.org/downloads/", 844 | "license": [ 845 | "MIT" 846 | ], 847 | "authors": [ 848 | { 849 | "name": "Twilio API Team", 850 | "email": "api@twilio.com" 851 | } 852 | ], 853 | "description": "A PHP wrapper for Twilio's API", 854 | "homepage": "http://github.com/twilio/twilio-php", 855 | "keywords": [ 856 | "api", 857 | "sms", 858 | "twilio" 859 | ], 860 | "time": "2020-09-02T20:08:41+00:00" 861 | }, 862 | { 863 | "name": "voku/portable-ascii", 864 | "version": "1.5.3", 865 | "source": { 866 | "type": "git", 867 | "url": "https://github.com/voku/portable-ascii.git", 868 | "reference": "25bcbf01678930251fd572891447d9e318a6e2b8" 869 | }, 870 | "dist": { 871 | "type": "zip", 872 | "url": "https://api.github.com/repos/voku/portable-ascii/zipball/25bcbf01678930251fd572891447d9e318a6e2b8", 873 | "reference": "25bcbf01678930251fd572891447d9e318a6e2b8", 874 | "shasum": "" 875 | }, 876 | "require": { 877 | "php": ">=7.0.0" 878 | }, 879 | "require-dev": { 880 | "phpunit/phpunit": "~6.0 || ~7.0" 881 | }, 882 | "suggest": { 883 | "ext-intl": "Use Intl for transliterator_transliterate() support" 884 | }, 885 | "type": "library", 886 | "autoload": { 887 | "psr-4": { 888 | "voku\\": "src/voku/" 889 | } 890 | }, 891 | "notification-url": "https://packagist.org/downloads/", 892 | "license": [ 893 | "MIT" 894 | ], 895 | "authors": [ 896 | { 897 | "name": "Lars Moelleken", 898 | "homepage": "http://www.moelleken.org/" 899 | } 900 | ], 901 | "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", 902 | "homepage": "https://github.com/voku/portable-ascii", 903 | "keywords": [ 904 | "ascii", 905 | "clean", 906 | "php" 907 | ], 908 | "funding": [ 909 | { 910 | "url": "https://www.paypal.me/moelleken", 911 | "type": "custom" 912 | }, 913 | { 914 | "url": "https://github.com/voku", 915 | "type": "github" 916 | }, 917 | { 918 | "url": "https://opencollective.com/portable-ascii", 919 | "type": "open_collective" 920 | }, 921 | { 922 | "url": "https://www.patreon.com/voku", 923 | "type": "patreon" 924 | }, 925 | { 926 | "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii", 927 | "type": "tidelift" 928 | } 929 | ], 930 | "time": "2020-07-22T23:32:04+00:00" 931 | } 932 | ], 933 | "packages-dev": [], 934 | "aliases": [], 935 | "minimum-stability": "dev", 936 | "stability-flags": [], 937 | "prefer-stable": false, 938 | "prefer-lowest": false, 939 | "platform": [], 940 | "platform-dev": [], 941 | "plugin-api-version": "1.1.0" 942 | } 943 | -------------------------------------------------------------------------------- /src/PhoneValidatorServiceProvider.php: -------------------------------------------------------------------------------- 1 | publishes([ 19 | __DIR__.'/config/twilio.php' => config_path('twilio.php'), 20 | ], 'twilio'); 21 | 22 | // load translation files 23 | $this->loadTranslationsFrom(__DIR__ . '/lang', 'phone'); 24 | 25 | // setup custom twilio validator 26 | $this->app->validator->extend('phone', function($attribute, $value, $parameters, $validator){ 27 | // fetch the api key from the config - which allows the config to be cached 28 | $twilioSID = config('twilio.sid'); 29 | $twilioToken = config('twilio.token'); 30 | 31 | // throw exception if the twilio credentials are missing from the env 32 | if( $twilioSID == null || $twilioToken == null ) { 33 | throw new TwilioCredentialsNotFoundException('Please provide a TWILIO_SID and TWILIO_TOKEN in your .env file.'); 34 | } 35 | 36 | $client = new Twilio($twilioSID, $twilioToken); 37 | try { 38 | // attempt to look up a phone number 39 | // if an exception is thrown, no phone number was found 40 | $client->lookups->phoneNumbers($value)->fetch(); 41 | return true; 42 | } catch (\Exception $e) { 43 | return false; 44 | } 45 | }, $this->app->translator->get('phone::validation.phone')); 46 | } 47 | 48 | /** 49 | * Register any application services. 50 | * 51 | * @return void 52 | */ 53 | public function register() 54 | { 55 | $this->mergeConfigFrom( 56 | __DIR__ . '/config/twilio.php', 'twilio' 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/TwilioCredentialsNotFoundException.php: -------------------------------------------------------------------------------- 1 | env('TWILIO_SID'), 5 | 'token' => env('TWILIO_TOKEN') 6 | ]; 7 | -------------------------------------------------------------------------------- /src/lang/en/validation.php: -------------------------------------------------------------------------------- 1 | 'The :attribute must be a valid phone number.' 5 | ]; 6 | --------------------------------------------------------------------------------