novo-connect / somali-phone
Validate, normalize and identify Somali mobile numbers: operator, virtual network and mobile money wallet. Works in plain PHP, with optional Laravel integration.
Requires
- php: ^8.2
Requires (Dev)
- laravel/pint: ^1.13
- orchestra/testbench: ^10.0|^11.0
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^11.5|^12.0
Suggests
- illuminate/support: For the Laravel validation rule, string rule and Eloquent cast (^12.0|^13.0).
Provides
None
Conflicts
None
Replaces
None
README
Validate and normalize Somali mobile numbers, and find out which operator and mobile money wallet they belong to.
Works with PHP 8.2+, and comes with a validation rule and an Eloquent cast for Laravel 12 and 13.
Installation
composer require novo-connect/somali-phone
Usage
use NovoConnect\SomaliPhone\SomaliPhone; $number = SomaliPhone::parse('063 412 3456'); $number->msisdn(); // "252634123456" $number->e164(); // "+252634123456" $number->local(); // "0634123456" $number->format(); // "+252 63 412 3456" $number->operator(); // Operator::TELESOM $number->networkName(); // "Telesom" $number->wallet(); // "Zaad" $number->supportsWaafi(); // true
Numbers can be written with or without the country code, with spaces, dashes or brackets, and in Arabic-Indic digits. parse() throws an InvalidPhoneNumber exception for anything else, while tryParse() returns null.
SomaliPhone::isValid('0644123456'); // false, 64 is not in use SomaliPhone::normalize('+252634123456'); // "252634123456" SomaliPhone::parse('0634123456')->equals('+252 63 412 3456'); // true
Some prefixes run a virtual network on top of an operator. For those, virtualNetwork() returns the network and networkName() returns it instead of the operator:
$number = SomaliPhone::parse('0702000001'); $number->operator(); // Operator::GOLIS $number->virtualNetwork(); // "Durdur" $number->wallet(); // "Kayd"
WAAFI
supportsWaafi() is only true for wallets listed in the WaafiPay docs: EVC Plus, Zaad and Sahal. Jeeb, Kaash Plus and Kayd may also work with WAAFI, but we couldn't confirm it, so they return false and isWaafiUnconfirmed() returns true. If you know of an official source, please open an issue.
Laravel
The service provider is registered automatically.
Validation
use NovoConnect\SomaliPhone\Laravel\Rules\SomaliPhoneNumber; use NovoConnect\SomaliPhone\Operator; $request->validate([ 'phone' => ['required', new SomaliPhoneNumber], 'evc_phone' => ['required', (new SomaliPhoneNumber)->operators(Operator::HORMUUD)], 'wallet' => ['required', (new SomaliPhoneNumber)->wallets('Zaad', 'Sahal')], 'payout' => ['required', (new SomaliPhoneNumber)->waafi()], ]);
You can also filter by virtualNetworks('Somnet'). Or use the string rule:
'phone' => 'required|somali_phone', 'phone' => 'required|somali_phone:Hormuud,Telesom',
Error messages are in English and Somali. Run php artisan vendor:publish --tag=somali-phone-lang to change them.
Eloquent cast
use NovoConnect\SomaliPhone\Laravel\Casts\AsSomaliPhone; protected $casts = [ 'phone' => AsSomaliPhone::class, ];
The number is saved as 252634123456 and you get a PhoneNumber back when you read it. Assigning an invalid number throws an exception, so validate first. Since the column is normalized, normalize input before querying it too:
Customer::where('phone', SomaliPhone::normalize($request->phone))->first();
Prefixes
| Prefix | Operator | Virtual network | Wallet |
|---|---|---|---|
| 61, 77, 78 | Hormuud | EVC Plus | |
| 68 | Hormuud | Somnet | Jeeb |
| 63 | Telesom | Zaad | |
| 67 | Telesom | Soltelco | Kaash Plus |
| 60, 72, 90 | Golis | Sahal | |
| 70 | Golis | Durdur | Kayd |
| 62, 65, 66, 76 | Somtel | eDahab | |
| 69 | NationLink | e-Maal | |
| 71, 75 | Amtel | MyCash |
Based on the NCA numbering plan published through the ITU in December 2024. Prefix 90 isn't in that plan but is widely used by Golis. If something here is wrong or out of date, a pull request with a source is very welcome.
Testing
composer test
Credits
Created by Zakaria Ibrahim, maintained by Novo Connect. Questions go to hello@novo.co.com.
License
MIT. See LICENSE.