I am studying how to write php code of DynamoDB now.
I have encounter some problems.
1) How can I know when connect to db fail
$aws = Aws::factory('config.php');
$client = $aws->get('DynamoDb');
Return client is a object, but i don't know how to check connect success or fail in my php code.
2) Same question when i try to putItem, updateItem and deleteItem
$result = $client->putItem(array(
...
));
I read the AWS SDK of PHP document, but I can't find solution.
These function return value is a array(?) and no attribute is mean success or fail.
Only queryItem() can check by 'Count' attribute.
How should I do in my php code to check these ?
Thanks in advance.
Regarding #1, the "connection" should not be treated the same way as a connection to a MySQL database. Requests to DynamoDB are made over HTTP(S), and this does not require that you establish an upfront connection. When you create the client object, you are not making a connection to DynamoDB, you are just configuring an HTTP client that will make requests to DynamoDB.
Regarding #2, I think you should read the SDK's Getting Started Guide, especially the sections on Working with modeled responses and Detecting and handling errors. Basically, if a request succeeds you get a Guzzle\Service\Resource\Model object, which behaves like an array (i.e., implements PHP's ArrayAccess and Traversable interfaces). If the request fails, an exception is thrown. For DynamoDB, that exception will be Aws\DynamoDb\Exception\DynamoDbException.
try {
$result = $client->putItem(array(
'Table' => 'my-table',
// ...
));
} catch (DynamoDbException $e) {
// The PutItem operation failed.
echo $e->getMessage();
}
Related
I'm using PHP-RQL library to work with RethinkDB,
i need to get changes when new data inserted.
but i'm getting PHP Fatal error: Uncaught RqlDriverError:
Options must be an array.
in api documentation its says:
table->changes(array('squash' => true, 'include_states' => false)) → stream
singleSelection->changes(array('squash' => true, 'include_states' => false)) → stream
Return an infinite stream of objects representing changes to a query.
Example: Subscribe to the changes on a table.
r\table('games')->changes()->run($conn, function($err, $cursor) {
$cursor->each($console->$log)
})
How to subscribe to the changes on a table? This example is doesn't work.
PHP-RQL is fully synchronous at the moment, so you cannot give it a callback.
Instead you get a cursor that you can iterate:
$cursor = r\table('games')->changes()->run($conn);
foreach ($update in $cursor) {
printr($update);
})
What are you using for concurrency? Are you using any async framework (React PHP) or multi-threading or anything like that?
There's no native integration into React with PHP-RQL at the moment, though if you're running a thread-enabled version of PHP you can spawn a thread, open a separate connection inside the thread and use the synchronous cursor interface from within there.
I have a php application that gets requests for part numbers from our server. At that moment, we reach out to a third party API to gather pricing information to make sure we have the latest pricing for that particular request. Sometimes the third party API is slow or it might be down, so we have a database that stores the latest pricing requests for each particular part number that we can use as a fallback. I'd like to run the request to the third party API and the database in parallel using Gearman. Here is the idea:
Receive request
Through gearman, create two jobs:
Request to third party API
MySQL database lookup
Wait in a loop and return the results based on the following conditions:
If the third party API has completed return that result, return that result immediately
If an elapsed time has passed, (e.g. 2 seconds) and the third party API hasn't responded, return the MySQL lookup data
Using gearman, my thoughts were to either run the two tasks in the foreground and break out of runTasks() within the setCompleteCallback() call, or to run them in the background and check in on the two tasks within a separate loop and check in on the tasks using jobStatus().
Unfortunately, I can't get either route to work for me while still getting access to the resulting data. Is there a a better way, or are there some existing examples of how someone has made this work?
I think you've described a single blocking problem, namely the results of an 3rd-party API lookup. There's two ways you can handle this from my point of view, either you could abort the attempt altogether if you decide that you've run out of time or you could report back to the client that you ran out of time but continue on with the lookup anyway, just to update your local cache just in case it happens to respond slower than you would like. I'll describe how I would go about the former problem because that would be easier.
From the client side:
$request = array(
'productId' => 5,
);
$client = new GearmanClient( );
$client->addServer( '127.0.0.1', 4730 );
$results = json_decode($client->doNormal('apiPriceLookup', json_encode( $request )));
if($results && property_exists($results->success) && $results->success) {
// Use local data
} else {
// Use fresh data
}
This will create a job on the job server with a function name of 'apiPriceLookup' and pass it the workload data containing a product id of 5. It will wait for the results to come back, and check for a success property. If it exists and is true, then the api lookup was successful.
The idea is to set the timeout condition then in the worker task, which completely depends on how you're implementing the API lookup. If you're using cURL (or some wrapper around cURL), you can see the answer to how to detect a timeout here.
From the worker side:
$worker= new GearmanWorker();
$worker->addServer();
$worker->addFunction("apiPriceLookup", "apiPriceLookup", $count);
while ($worker->work());
function apiPriceLookup($job) {
$payload = json_decode($job->workload());
try {
$results = [
'data' => PerformApiLookupForProductId($payload->productId),
'success' => true,
];
} catch(Exception $e) {
$results = ['success' => false];
}
return json_encode($results);
}
This just creates a GearmanWorker object and subscribes it the function of apiPriceLookup. It will call the function apiPriceLookup whenever a client submits a task to the job server. That function calls out to another function, PerformApiLookupForProductId, which should be written so as to throw an exception whenever a timeout condition occurs.
I don't think this would be considered using exceptions to control logic flow, I think timeout conditions generally are exceptional (or should be) events. For instance, Guzzle will throw a GuzzleHttp\Exception\RequestException when it has decided to timeout.
Could you tell me if there is a tool to generate a soap client with these requirements:
soap 1.2
the client is based on three different service (so 3 wsdl)
those services have shared types
I found out about:
http://php.net/manual/en/class.soapclient.php
and
http://www.php.net/manual/en/soapclient.soapclient.php
The thing I can't find out searching for it is especially the last two point.
Any help will be appreciated because I can't unserstand how to create it from different sources and how to call a specific service.
I can't test my solution as i don't have 2-3 web services running, but i think this solution will work (if i understood you correctly). Please if you can try it and let me know.
<?php
class wstest {
function __construct($url) {
$this->soapUrl = $url;
try{
$this->client = new SoapClient($this->soapUrl,array('login' => 'wsuser', 'password' => "some_password", "connection_timeout"=>30,'trace'=>true,'keep_alive'=>false,'features' => SOAP_SINGLE_ELEMENT_ARRAYS));
} catch (Exception $e) {
echo $e->getMessage();
}
}
};
$con = new wstest("http://firstwebservice.com/?wsdl");
$con2 = new wstest("http://secondwebservice.com/?wsdl");
$con3 = new wstest("http://thirdwebservice.com/?wsdl");
?>
I'm trying to figure out what you might want to do.
First: One WSDL === one Service === one SoapClient. You cannot mix two WSDL locations on the Soap client level, but depending on your application, might connect each services' results on a higher level.
So if you have three WSDL, then you must instantiate three SoapClient classes to be used. It's not like a single generic HTTP Client which can make requests to any existing webserver.
Second: Unless you provide a classmap to the SoapClient, the return value of any request is only a mixture of stdClass and array. There might be types defined in the WSDL, but PHP does not map them to anything unless you define it.
I would recommend using a classmap with your own defined classes that match the ComplexType definitions in the WSDL. There are some code generators to be googled that might do the job, but the Soap standard is complex, as is the definitionof WSDL, so you might end up doing work by hand.
You can perfectly live without a classmap if the data structures are small.
Third: If the three WSDL share data types, this will not affect PHP in any way. Since without classmap the responses are stdClass and Array, and the Request parameters can be the same, you won't get any benefit from this information.
If on the other hand you go the way of the classmap, I'd expect that the shared types will lead to the same classes generated, so you would also see on the PHP level that a ComplexType from Service A is identical to the ComplexType of Service B.
I am using Zend Framework for my PHP developments and here is a small function I used to execute a query. This is not about an error. The code and everything works fine. But I want to know some concept behind this.
/**
* Get dataset by executing sql statement
*
* #param string $sql - SQL Statement to be executed
*
* #return bool
*/
public function executeQuery($sql)
{
$this->sqlStatement = $sql;
if ($this->isDebug)
{
echo $sql;
exit;
}
$objSQL = $this->objDB->getAdapter()->prepare($sql);
try
{
return $objSQL->execute();
}
catch(Exception $error)
{
$this->logMessage($error->getMessage() . " SQL : " .$sql);
return false;
}
return false;
}
Bellow are unclear areas for me.
How Zend_Db_Table_Abstract Maintain database connections?
Is it creating new connection all the time when I call this function or Does it have some connection pooling?
I didn't write any coding to open or close database connection. So will zend framework automatically close connections?
If this open and close connection works all the time if I execute this function, Is there any performance issue?
Thank you and appreciate your suggestions and opinion on this.
Creating Connection
Creating an instance of an Adapter class does not immediately connect to the RDBMS server. The Adapter saves the connection parameters, and makes the actual connection on demand, the first time you need to execute a query. This ensures that creating an Adapter object is quick and inexpensive. You can create an instance of an Adapter even if you are not certain that you need to run any database queries during the current request your application is serving.
If you need to force the Adapter to connect to the RDBMS, use the getConnection() method. This method returns an object for the connection as represented by the respective PHP database extension. For example, if you use any of the Adapter classes for PDO drivers, then getConnection() returns the PDO object, after initiating it as a live connection to the specific database.
It can be useful to force the connection if you want to catch any exceptions it throws as a result of invalid account credentials, or other failure to connect to the RDBMS server. These exceptions are not thrown until the connection is made, so it can help simplify your application code if you handle the exceptions in one place, instead of at the time of the first query against the database.
Additionally, an adapter can get serialized to store it, for example, in a session variable. This can be very useful not only for the adapter itself, but for other objects that aggregate it, like a Zend_Db_Select object. By default, adapters are allowed to be serialized, if you don't want it, you should consider passing the Zend_Db::ALLOW_SERIALIZATION option with FALSE, see the example above. To respect lazy connections principle, the adapter won't reconnect itself after being unserialized. You must then call getConnection() yourself. You can make the adapter auto-reconnect by passing the Zend_Db::AUTO_RECONNECT_ON_UNSERIALIZE with TRUE as an adapter option.
Closing a Connection
Normally it is not necessary to close a database connection. PHP automatically cleans up all resources and the end of a request. Database extensions are designed to close the connection as the reference to the resource object is cleaned up.
However, if you have a long-duration PHP script that initiates many database connections, you might need to close the connection, to avoid exhausting the capacity of your RDBMS server. You can use the Adapter's closeConnection() method to explicitly close the underlying database connection.
Since release 1.7.2, you could check you are currently connected to the RDBMS server with the method isConnected(). This means that a connection resource has been initiated and wasn't closed. This function is not currently able to test for example a server side closing of the connection. This is internally use to close the connection. It allow you to close the connection multiple times without errors. It was already the case before 1.7.2 for PDO adapters but not for the others.
More information
I'm trying to use Zend_Soap_Client to communicate with an ASP.net web service. Here's my client call:
$client = new Zend_Soap_Client(null, array(
'location' => 'http://example.com/service.asmx',
'uri' => 'http://example.com/'
));
$user = new UserDetail();
$result = $client->UserDetails($user);
However this always gives me the error:
System.NullReferenceException: Object reference not set to an instance of an object. at Service.UserDetails(UserDetail UserDetail)
some googling revealed that this is quite a common problem. The most common solution seemed to be to pass the parameters as an array, so I tried:
$result = $client->UserDetails(array('UserDetail' => $user));
but this gave the same error. I also tried passing the params as a stdClass object, nesting the array in another with 'params' as the key, and a few other things but the error is always the same.
I have the ASP code for the web service itself, the relevant method is:
public Result UserDetails(UserDetail UserDetail) {
[some stuff]
Hashtable ht = new Hashtable();
ht = UserDetail.GenerateData();
}
the error is caused by the GenerateData() call.
I assume the UserDetails method is getting null instead of my object as the parameter, but I'm not sure how I should be calling the method, or how I can debug this further. The majority of the Zend_Soap_Client examples I've found seem to be using WSDL, which this service is not; not sure if that is relevant. Any help appreciated!
I eventually solved this with:
$userDetails = new UserDetails();
$userDetails->UserDetail = $user;
$client->UserDetails($userDetails);
it seems ASP.net expects (and returns) params to be nested in an object/array with the same name as the method being called.
If you have any possibility to change the asp.net code I'd suggest you try an implementation of the method UserDetails without parameters just to make sure that code isn't broken.
I would then create a consumer-method in asp.net, debug the http-request and see how the userdetail-object is serialized/broken down in array form. Then it's "just" a matter of creating a similar http request from php.