normalizing results from the graph or fql.query - facebook-graph-api

I'm running an application that calls both the graph and fql.query for Insights information. (It happens to impersonate dozens of apps and pulls stats) I get a couple different formats back when querying and I'm wondering if there's a better way to 'normalize' results?
It would be nice to have something like this in the SDK, since Facebook formats/ data changes all the time. Where do I make an SDK request?
Code to get key-value---
[code]
public function saveResults($application = null, $result = array())
{
// graph insights are under a data key
if(isset($result['data'])) {
$this->saveResults($application, $result['data']);
}
// graph insights are under a values array
elseif(isset($result['values'])) {
foreach($result['values'] as $k => $v) {
$this->saveResult($application, $result['name'], $v['value'], $result['period'], $v['end_time']);
}
}
// fql.query results have a metric and value
elseif(isset($result['metric'])) {
$this->saveResult($application, $result['metric'], $result['value'], $result['period'], $result['end_time']);
}
// otherwise save key values
elseif(is_array($result)) {
foreach($result as $key => $val) {
if(is_numeric($key) && is_array($val)) {
$this->saveResults($application, $val);
}
else {
$this->saveResult($application, $key, $val);
}
}
}
}
[/code]
Results from fql --
=> Array
(
[0] => Array
(
[app_id] => 1248...
[api_key] => 1248...
[canvas_name] => ABC123
[display_name] => ABC123
[company_name] =>
[developers] => Array
(
)
[restriction_info] => Array
(
)
[daily_active_users] => 0
[weekly_active_users] => 0
[monthly_active_users] => 8
)
)
=> Array
(
[0] => Array
(
[metric] => application_canvas_views
[value] => 0
[period] => 86400
[end_time] => 1317538800
)
)
Results from graph --
=> Array
(
[id] => 1248...
[name] => ABC123
[picture] => https://fbcdn-profile...
[link] => http://www.facebook.com/ABC123
[likes] => 58450
[category] => Product/service
[website] => http://www.ABC123..
=> Array
(
[data] => Array
(
[0] => Array
(
[id] => ABC123.../insights/page_like_adds/day
[name] => page_like_adds
[period] => day
[values] => Array
(
[0] => Array
(
[value] => 60
[end_time] => 2011-01-01T08:00:00+0000
)
[1] => Array
(
[value] => 15
[end_time] => 2011-01-02T08:00:00+0000
)
[2] => Array
(
[value] => 2

From my experience there's no 1:1 correlation between "object properties" being returned from the FQL tables to that of the new graph API objects. There's so many more properties on the FQL tables than there are in the graph from what I've seen. Trying to get them tied together would be like giving a cat a bath. It can be done, but it's going to be painful!!
My suggestions would be to determine from the project requirements what you're trying to accomplish and then determine whether FQL or Graph API is your best route to getting to each requirement. One requirement might be easier done with the graph, and another using FQL. Good luck.

Related

500 Server Error from charge-credit-card.php Authorize.net

I am using the php spl package for the Authorize.net SDK. I verified that SimpleXML, cURL, and JSON are all installed on the server and PHP 5.6+ is being used.
I have verified that the SDK is building the $request object $request->setTransactionRequest( $transactionRequestType);
The returned object using print_r
net\authorize\api\contract\v1\CreateTransactionRequest Object ( [transactionRequest:net\authorize\api\contract\v1\CreateTransactionRequest:private] => net\authorize\api\contract\v1\TransactionRequestType Object ( [transactionType:net\authorize\api\contract\v1\TransactionRequestType:private] => authCaptureTransaction [amount:net\authorize\api\contract\v1\TransactionRequestType:private] => 151.51 [currencyCode:net\authorize\api\contract\v1\TransactionRequestType:private] => [payment:net\authorize\api\contract\v1\TransactionRequestType:private] => net\authorize\api\contract\v1\PaymentType Object ( [creditCard:net\authorize\api\contract\v1\PaymentType:private] => net\authorize\api\contract\v1\CreditCardType Object ( [cardCode:net\authorize\api\contract\v1\CreditCardType:private] => [isPaymentToken:net\authorize\api\contract\v1\CreditCardType:private] => [cryptogram:net\authorize\api\contract\v1\CreditCardType:private] => [cardNumber:net\authorize\api\contract\v1\CreditCardSimpleType:private] => 4111111111111111 [expirationDate:net\authorize\api\contract\v1\CreditCardSimpleType:private] => 2038-12 ) [bankAccount:net\authorize\api\contract\v1\PaymentType:private] => [trackData:net\authorize\api\contract\v1\PaymentType:private] => [encryptedTrackData:net\authorize\api\contract\v1\PaymentType:private] => [payPal:net\authorize\api\contract\v1\PaymentType:private] => [opaqueData:net\authorize\api\contract\v1\PaymentType:private] => ) [profile:net\authorize\api\contract\v1\TransactionRequestType:private] => [solution:net\authorize\api\contract\v1\TransactionRequestType:private] => [callId:net\authorize\api\contract\v1\TransactionRequestType:private] => [authCode:net\authorize\api\contract\v1\TransactionRequestType:private] => [refTransId:net\authorize\api\contract\v1\TransactionRequestType:private] => [splitTenderId:net\authorize\api\contract\v1\TransactionRequestType:private] => [order:net\authorize\api\contract\v1\TransactionRequestType:private] => net\authorize\api\contract\v1\OrderType Object ( [invoiceNumber:net\authorize\api\contract\v1\OrderType:private] => 101 [description:net\authorize\api\contract\v1\OrderType:private] => Golf Shirts ) [lineItems:net\authorize\api\contract\v1\TransactionRequestType:private] => Array ( [0] => net\authorize\api\contract\v1\LineItemType Object ( [itemId:net\authorize\api\contract\v1\LineItemType:private] => Shirts [name:net\authorize\api\contract\v1\LineItemType:private] => item1 [description:net\authorize\api\contract\v1\LineItemType:private] => golf shirt [quantity:net\authorize\api\contract\v1\LineItemType:private] => 1 [unitPrice:net\authorize\api\contract\v1\LineItemType:private] => 20.95 [taxable:net\authorize\api\contract\v1\LineItemType:private] => ) ) [tax:net\authorize\api\contract\v1\TransactionRequestType:private] => net\authorize\api\contract\v1\ExtendedAmountType Object ( [amount:net\authorize\api\contract\v1\ExtendedAmountType:private] => 4.5 [name:net\authorize\api\contract\v1\ExtendedAmountType:private] => level 2 tax name [description:net\authorize\api\contract\v1\ExtendedAmountType:private] => level 2 tax ) [duty:net\authorize\api\contract\v1\TransactionRequestType:private] => [shipping:net\authorize\api\contract\v1\TransactionRequestType:private] => [taxExempt:net\authorize\api\contract\v1\TransactionRequestType:private] => [poNumber:net\authorize\api\contract\v1\TransactionRequestType:private] => 15 [customer:net\authorize\api\contract\v1\TransactionRequestType:private] => net\authorize\api\contract\v1\CustomerDataType Object ( [type:net\authorize\api\contract\v1\CustomerDataType:private] => [id:net\authorize\api\contract\v1\CustomerDataType:private] => 15 [email:net\authorize\api\contract\v1\CustomerDataType:private] => foo#example.com [driversLicense:net\authorize\api\contract\v1\CustomerDataType:private] => [taxId:net\authorize\api\contract\v1\CustomerDataType:private] => ) [billTo:net\authorize\api\contract\v1\TransactionRequestType:private] => net\authorize\api\contract\v1\CustomerAddressType Object ( [phoneNumber:net\authorize\api\contract\v1\CustomerAddressType:private] => [faxNumber:net\authorize\api\contract\v1\CustomerAddressType:private] => [email:net\authorize\api\contract\v1\CustomerAddressType:private] => [firstName:net\authorize\api\contract\v1\NameAndAddressType:private] => Ellen [lastName:net\authorize\api\contract\v1\NameAndAddressType:private] => Johnson [company:net\authorize\api\contract\v1\NameAndAddressType:private] => Souveniropolis [address:net\authorize\api\contract\v1\NameAndAddressType:private] => 14 Main Street [city:net\authorize\api\contract\v1\NameAndAddressType:private] => Pecan Springs [state:net\authorize\api\contract\v1\NameAndAddressType:private] => TX [zip:net\authorize\api\contract\v1\NameAndAddressType:private] => 44628 [country:net\authorize\api\contract\v1\NameAndAddressType:private] => USA ) [shipTo:net\authorize\api\contract\v1\TransactionRequestType:private] => net\authorize\api\contract\v1\NameAndAddressType Object ( [firstName:net\authorize\api\contract\v1\NameAndAddressType:private] => Bayles [lastName:net\authorize\api\contract\v1\NameAndAddressType:private] => China [company:net\authorize\api\contract\v1\NameAndAddressType:private] => Thyme for Tea [address:net\authorize\api\contract\v1\NameAndAddressType:private] => 12 Main Street [city:net\authorize\api\contract\v1\NameAndAddressType:private] => Pecan Springs [state:net\authorize\api\contract\v1\NameAndAddressType:private] => TX [zip:net\authorize\api\contract\v1\NameAndAddressType:private] => 44628 [country:net\authorize\api\contract\v1\NameAndAddressType:private] => USA ) [customerIP:net\authorize\api\contract\v1\TransactionRequestType:private] => [cardholderAuthentication:net\authorize\api\contract\v1\TransactionRequestType:private] => [retail:net\authorize\api\contract\v1\TransactionRequestType:private] => [employeeId:net\authorize\api\contract\v1\TransactionRequestType:private] => [transactionSettings:net\authorize\api\contract\v1\TransactionRequestType:private] => [userFields:net\authorize\api\contract\v1\TransactionRequestType:private] => ) [merchantAuthentication:net\authorize\api\contract\v1\ANetApiRequestType:private] => net\authorize\api\contract\v1\MerchantAuthenticationType Object ( [name:net\authorize\api\contract\v1\MerchantAuthenticationType:private] => *******[transactionKey:net\authorize\api\contract\v1\MerchantAuthenticationType:private] => ***********[sessionToken:net\authorize\api\contract\v1\MerchantAuthenticationType:private] => [password:net\authorize\api\contract\v1\MerchantAuthenticationType:private] => [impersonationAuthentication:net\authorize\api\contract\v1\MerchantAuthenticationType:private] => [fingerPrint:net\authorize\api\contract\v1\MerchantAuthenticationType:private] => [mobileDeviceId:net\authorize\api\contract\v1\MerchantAuthenticationType:private] => ) [refId:net\authorize\api\contract\v1\ANetApiRequestType:private] => ref1453823618 )
The error seems to happen at:
$controller = new AnetController\CreateTransactionController($request);
$response = $controller->executeWithApiResponse( \net\authorize\api\constants\ANetEnvironment::SANDBOX);
Commenting either out one at a time causes the 500 error, if both removed it finishes the script.
The full script:
<?php
require '../../autoload.php';
use net\authorize\api\contract\v1 as AnetAPI;
use net\authorize\api\controller as AnetController;
define("AUTHORIZENET_LOG_FILE", "phplog");
// Common setup for API credentials
$merchantAuthentication = new AnetAPI\MerchantAuthenticationType();
$merchantAuthentication->setName("*********");
$merchantAuthentication->setTransactionKey("******************");
$refId = 'ref' . time();
// Create the payment data for a credit card
$creditCard = new AnetAPI\CreditCardType();
$creditCard->setCardNumber( "4111111111111111" );
$creditCard->setExpirationDate( "2038-12");
$paymentOne = new AnetAPI\PaymentType();
$paymentOne->setCreditCard($creditCard);
// Order info
$order = new AnetAPI\OrderType();
$order->setInvoiceNumber("101");
$order->setDescription("Golf Shirts");
// Line Item Info
$lineitem = new AnetAPI\LineItemType();
$lineitem->setItemId("Shirts");
$lineitem->setName("item1");
$lineitem->setDescription("golf shirt");
$lineitem->setQuantity("1");
$lineitem->setUnitPrice(20.95);
$lineitem->setTaxable(false);
// Tax info
$tax = new AnetAPI\ExtendedAmountType();
$tax->setName("level 2 tax name");
$tax->setAmount(4.50);
$tax->setDescription("level 2 tax");
// Customer info
$customer = new AnetAPI\CustomerDataType();
$customer->setId("15");
$customer->setEmail("foo#example.com");
// PO Number
$ponumber = "15";
//Ship To Info
$shipto = new AnetAPI\NameAndAddressType();
$shipto->setFirstName("Bayles");
$shipto->setLastName("China");
$shipto->setCompany("Thyme for Tea");
$shipto->setAddress("12 Main Street");
$shipto->setCity("Pecan Springs");
$shipto->setState("TX");
$shipto->setZip("44628");
$shipto->setCountry("USA");
// Bill To
$billto = new AnetAPI\CustomerAddressType();
$billto->setFirstName("Ellen");
$billto->setLastName("Johnson");
$billto->setCompany("Souveniropolis");
$billto->setAddress("14 Main Street");
$billto->setCity("Pecan Springs");
$billto->setState("TX");
$billto->setZip("44628");
$billto->setCountry("USA");
//create a transaction
$transactionRequestType = new AnetAPI\TransactionRequestType();
$transactionRequestType->setTransactionType( "authCaptureTransaction");
$transactionRequestType->setAmount(151.51);
$transactionRequestType->setPayment($paymentOne);
$transactionRequestType->setOrder($order);
$transactionRequestType->addToLineItems($lineitem);
$transactionRequestType->setTax($tax);
$transactionRequestType->setPoNumber($ponumber);
$transactionRequestType->setCustomer($customer);
$transactionRequestType->setBillTo($billto);
$transactionRequestType->setShipTo($shipto);
$request = new AnetAPI\CreateTransactionRequest();
$request->setMerchantAuthentication($merchantAuthentication);
$request->setRefId( $refId);
$request->setTransactionRequest( $transactionRequestType);
$controller = new AnetController\CreateTransactionController($request);
$response = $controller->executeWithApiResponse( \net\authorize\api\constants\ANetEnvironment::SANDBOX);
if ($response != null)
{
$tresponse = $response->getTransactionResponse();
if (($tresponse != null) && ($tresponse->getResponseCode()=="1") )
{
echo "Charge Credit Card AUTH CODE : " . $tresponse->getAuthCode() . "\n";
echo "Charge Credit Card TRANS ID : " . $tresponse->getTransId() . "\n";
}
else
{
echo "Charge Credit Card ERROR : Invalid response\n";
}
}
else
{
echo "Charge Credit card Null response returned";
}
?>
Thank you for any help or advice on establishing the connection properly

Coupon Magento API Soap

I’ve a problem with the Coupon API when i make :
$couponCode = "test";
$resultCartCoupon = $proxy->call($sessionId, "cart_coupon.add", array($shoppingCartId, $couponCode));
I always got : Uncaught SoapFault exception: [1083] Coupon is not valid if i try the coupon code in the front end there is no problem. Is there anyone who have ever used this API part with success ?
Thanks.
This error comes from Mage_Checkout_Model_Cart_Coupon_Api::_applyCoupon()
if ($couponCode) {
if (!$couponCode == $quote->getCouponCode()) {
$this->_fault('coupon_code_is_not_valid');
}
}
This looks like it could be a bug, instead it should be if ($couponCode != $quote->getCouponCode()) { but I'm not certain.
It could be that the cart (quote) you're trying to apply the coupon to isn't valid, i.e. doesn't have the qualifying items it needs to receive the coupon. Are you sure $shoppingCartId correctly matches the expected quote in Magento's sales_flat_quote table?
I noticed that the error is in this excerpt:
try {
$quote->getShippingAddress()->setCollectShippingRates(true);
$quote->setCouponCode(strlen($couponCode) ? $couponCode : '')
->collectTotals()
->save();
} catch (Exception $e) {
$this->_fault("cannot_apply_coupon_code", $e->getMessage());
}
In this specific line: ->collectTotals() By removing this stretch , not of error , but not applied the coupon.
After debugging 2-3 hour on API, I have solved this error at my-end. Check below code which i have used in Coupon API.
<?php
$mage_url = 'http://yoursiteurl/api/soap?wsdl';
$mage_user= "API_User"; //webservice user login
$mage_api_key = "API_PASSWORD"; //webservice user pass
$client = new SoapClient($mage_url);
$couponCode = 'couponCode'; // a coupon to be apply
$shoppingCartId = '35'; // a cart Id which i have put test id
$sessionId = $client->login($mage_user, $mage_api_key);
$result = $client->call($sessionId,'cart_coupon.add',array($shoppingCartId,$couponCode));
print_r($result);
?>
The above code gives error that "Uncaught SoapFault exception: [1083] Coupon is not valid". When i debugg the core code i came to know that magento cart.create API insert wrong store id in sales_flat_quote table. I have changed the store id value in sales_flat_quote table manually and again run the Coupon API and after that it works perfectly. So here is the my solution. When you create cart id just run the below update query to change the store id.
<?php
$shoppingCartId = $soap->call( $sessionId, 'cart.create');
$mageFilename = '../app/Mage.php';
require_once $mageFilename;
umask(0);
Mage::app();
$db_write1 = Mage::getSingleton('core/resource')->getConnection('core_write');
$updateQue = "update sales_flat_quote set store_id='1' where entity_id ='".$shoppingCartId."'";
$db_write1->query($updateQue);
// Now run the Coupon API here
?>
Code taken from here : http://chandreshrana.blogspot.in/2015/11/uncaught-soapfault-exception-1083.html
You do not need to write direct SQL to resolve this issue. Just specify store ID parameter in the API call. Example is below is the demo script to apply discount code using Magento SOAP APIs V2 :
/* Set Discount Code */
try
{
$result = $client->shoppingCartCouponAdd($session, $quoteId, 'test123',$storeId);
echo "<br>Apply discount code: ";
var_dump($result);
}
catch(Exception $ex)
{
echo "<br>Discount code Failed: " . $ex->getMessage();
}
To apply discount code, perform following steps :
$quoteId = $client->shoppingCartCreate($session,$storeId);
/* Set cart customer */
$guest = true;
if ($guest)
{
$customerData = array(
"firstname" => "testFirstname",
"lastname" => "testLastName",
"email" => "testEmail#mail.com",
"mode" => "guest",
"website_id" => "1"
);
}
else
{
$customer = array(
"customer_id" => '69301',
"website_id" => "1",
"group_id" => "1",
"store_id" => "1",
"mode" => "customer",
);
}
//Set cart customer (assign customer to quote)
$resultCustomerSet = $client->shoppingCartCustomerSet($session, $quoteId, $customerData,$storeId);
/* Set customer addresses Shipping and Billing */
$addresses = array(
array(
"mode" => "shipping",
"firstname" => "Ahsan",
"lastname" => "testLastname",
"company" => "testCompany",
"street" => "testStreet",
"city" => "Karachi",
"region" => "Sindh",
"postcode" => "7502",
"country_id" => "PK",
"telephone" => "0123456789",
"fax" => "0123456789",
"is_default_shipping" => 0,
"is_default_billing" => 0
),
array(
"mode" => "billing",
"firstname" => "Ahsan",
"lastname" => "testLastname",
"company" => "testCompany",
"street" => "testStreet",
"city" => "Karachi",
"region" => "Sindh",
"postcode" => "7502",
"country_id" => "PK",
"telephone" => "0123456789",
"fax" => "0123456789",
"is_default_shipping" => 0,
"is_default_billing" => 0
)
);
//Set cart customer address
$resultCustomerAddress = $client->shoppingCartCustomerAddresses($session, $quoteId, $addresses,$storeId);
/* Set payment method */
$responsePayment = $client->shoppingCartPaymentMethod($session, $quoteId, array(
'method' => 'cashondelivery',
),$storeId);
/* Set shipping method */
$setShipping = $client->shoppingCartShippingMethod($session, $quoteId, 'flatrate_flatrate',$storeId);
After all above apply discount code,
try
{
$result = $client->shoppingCartCouponAdd($session, $quoteId, 'test123',$storeId);
echo "<br>Apply discount code: ";
var_dump($result);
}
catch(Exception $ex)
{
echo "<br>Discount code Failed: " . $ex->getMessage();
}

Regular expression search and replace in Sublime Text

I have an array in Sublime Text with every city in the U.S as the value and a code which includes the state abbreviation as the key. It looks a little something like this:
$array = array(
"United States of America" => array(
"USAK0001" => "Adak",
"USAK0002" => "Adak Island",
"USAK0003" => "Akiachak",
"USAK0004" => "Akiak",
"USAK0005" => "Akutan",
"USAK0006" => "Alakanuk",
"USAK0007" => "Aleknagik",
"USAK0008" => "Allakaket",
"USAL0028" => "Arlington",
"USAL0029" => "Ashford",
"USAL0030" => "Ashland",
"USAL0031" => "Ashville",
"USAL0032" => "Athens",
"USAL0033" => "Atmore",
"USAL0034" => "Attalla",
"USAL0035" => "Auburn",
"USAL0036" => "Auburn University",
"USAL0037" => "Autaugaville",
"USAL0038" => "Axis",
"USAL0039" => "Baileyton",
)
);
What I need to do is a search and replace to append the state name to the value, based on finding the two letter state abbreviation in the array key code.
So for example, a search that finds "AK" in the key and adds "Alaska" to the value, so they would look like this:
"USAK0001" => "Alaska, Adak",
"USAK0002" => "Alaska, Adak Island",
"USAK0003" => "Alaska, Akiachak",
"USAK0004" => "Alaska, Akiak",
"USAK0005" => "Alaska, Akutan",
"USAK0006" => "Alaska, Alakanuk",
Every key is 8 characters long, but I really don't even know how to begin trying to do this in Sublime Text.
Thanks to nhahtdh, I did this quite easily with a PHP script to merge it. It ended up being as simple as the below, with no need for regex! (Huzzah!)
function merge_states_into_cities( $states, $cities ) {
foreach ( $cities as $key => $array ) {
foreach ( $array as $code => $city ) {
foreach ( $states as $abbrv => $state ) {
if ( strpos( $code, $abbrv, 2 ) ) {
echo '"' . $code . '" => "' . $state . ', ' . $city . '",<br>';
}
}
}
}
}

Drupal services endpoint returns 404 : Could not find resource retrieve

I followed this tutorial :
http://pingv.com/blog/an-introduction-drupal-7-restful-services
and seems everyone have the same problem as mine in the comments.
I made a rest service with drupal services module :
Server = REST
path = api/mohtadoon
mohtadoon_api.module file
<?php
/**
* Implements of hook_services_resources().
*/
function mohtadoon_api_services_resources() {
$api = array(
'mohtadoon' => array(
'operations' => array(
'retrieve' => array(
'help' => 'Retrieves mohtadoon data',
'callback' => 'mohtadoon_api_stories_retrieve',
'file' => array('file' => 'inc', 'module' => 'mohtadoon_api','name' => 'resources/mohtadoon_api'),
'access arguments' => array('access content'),
),
),
),
);
return $api;
}
mohtadoon_api.inc file in resources/mohtadoon_api path
<?php
function mohtadoon_api_stories_retrieve() {
return mohtadoon_api_find_stories();
}
function mohtadoon_api_find_stories() {
// Compose query
$query = db_select('node', 'n');
$query->join('node_revision', 'v', '(n.nid = v.nid) AND (n.vid = v.vid)');
$query->join('users', 'u', 'n.uid = u.uid');
$query->join('field_data_body', 'b', '((b.entity_type = \'node\') AND (b.entity_id = n.nid) AND (b.revision_id = n.vid))');
$query->fields('v', array('timestamp', 'title'));
$query->addField('u', 'name', 'author');
$query->addField('b', 'body_value', 'content');
$query->condition('n.type', 'stories', '=');
$items = $query->execute()->fetchAll();
return $items;
}
?>
when I access the path
http://localhost/mohtadoon01/?q=api/mohtadoon/retrieve
where mohtadoon01 is project path AND ?q= because
the request result is 404 Not found: Could not find resource retrieve.
why is this happens && how to debug something like this ... I didn't deal with drupal before and want to make only one get web service.
You likely need to url encode your string:
http://localhost/mohtadoon01/?q=api%2Fmohtadoon%2Fretrieve
Can't promise this will work though, depending on your drupal configuration.
Slashes are allowed in query string, as per RFC: http://ietf.org/rfc/rfc3986.txt, however many services out of the box do not: you may need to enable AllowEncodedSlashes.
I encountered exactly the same thing using Services 7.x-3.7. To understand the issue, I looked through the following file:
services/servers/rest_server/includes/RESTServer.inc
Given the definition of your service, the code exercised by GET requests for your resource should be:
protected function resolveController($resource, &$operation) {
...
if ( $request_method == 'GET'
&& $canon_path_count >= 1
&& isset($resource['operations']['retrieve'])
&& $this->checkNumberOfArguments($canon_path_count, $resource['operations']['retrieve'])
&& !empty($canonical_path_array[0])
) {
$operation_type = 'operations';
$operation = 'retrieve';
}
...
}
If we now take a look at the code for $this->checkNumberOfArguments():
// We can see from the snippet above that $args_number = $canon_path_count and hence that
// $args_number is always greater than 0
protected function checkNumberOfArguments($args_number, $resource_operation, $required_args = 0) {
$not_required_args = 0;
if (isset($resource_operation['args'])) {
foreach ($resource_operation['args'] as $argument) {
if (isset($argument['source']) && is_array($argument['source']) && isset($argument['source']['path'])) {
if (!empty($argument['optional'])) {
$not_required_args++;
}
else {
$required_args++;
}
}
}
}
// This is where we fall down; Since the service definition does not include any args,
// both $required_args and $not_required_args will equal zero when we get here. Not a problem
// for the first condition (1 >= 0), but clearly the second condition (1 <= 0 + 0) will evaluate
// to false and hence the argument count will not be accepted. As a result, the services module
// does not accept this controller and reports this as '404 not found'
return $args_number >= $required_args && $args_number <= $required_args + $not_required_args;
}
Try adding an argument to your service definition like this:
<?php
/**
* Implements of hook_services_resources().
*/
function mohtadoon_api_services_resources() {
$api = array(
'mohtadoon' => array(
'operations' => array(
'retrieve' => array(
'help' => 'Retrieves mohtadoon data',
'callback' => 'mohtadoon_api_stories_retrieve',
'file' => array('file' => 'inc', 'module' => 'mohtadoon_api','name' => 'resources/mohtadoon_api'),
'access arguments' => array('access content'),
'arg' => array(
array(
'name' => 'entity',
'type' => 'string',
'description' => 'Entity to operate on',
'source' => array('path' => '0'),
'optional' => TRUE,
'default' => '0',
),
),
),
),
),
);
return $api;
}
EDIT:
I think what is confusing people reading the blog post that you linked to (and I was one of those!) is that the URL given as the accessor for the service includes as its final parameter the name of the method that it was intended to invoke ('retrieve'). You could replace 'retrieve' with pretty much anything and the service should still respond (e.g. '/api/blog/pink-rabbit' or, in your case, 'api/mohtadoon/pink-rabbit'). The web service definitions themselves do not indicate what value of parameters can be passed to the endpoint. What counts is what HTTP method is used to access the service and how many parameters are passed to the endpoint (zero or more). Some types of operation require at least a certain number of parameters (e.g. 'retrieve' operations require at least one parameter to identify the specific thing that you want to retrieve).

Self Join Query Doctrine 2 Zendframework 2

I am using Doctrine 2 ORM, Zendframework 2
Entity attribute in Role Entity look like this
/**
*
* #ORM\Column(type="string")
*/
protected $name;
/**
*
* #ORM\OneToMany(targetEntity="\Application\Entity\Role", mappedBy="parent")
*/
protected $children;
/**
*
* #ORM\ManyToOne(targetEntity="\Application\Entity\Role", inversedBy="children")
*
*/
protected $parent;
Mysql Table look like this.
Result I am looking for is an array.
One thing is critical, Any entry in array before apprearing in value must be added as key,
So order is very important.
i.e [site-manager] => guest can't come as first entry(0 index) if [guest] => will not exist before it becaause guest(value) does not exist in array as key
so [guest] => will come first even if it is entered as second record in table
Array(
[guest] =>
[site-manager] => guest
[company-manager] => site-manager
[member] => guest
[staff] => member
[internalstaff] => member
[sales] => staff
[manager] => sales,internalstaff
[admin] => manager
)
I am running this code in my controller which is returning empty array
$qb = $objectManager->createQueryBuilder();
$qb->select('r, p')
->from('\Application\Entity\Role', 'r')
->innerJoin('r.parent','p', 'with','p.id = r.id')
//->where('b.id = ?1')
->orderBy('r.id', 'ASC');
$data = $qb->getQuery()->getArrayResult();
Any help will be appreciated
One solution could be
$qb = $objectManager->createQueryBuilder();
$qb->select('r.name', 'c.name as children')
->from('\Application\Entity\Role', 'r')
->join('r.parent','c');
$data = $qb->getQuery()->getArrayResult();
$refine = array();
foreach ($data as $v)
{
if(is_array($v))
{
if(array_key_exists($v["children"], $refine)){
$refine[$v["name"]][] = $v["children"];
} else {
$refine[$v["children"]] = array();
$refine[$v["name"]][] = $v["children"];
}
}
}
print_r($refine);
Will return following
Array
(
[guest] => Array
(
)
[site-manager] => Array
(
[0] => guest
)
[company-manager] => Array
(
[0] => site-manager
)
[member] => Array
(
[0] => guest
)
[staff] => Array
(
[0] => member
)
[internalStaff] => Array
(
[0] => member
)
[sales] => Array
(
[0] => staff
)
[manager] => Array
(
[0] => internalStaff
[1] => sales
)
[admin] => Array
(
[0] => manager
)
)
You can use implode function if you wish to flatten inner array