Twilio - Bypass ".json not found" in php - php

I am trying to check for toll-free numbers, and it is working as expected. However, my problem is that some countries don't have the TollFree numbers.
Using the same code on these countries throws a 404 error and stops the code there.
The only way I could think of is making a massive if statement and adding each country manually which offers toll-free option, but I don't like this solution at all as it will be hardcoded. Is there a way to overcome this issue, so it works for the countries that has the .json and ignore the ones that doesn't (instead of crashing the code)?
$twilio = new Client(env('TWILIO_ID'), env('TWILIO_TOKEN'));
$iso = 'CY';
$params = ["excludeLocalAddressRequired" => "true"];
$tollFreeNumbers = $twilio->availablePhoneNumbers($iso)->tollFree->read($params);
This is the response:
"[HTTP 404] Unable to fetch page: The requested resource /2010-04-01/Accounts/ACxxxxx/AvailablePhoneNumbers/CY/TollFree.json was not found"
Using this code will crash with CY but will work with UK, US, CA and many more. Should I add an if statement with hardcoded countries? (I really dislike this solution, but this is what I can think of). What I mean is:
if ($iso == 'GB' || $iso == 'US' || $iso == 'CA') { // and many more
$tollFreeNumbers = $twilio->availablePhoneNumbers($iso)->tollFree->read($params);
}

Twilio developer evangelist here.
Rather than guarding up front with a conditional (which could become out of date as we add toll free numbers in other countries in the future), why not catch the error and return a message to the user to say that toll free numbers are not available in the country they are searching in.
Something like:
try {
$tollFreeNumbers = $twilio->availablePhoneNumbers($iso)->tollFree->read($params);
} catch (Exception $e) {
$tollFreeNumbers = [];
$message = "Toll free numbers are not available in this country.";
}
Let me know if that helps at all.

Why not just wrap it in a try catch?
try {
$tollFreeNumbers = $twilio->availablePhoneNumbers($iso)->tollFree->read($params);
} catch(\Exception $e) {
$tollFreeNumbers = [];
}

Related

Exceptions - what is "exceptional"?

