I use GAPI (Google Analytics PHP Interface) to retrieve report about my site.
When I save the GAPI response in php variable I get an error.
The error I get:
Call to a member function getUsers() on array
When I run the request like this, I get the error:
//Get Total users who visited the site
$total_visitors=$this->gapi->requestReportData($this->config->item('ga_profile_id'), array('day'), array('users'), array('-day'), '', date('2008-01-01'), date('Y-m-d'), 1, 10000);
$data['total_visitors'] = $total_visitors->getUsers();
When I run the request like this, it works fine:
//Get Total users who visited the site
$this->gapi->requestReportData($this->config->item('ga_profile_id'), array('day'), array('users'), array('-day'), '', date('2008-01-01'), date('Y-m-d'), 1, 10000);
$data['total_visitors'] = $this->gapi->getUsers();
Seems like requestReportData is returning an array and not $this meaning the instance of the object that would allow you to call further methods (Like getUsers()) or manipulate the object. So either check the data in the array returned by requestReportData or you can try this if you really need to use the getUsers() method:
$this->gapi->requestReportData($this->config->item('ga_profile_id'), array('day'), array('users'), array('-day'), '', date('2008-01-01'), date('Y-m-d'), 1, 10000);
$total_visitors = $this->gapi->getUsers();
$data['total_visitors'] = $total_visitors->getUsers();
Related
Im using this laravel package "https://github.com/kanazaca/easypay" to create a MB reference using the Easypay API.
I have this method to create the reference:
public function generateReference()
{
$amount = Session::get('total');
$payment_info = [
't_value' => $amount,
'o_obs' => '',
't_key' => 1
];
$easypay = new EasyPay($payment_info);
$reference = $easypay->createReference();
Session::put('entity', $reference['ep_entity']);
Session::put('reference', $reference['ep_reference']);
Session::put('value', $reference['ep_value']);
}
And it works fine with this code I get some reference codes which can be payed using MB or credit-card.
Then, when a payment is made, easypay will call a "Notification URL".
that we should configure on easypay's backoffice under "URL Configurations".
Because when the easypay service receives the payment they will call the URL that we provided. So I defined a url in the easypay´s backoffice and created a route in the project:
Route::get('/easypay/notification-callback', [
'uses' => 'PaymentController#receiveNotifications',
'as' =>'mb.notifications'
]);
In the api backoffice there is a button that simulates a payment, after this button is clicked nothing happens and if I manually access "http://....ngrok.io/easypay/notification-callback" it appears an empty array:
[]
But in the documentation (https://docs.easypay.pt/workflow/payment-notification) says that when Easypay calls this endpoint, it comes with a few parameters: "ep_cin", "ep_user" and "ep_doc" that will be necessary in the process. So it should not appear an empty array.
Do you know what can be the issue? Im a beginner uing API´s so Im not understnading what the issue can be.
PaymentController receiveNotifications() method:
public function receiveNotifications(Request $request)
{
dd($request->all());
//$easypay = new EasyPay($payment_info);
//$xml = $easypay->processPaymentInfo();
//return \Response::make($xml, '200')->header('Content-Type', 'text/xml'); //must return in text/xml for easypay
}
receiveNotifications() method with log:
public function receiveNotifications(Request $request)
{
//dd($request->all());
Log::info('Showing info: ' .var_export($request->all(),true));
$payment_info = [
'ep_cin' => $request->ep_cin,
'ep_user' => $request->ep_user,
'ep_doc' => $request->ep_doc
];
Log::info('Showing info: ' .var_export($payment_info,true));
//dd($payment_info);
$easypay = new EasyPay($payment_info);
$xml = $easypay->processPaymentInfo();
return \Response::make($xml, '200')->header('Content-Type', 'text/xml'); //must return in text/xml for easypay
}
The session is saved in the session file of the user that visits your website that initiates the payment.
The receiveNotifications would call data from the session file that belongs to the payment gateway server if you were doing anything there. The data isn't matched because the two don't know about each other.
Also, you might not have a Session::save() somewhere in your request handling which writes the session data to file.
Store the reference in a database. Create a model for storing this data, so you can then query that model for the correct reference ID to verify/do stuff.
When the request comes back from the payment gateway use the variables ep_cin, ep_user and ep_doc to get the data from the model.
When you manually request that data you are requesting it with a GET request, which doesn't send the above data along.
The request made by the payment provider will get the result of the DD but that's logged nowhere, so nothing happens.
Log your data for requests triggered by remote api's to see what happens.
I am trying to exclude some objectIDs from being retrieved in the query time. I have tried many approaches:
NOT objectID: 123 tried this in Algolia dashboard and not working.
objectID :- 123 tried this in Algolia dashboard and working but not in the code, using php client.
If possible how to do for multiple objectIDs?
Yes, it possible and even for multiple objectIDs.
The right syntax for the PHP API client is:
$client = new \AlgoliaSearch\Client('APP_ID', 'API_KEY');
$index = $client->initIndex('index_name');
$results = $index->search('query', ['filters' => 'NOT objectID:XX AND NOT objectID:YY']);
If you want to do the same in JS with using pure API client you can do it like:
var client = algoliasearch('APP_ID', 'API_KEY');
var index = client.initIndex('index_name');
index.search('', { filters: 'NOT objectID:XX'}, function(err, content) {
console.log(content.nbHits);
});
I am working with Hotelbeds APItude PHP API to find out the information of available hotel rooms.
Well, I am able to get all information of available hotels through the documentation
But, I am facing problem with getting daily rate of all available hotel rooms.
There is an option in documentation to send request attribute for getting daily rate of each room. Here is the request attribute -
availabilityRQ/#dailyRate -- Boolean -- Optional -- Display the rate day-by-day
dailyRate is an boolean value that confirms is the API ll send back daily rate info (I think so far).
So, in implementation, I send following request parameter -
$rqData = new \hotelbeds\hotel_api_sdk\helpers\Availability();
$rqData->stay = new Stay(DateTime::createFromFormat("Y-m-d", "2016-09-01"),
DateTime::createFromFormat("Y-m-d", "2016-09-10"));
$rqData->hotels = ["hotel" => [1067, 1070,]];
// $rqData->destination = new Destination("PMI");
$occupancy = new Occupancy();
$occupancy->adults = 2;
$occupancy->children = 1;
$occupancy->rooms = 1;
$occupancy->paxes = [new Pax(Pax::AD, 30, "Mike", "Doe"), new Pax(Pax::AD, 27, "Jane", "Doe"), new Pax(Pax::CH, 8, "Mack", "Doe")];
$rqData->occupancies = [$occupancy];
$rqData->dailyRate = TRUE;
$availRS = $apiClient->Availability($rqData);
I checked, everything work fine except the $rqData->dailyRate = TRUE; parameter.
I get following error -
Bad Request: The request is not compliant with the specified version of the API. Error at property dailyRate: Can not construct instance of boolean from String value 'Y': only "true" or "false" recognized
I think, I am missing something like creating boolean parameter for the dailyRate attribute.
How can I solve the issue?
This looks like a bug with their public API or their PHP library. File a bug report.
class Availability extends ApiHelper. class ApiHelper extends DataContainer.
In DataContainer, if (is_bool($item)) return $item ? "Y" : "N";.
https://github.com/hotelbeds-sdk/hotel-api-sdk-php/blob/56b4621bbf488a878f1eb1a194f6a63d928dc9db/src/generic/DataContainer.php#L105
Their DataContainer.php in their library casts boolean values to Y or N. As such, when you do your API request - any values which are true/false get converted to Y/N.
But their API requires true/false.
Some basic background: I help run a gaming channel on YouTube, and I'm building a utility (using PHP) to integrate the channel's content with a companion website. Our playlists are primarily "let's play" series ordered by publication date that follow chronological progress through various games, and I would like the website to display the "latest episode" from a select number of series.
I know that I can work my way to the last video by chaining calls to the following:
$youtubeService->playlistItems->listPlaylistItems(
"snippet",
array(
"playlistId" => $playlistId
"pageToken" => $nextPageToken
)
)
And simply grab the last item in the response set when $nextPageToken is unset.
However, this strikes me as incredibly inefficient--partly because I believe it eats away at my API request quota, but mostly because it's going to slow down the overall response time of the site. Neither of those are ideal.
It seems like there should be an easier way to grab the "latest" video in a playlist either by changing the order of the response, or with some handy function, but I can't find any documentation on it.
I've looked at using the Search functions over the PlaylistItems, but (according to the documentation), Search only accepts Channel IDs as a parameter and not Playlist IDs, which makes me think that its the wrong direction to head.
The short answer here is that this appears to be impossible under the current version of the API. There is no apparent way to essentially select videos in reverse, but I did make a minor change which resulted in whole process being a tad more efficient.
This is the original code:
$items = $youtube->playlistItems->listPlaylistItems(
"snippet",
array(
"playlistId" => $playlistId,
"maxResults" => 50
)
);
while ($items->nextPageToken) {
$items = $youtube->playlistItems->listPlaylistItems(
"snippet",
array(
"playlistId" => $playlistId,
"maxResults" => 50,
"pageToken" => $items->nextPageToken
)
);
}
if ($items) {
return end($items->getItems());
}
This is the fix:
First, I added an object to assist with caching:
class PlaylistCache {
protected $expirationDate;
protected $playlistId;
protected $latestEpisode;
__construct($playlistId, $latestEpisode) {
$this-playlistId = $playlistId;
$this->latestEpisode = $latestEpisode;
$this->expirationDate = time() + 86400;
// get current time + 24 hours
}
public function getLatestEpisode() {
return $this->latestEpisode;
}
public function getPlaylistId() {
return $this->playlistId;
}
public function isExpired() {
return $this->expirationDate < time();
}
}
Then, before polling the API, I look to see if I have a cached version available, and I only resort to the API if that cached version is expired.
$playlistCache = json_decode(get_option('playlist_cache_' . $playlistId));
if ($playlistCache->isExpired()) {
$items = $youtube->playlistItems->listPlaylistItems(
"id",
array(
"playlistId" => $playlistId,
"maxResults" => 50
)
);
while ($items->nextPageToken) {
$items = $youtube->playlistItems->listPlaylistItems(
"id",
array(
"playlistId" => $playlistId,
"maxResults" => 50,
"pageToken" => $items->nextPageToken
)
);
}
if ($items) {
$videoId = end($items->getItems()[0]->getId());
$video = $youtube->videos->listVideos("snippet", array('id' => $videoId))
$video = $video->getItems()[0];
$playlistCache = new PlaylistCache($playlistId, $video);
update_option('playlist_cache_' . $playlistId, json_encode($playlistCache)));
}
}
return $playlistCache->getLatestEpisode();
The other big change here is that my calls to listPlaylistItems() are requesting the id instead of the snippet.
According to the documentation, the snippet costs 2 units of the API quota while requests for the id are 0. So, I don't need to snag the snippet for every single item on every single page. I only need to grab the snippet of the final video in the results, which I can do with the more refined call to
$youtube->videos->listVideos()
With the addition of the PlaylistCache class I only reach out to the API when the cached version of the Playlist returns true on the $playlistCache->isExpired() call, so I only need to poll the entire playlist one time every 24 hours instead of 1 time every page load for every user.
It's still not exactly ideal, but as far as I can tell, it's the best option available right now.
Firstly, you need to get the channelId for the user via HTTP request:
Sample request:
https://www.googleapis.com/youtube/v3/channels?part=snippet&forUsername={0}&key={1}
where {0} is the USERNAME and key is you API key
Then, get the list of videos by calling 'PlaylistItems:list', it returns a collection of playlist items that match the API request parameters. You can retrieve all of the playlist items in a specified playlist or retrieve one or more playlist items by their unique IDs.
Sample request:
https://www.googleapis.com/youtube/v3/search?order=date&part=snippet&channelId={0}&key={1}
From there, you can create an array to get the last video in the playlist. Include max-results parameter, the max-results specifies the maximum number of results that included in the result set.
Typically, the latest video in a playlist in added to the front, not the end.
My existing extJS code passes readData.php a param object
params: {
start: 0,
limit: 1000,
proc_nm: 'sel_bkng_srch',
srchStrng: '',
parms: [[dnStrng,1],[mtStrng,1],[dtFromStrng,1],[dtToStrng,1]],
connId: 'AW'
}
so it can call a stored procedure which I want to share with d3. After lots of attempts, latest is:
d3.json("php/readData.php")
.header("params", "params: {start: 0,limit: 1000,proc_nm: 'sel_bkng_srch',srchStrng: '',parms: [1,1],[2,1],[3,1],[4,1]],connId: 'AW'}")
.get(function(error, data) {
console.log('readData: ', error) ;
});
I do not have the syntax correct to pass the object with d3.json. Everything else is functional I think - php gets called, returns an empty success object (php code needs looking at here) which is picked up back in d3. tia.