Laravel PHP Tutoriel
3 min de lecture

Network Operators Query scope Laravel

muarachmann

Mua Rachmann

@muarachmann

Network Operators Query scope Laravel

Before diving into the hassle of creating this post, I had one big concern dealing with tons of telephone data (numbers), I had to filter these based on Cameroonian network operators (MTN, ORANGE, CAMTEL & NEXTTEL). While this was an easy thing to do with the 'LIKE' functionality of mysql. However, I didn't like my solution as shown below.

1// scope for network operators
2public function scopeNetworkOperator($query, string $operator = null)
3 {
4 switch ($operator) {
5 case "mtn":
6 return $query->where('phone', 'like', '67%')
7 ->orWhere('phone', 'like', '650%')
8 ->orWhere('phone', 'like', '651%')
9 ->orWhere('phone', 'like', '652%')
10 ->orWhere('phone', 'like', '653%')
11 ->orWhere('phone', 'like', '654%')
12 ->orWhere('phone', 'like', '680%')
13 ->orWhere('phone', 'like', '681%')
14 ->orWhere('phone', 'like', '682%')
15 ->orWhere('phone', 'like', '683%');
16 case "orange":
17 return $query->where('phone', 'like', '69%')
18 ->orWhere('phone', 'like', '655%')
19 ->orWhere('phone', 'like', '656%')
20 ->orWhere('phone', 'like', '657%')
21 ->orWhere('phone', 'like', '658%')
22 ->orWhere('phone', 'like', '659%');
23 case "camtel":
24 return $query->where('phone', 'like', '233%')
25 ->orWhere('phone', 'like', '222%')
26 ->orWhere('phone', 'like', '242%')
27 ->orWhere('phone', 'like', '243%');
28 case "nexttel":
29 return $query->where('phone', 'like', '66%');
30 default:
31 return $query;
32 }
33 }

With this we can then get them all with

1Client::networkOperator('mtn')->get();

However for scalability and readability, and the fact I worried about dial codes which wasn't a problem at this moment because I had this separated this for my database, so actually phone numbers where in standard format and not international formats and I kept the dail code in another column. Yet I wasn't still satisfied. So I began playing with some regex. Yes regex. If you haven't heard about regex, a nice place to start will be here https://regexlearn.com/learn and you can test them here https://regex101.com/

For simplicity I made it as a helper function. You can go ahead and make it as a trait, class, package whatever.

Enough talk, lets dive into action...

We first create a helper function to match produce our regex given the operator.

1 // NetworkOperator.php
2class NetworkOperator
3{
4 /**
5 * Country Prefix.
6 */
7 const PREFIX = '237';
8 
9 /**
10 * Operator Prefixes.
11 */
12 const OPERATOR_PREFIXES = [
13 'mtn' => [
14 67, 650, 651, 652, 653, 654, 680, 681, 682, 683,
15 ],
16 'orange' => [
17 69, 655, 656, 657, 658, 659,
18 ],
19 'nexttel' => [
20 66,
21 ],
22 'camtel' => [
23 233, 222, 242, 243,
24 ],
25 ];
26 
27 /**
28 * Match Regex to Operator.
29 * @param string|null $operator
30 * @return string
31 */
32 public static function getRegex(string $operator = null): ?string
33 {
34 if (!$operator || !array_key_exists($operator, self::OPERATOR_PREFIXES)) return 'null';
35 $operator_prefixes = trim(implode('|', self::OPERATOR_PREFIXES[$operator]), '|');
36 return "((|(0{2}))?" . self::PREFIX . ")?(("."$operator_prefixes".")([0-9]{6,7}))$";
37 }
38}

With this, I can get the regex of a particular operator by simply performing

1NetworkOperator::getRegex('mtn')
2 
3// results
4((|(0{2}))?237)?((67|650|651|652|653|654|680|681|682|683)([0-9]{6,7}))$

With this I was very pleased cause this takes care of all scenarios and even international standards. Again if you don't know about regex, please make sure to get the basics to understand what is going on in the getRegex() method.

With this, I refactored my queryScope with the following code

1public function scopeNetworkOperator($query, string $operator = null)
2{
3 $regex = NetworkOperator::getRegex($operator);
4 return $query->whereRaw("phone regexp '$regex'");
5}

Then I can call this anywhere within my controller via my model

1Client::networkOperator('mtn')->get()
2User::networkOperator('mtn')->get()
3...
4etc

I like this solution because it is scalable and can work for any country/dial code, you just need to modify the country dial code prefix and its operators number and you are good to go. Feel free to tweak the regex if your database is not using numbers in international formats. I hope this be of help to you someday :)

muarachmann

Mua Rachmann

@muarachmann

Lead Software Engineer @waspito,

Vous aimez cet article ? Faite le savoir en partageant