I've read that exceptions shouldn't be used for directing the flow of your application but should be used to recover the application to a stable state when something "exceptional" happens, for example, when you fail to connect to a database.
An example of where an exception shouldn't be used would be a user providing an incorrect login. It wouldn't be an exception since it's expected that that will happen.
I'm not sure whether the following case is exceptional or not:
I'm currently designing a simple blog. A "post" is assigned to just one "category". In my posts table I have a category_id field with a foreign key constraint.
Now, I'm using Laravel so if I try to delete a category that currently has posts in it, I believe it should throw an \Illuminate\Database\QueryException because of the foreign key constraint. Therefore should I rely on this and write code like:
try {
$category->delete();
}
catch (\Illuminate\Database\QueryException $e) {
// Tell the user that they can't delete the category because there are posts assigned to it
}
or since I know how I want my blog to work, should I use:
if ($category->posts->isEmpty()) {
$category->delete();
}
else {
// Tell the user they can't delete...
}
Any advice would be appreciated. Thanks!
It is very opinion based, so i'll give you my opinion:
Exceptions are powerfull, because you can attach a lot of information with it - and you can send them "up the callstack" without having hundrets of methods checking the return value of any call and returning whatever to their own caller.
This allows you to easily handle an error at the desired layer in the callstack.
A Method should return, what is the result of the call (even if it's void). If the call fails for any reason, there should be no return value.
Errors should not be transported by returnvalues, but with exceptions.
Imagine a function doing db-queries: KeyAlreadyExistsException, InvalidSyntaxException and NullPointerException - most likely you want to handle this "errors" at very different parts in your code.
(One is a code-error, one is a query-error, one is a logical-error)
Example one, easy "handling":
try{
method1(1);
}catch (Exception $e){
//Handle all but NullpointerExceptions here.
}
---
method1($s){
try{
method2($s+2);
} catch (NullPointerException $e){
//only deal with NPEs here, others bubble up the call stack.
}
}
---
method2($s){
//Some Exception here.
}
Example two - you see the required "nesting", and the stack-depth is only 2 here.
$result = method1(1);
if ($result === 1){
//all good
}else{
//Handle all but NullpointerExceptions here.
}
---
method1($s){
$result = method2($s+2);
if ($result === 1){
return $result;
}else{
if ($result === "NullPointerException"){
//do something
}
}
method2($s){
//Exception here.
}
Especially for maintainance, Exceptions have huge advantages: If you add a new "Exception" - the worstcase will be an unhandled exception, but code execution will break.
If you add new "return errors", you need to make sure, that every Caller is aware of these new errors:
function getUsername($id){
// -1 = id not found
$name = doQuery(...);
if (id not found) return -1;
else return $name;
}
vs
function getUsername($id){
$name = doQuery(...);
if (id not found) throw new IdNotFoundException(...);
return $name;
}
Now consider the handling in both cases:
if (getUsername(4)=== -1) { //error } else { //use it }
vs
try{
$name = getUsername(4);
//use it
}catch (IdNotFoundException $e){
//error
}
And now, you add the return code -2: First way would assume the username to be -2, until the error code is implemented. Second way (Another Exception) would cause the execution to stop with an unhandled exception somewhere way up in the callstack.
Dealing with return values (of any kind) for error-transportation is error prone and errors might vanish somewhere, turning into a "wrong" interpreted result.
Using exceptions is safer: You either have a return value to use, or a (handled or unhandled) exception, but no "wrong values" due to autocasts etc.

Google Adwords Incorrect statistics

I'm using the Google AdWords PHP API to access statistics from our account. However, I'm getting some really strange read outs from the statistics through the api. I'm trying to access the stats for individuals Ads or Adgroups. The statistics returned, however, are way off what they are in the client center. The code I'm using:
$user->SetClientCustomerId($clientId);
$adService = $user->GetService("AdGroupAdService", ADWORDS_VERSION);
$selector = new Selector();
$selector->fields = array("Id", "Name", "Clicks", "Impressions", "Cost");
$selector->predicates[] = new Predicate("AdGroupId", "IN", array($adGroupId));
$selector->dateRange = $dateRange;
$selector->paging = new Paging(0, AdWordsConstants::RECOMMENDED_PAGE_SIZE);
do {
// Make the get request.
$page = $adService->get($selector);
if (isset($page->entries)) {
foreach ($page->entries as $ad) {
$newLineObject->adName = $ad->name;
$newLineObject->clicks = $ad->ad->AdStats->clicks;
$newLineObject->impressions = $ad->adStats->impressions;
$newLineObject->cost = $ad->ad->AdStats->cost->microAmount/ AdWordsConstants::MICROS_PER_DOLLAR;
}
}
else {
print "No matching ads were found.\n";
}
$selector->paging->startIndex += AdWordsConstants::RECOMMENDED_PAGE_SIZE;
} while ($page->totalNumEntries > $selector->paging->startIndex);
When I print the results I get numbers that are considerably larger than those displayed in the client center. For example, for one partiuclar Ad the API reported 2.000.000 impressions, while the client center showed 56.000.
What am I doing wrong?
Your code seems correct to me. However, you problem may be that your date range in your code is different to the one you see in your client center. Make sure that you keep the same date range when you cross check.
Having tried using the method detailed above extensively, I have altered my code completely. I now use AdHoc Reporting (described here https://developers.google.com/adwords/api/docs/guides/reporting). This method was suggested to me by an AdWords developer. While this does not literally solve my question (i.e. why does the above code return incorrect statistics), it does provide an easy and clean way to obtain the data correctly.

How do I use the twilio-php library to retrieve all calls made between two dates?

Using the following code I am able to get the logs of calls and SMS's. How do I modify this code to only search between certain dates using PHP?
// Instantiate a new Twilio Rest Client
$client = new Services_Twilio($AccountSid, $AuthToken, $ApiVersion);
// http://www.twilio.com/docs/quickstart...
try {
// Get Recent Calls
foreach ($client->account->calls as $call) {
echo "Call from $call->sid : $call->from to $call->to at $call->start_time of length $call->duration $call->price <br>";
}
}
catch (Exception $e) {
echo 'Error: ' . $e->getMessage();
}
You will want to add a code snippet that looks something like this:
$client = new Services_Twilio('AC123', '123');
foreach ($client->account->calls->getIterator(0, 50, array(
'StartTime>' => '2012-04-01',
'StartTime<' => '2012-05-01'
)) as $call) {
echo "From: {$call->from}\nTo: {$call->to}\nSid: {$call->sid}\n\n";
}
If you want to filter the list, you have to construct the iterator yourself with the getIterator command. There's more documentation here: Filtering Twilio Calls with PHP
User search terms StartTime> and StartTime< for this. First one means call start time is greater than and last one means call start time is less than.
To find every calls that started between 4th and 6th July of 2009 add search term
array(
'StartTime>' => '2009-07-04',
'StartTime<' => '2009-07-06'
)
See example 4 on the twilio doc.
Also note you can always ask twilio support. They usually help gladly.

How to strip subdomains to get valid root domain using PHP?

Ok, here's what I'm looking for: from a list of links, I'm stripping everything but the domains. The result is a mixed list of domains and domain-names which represent subdomains.
stackoverflow.com
security.stackexchange.com
whoknows.test.co.uk
you.get.it.by.now.dont.you.com
What I want to do is to trim all list entries down to their VALID (=only existing) root domains like this:
stackoverflow.com
security.stackexchange.com
test.co.uk
-fail-
Currently I explode each line into an array and work my list from back to front, using curl to check each potential root domain for it's existance... as soon as curl throws back a HTTP code >= 200 and < 400, I regard the root domain to be found. When the end of each potential domain lookup is done and no valid domain has been found at all, the domain is considered to be non-existant.
input: stackoverflow.com
test: stackoverflow.com - succeeds and is the root domain
result: stackoverflow.com - valid root domain
input: whoknows.test.co.uk
test: co.uk - fails
test: test.co.uk - succeeds (theoretically) and is the root domain
result: test.co.uk - valid root domain
input: you.get.it.by.now.dont.you.com
test: you.com - fails
test: dont.you.com - fails
test: now.dont.you.com - fails
test: by.now.dont.you.com - fails
test: it.by.now.dont.you.com - fails
test: get.it.by.now.dont.you.com - fails
test: you.get.it.by.now.dont.you.com - fails
result: you.get.it.by.now.dont.you.com - invalid domain
Is there any alternative way to do this? I would like to stop heating up my webserver's CPU with 2 to X (=near to unlimited) curl look-ups for every domain on my 100.000+ list. Also, all these lookups take a bunch of time. Maybe - so I hope - there is a quicker solution to do this.
The catch? It has to work with PHP.
There are a bunch of shortcuts to acheive what you need.
For example, you already know that .co.uk and .com are TLDs, so checking these you can obviously skip.
The problem is with all the other crazy TLDs.
I suggest you take a look at the source for ruby-domain-name
They have done a lot of work using RFCs and known data, to try and process it the right way.
So...
I've been fiddling around with this for a long time now, looking for the potential bottlenecks and after a few days of back and forth I discovered that it's actually CURL (that's waiting for the individual servers to respond with a HTTP code) that's making things slower than needed.
In the end, I opted in for a different "gethostbyname" function that takes IP6 into account to solve my problem(s).
function my_gethostbyname($host, $try_a = FALSE)
{
$dns = gethostbynamel6($host, $try_a);
if ($dns == FALSE)
{
return FALSE;
}
else
{
return $dns[0];
}
}
function gethostbynamel6($host, $try_a = FALSE)
{
$dns = array();
$dns6 = #dns_get_record($host, DNS_AAAA);
if($dns6!== FALSE)
{
$dns = array_merge($dns, $dns6);
}
if ($try_a == TRUE)
{
$dns4 = #dns_get_record($host, DNS_A);
if($dns4!== FALSE)
{
$dns = array_merge($dns, $dns4);
}
}
else
{
$dns = $dns6;
}
$ip6 = array();
$ip4 = array();
foreach ($dns as $record)
{
if ($record["type"] == "A")
{
$ip4[] = $record["ip"];
}
if ($record["type"] == "AAAA")
{
$ip6[] = $record["ipv6"];
}
}
if (count($ip6) < 1)
{
if ($try_a == TRUE)
{
if (count($ip4) < 1)
{
return FALSE;
}
else
{
return $ip4;
}
}
else
{
return FALSE;
}
}
else
{
return $ip6;
}
}
As soon as the first domain-part actually resolves to an IP, (a) the domain exists and (b) is the root domain.
This spares me major time and the trick of this is that you're only as slow as your DNS resolution and some microsecs. The curl option I used before took around 3 seconds per call (sometimes up to the full timeout range I had set to 20 secs), depending on the target server's response time - if any.
The path I now chose is easy to understand: I end up with a list of resolving domains and - when needed - I can check those using curl "on demand" or using one or more CRON jobs "on interval".
I know that it's kind of a workaround, but splitting the problem into two tasks (1 = pre-check for root domain, 2 = check if domain returns expected HTTP code) makes the whole thing faster than trying to do the complete job at once using curl.
What I've learned from this...
When checking domains, try to resolve them first so you can spare yourself the timeout burden that comes with curl.
Curl is great for many tasks, but it's not the smartest way to try to do everything with it.
When you think you can't solve a problem more than you've tried to do, split the problem in two or more parts and check again. Chances are big that you'll discover a whole new world of options to enhance what you've got.
I hope this spares someone the burden of fiddling around with an alike problem for weeks. ;)
class DomainUtils {
function __construct(){
//only these super domains
$this->superDomains = array(
'.com',
'.gov',
'.org',
'.co.uk',
'.info',
'.co',
'.net',
'.me',
'.tv',
'.mobi'
);
}
//get super domain
public function getMainDomain($domain = null){
$domainChunks = explode('.', str_ireplace($this->superDomains, '', $domain));
if(sizeof($domainChunks) == 0){
return false;
}
foreach($domainChunks as $key => $domainChunk){
if($key < sizeof($domainChunks) - 1){
$domain = str_ireplace($domainChunk . '.', '', $domain);
}
}
return $domain;
}
}

facebook api: count attendees for event (limit problem)

Okay normally I'm all fine about the facebook API but I'm having a problem which just keeps me wondering. (I think it's a bug (Check ticket http://bugs.developers.facebook.net/show_bug.cgi?id=13694) but I wanted to throw it here if somebody has an idea).
I'm usng the facebook PHP library to count all attendees for a specific event
$attending = $facebook->api('/'.$fbparams['eventId'].'/attending');
this works without a problem it correctly returns an array with all attendees...
now heres the problem:
This event has about 18.000 attendees right now.
The api call returns a max number of 992 attendees (and not 18000 as it should).
I tried
$attending = $facebook->api('/'.$fbparams['eventId'].'/attending?limit=20000');
for testing but it doesn't change anything.
So my actual question is:
If I can't get it to work by using the graph api what would be a good alternative? (Parsing the html of the event page maybe?) Right now I'm changing the value by hand every few hours which is tedious and unnecessary.
Actually there are two parameters, limit and offset. I think that you will have to play with both and continue making calls until one returns less than the max. limit.
Something like this, but in a recursive approach (I'm writting pseudo-code):
offset = 0;
maxLimit = 992;
totalAttendees = count(result)
if (totalAttendees >= maxLimit)
{
// do your stuff with each attendee
offset += totalAttendees;
// make a new call with the updated offset
// and check again
}
I've searched a lot and this is how I fixed it:
The requested URL should look something like this.
Here is where you can test it and here is the code I used:
function events_get_facebook_data($event_id) {
if (!$event_id) {
return false;
}
$token = klicango_friends_facebook_token();
if ($token) {
$parameters['access_token'] = $token;
$parameters['fields']= 'attending_count,invited_count';
$graph_url = url('https://graph.facebook.com/v2.2/' . $event_id , array('absolute' => TRUE, 'query' => $parameters));
$graph_result = drupal_http_request($graph_url, array(), 'GET');
if(is_object($graph_result) && !empty($graph_result->data)) {
$data = json_decode($graph_result->data);
$going = $data->attending_count;
$invited = $data->invited_count;
return array('going' => $going, 'invited' => $invited);
}
return false;
}
return false;
}
Try
SELECT eid , attending_count, unsure_count,all_members_count FROM event WHERE eid ="event"

Categories