Im using a php web form to insert product registrations into a .NET published web service. My insertXmlData function works, but I'm having trouble with error handling. When I attempted to insert a record with an already existing serial number Im getting this returned:
ERROR-5002 - Unique serial number must not be blank System.Exception
I tried this:
try
{
$xmlData = insertXmlData($url, $xml);
}
catch (Exception $e)
{
echo ("Triggered");
throw new Exception( 'There was an error...', 0, $e);
}
But the catch clause doesn't even trigger. Is it a .NET to php thing or is my syntax incorrect? What's my best option for handling errors in this situation?
Related
I'm building a full system with both Laravel and VueJS and at some point, I'm generating pictures from a list of pictures with Image Intervention.
But this process can break, there are many issues that I faced and resolved that can appear in the future.
What would you recommend me to do to have a broken code not stop the rest ? I was thinking on some service that would be called and be independent, asynchronous.
Can Laravel cover that ? I have read about events in both Laravel and Symfony but that is something I never understood.
Greetgins
Well, I was in a similar problem some days ago. Although, My problem was related to inserting data from CSV to the database. So, there were chances of having some different datatype that might generate the error and halt the whole remaining process. So, I used try catch inside my job. I will show you reference, you can modify as you wish:
$error_arr = array();
$error_row_numbers = array();
try{
//Write your code here that might throw error
$row = Model::updateOrCreate(
['id' => $id,
$Arr
);
} catch (\Exception $e) {
//Optionally you can store error message
//and image number which is failed here
$error_arr[] = $e->getMessage();
$error_row_numbers[] = $row_no; //this row_no is different variable
//and should be increased in loop
//to determine exact image
}
I've generated a PHP client library for Magento2 using swagger-codegen. I'm able to connect to Magento and just trying some methods to see how usable the generated client is. It seems like I'm either missing something or maybe the swagger spec published by Magento is not quite there yet.
In particular, invoking the various list operations seems to be marginalized by design, and broken by nature in the generated swagger client. Take for example the operation to list products, /V1/products. Swagger UI indicates this can be parameterized with GET parameters (and in fact seems you must - when I try calling it with no parameters Magento returns an HTTP 400). Here's the sample generated code from the Markdown Swagger generated along with the client library
try {
$result = $api_instance->catalogProductRepositoryV1GetListGet(
$search_criteria_filter_groups_filters_field,
$search_criteria_filter_groups_filters_value,
$search_criteria_filter_groups_filters_condition_type,
$search_criteria_sort_orders_field,
$search_criteria_sort_orders_direction, $search_criteria_page_size,
$search_criteria_current_page);
print_r($result);
} catch (Exception $e) {
echo
'Exception when calling CatalogProductRepositoryVApi->catalogProductRepositoryV1GetListGet: ',
$e->getMessage(), "\n";
}
The first thing I notice is that these parameters only allow a single entry for each field, when the API actually allows you to define multiple filter_groups, multiple filters per filter_group etc. This great blog post helped me understand how the API is supposed to work.
Stepping back though, and supposing a limit of one filter_group and one filter for that group are acceptable and just trying to use the generated client on faith, I tried to put together a simple call
// Fetch all products with a contrived like query
$oMageClient = new Swagger\Client\Api\CatalogProductRepositoryVApi($oApiClient);
$result = $oMageClient->catalogProductRepositoryV1GetListGet('name', '%', 'like');
Magento complains with an HTTP 400, and it's because of the generated client's request params:
searchCriteria[filterGroups][][filters][][field]=name&searchCriteria[filterGroups][][filters][][value]=%&searchCriteria[filterGroups][][filters][][conditionType]=like
What it's done is broken up the parameters into different filter_groups... Sure enough when I look at the generated Swagger\Client\Api\CatalogProductRepositoryVApi:: catalogProductRepositoryV1GetListGetWithHttpInfo method I find the culprit where the query params are set. By changing
// query params
if ($search_criteria_filter_groups_filters_field !== null) {
$queryParams['searchCriteria[filterGroups][][filters][][field]'] = $this->apiClient->getSerializer()->toQueryValue($search_criteria_filter_groups_filters_field);
}// query params
if ($search_criteria_filter_groups_filters_value !== null) {
$queryParams['searchCriteria[filterGroups][][filters][][value]'] = $this->apiClient->getSerializer()->toQueryValue($search_criteria_filter_groups_filters_value);
}// query params
if ($search_criteria_filter_groups_filters_condition_type !== null) {
$queryParams['searchCriteria[filterGroups][][filters][][conditionType]'] = $this->apiClient->getSerializer()->toQueryValue($search_criteria_filter_groups_filters_condition_type);
}
to
// query params
if ($search_criteria_filter_groups_filters_field !== null) {
$queryParams['searchCriteria[filterGroups][0][filters][0][field]'] = $this->apiClient->getSerializer()->toQueryValue($search_criteria_filter_groups_filters_field);
}// query params
if ($search_criteria_filter_groups_filters_value !== null) {
$queryParams['searchCriteria[filterGroups][0][filters][0][value]'] = $this->apiClient->getSerializer()->toQueryValue($search_criteria_filter_groups_filters_value);
}// query params
if ($search_criteria_filter_groups_filters_condition_type !== null) {
$queryParams['searchCriteria[filterGroups][0][filters][0][conditionType]'] = $this->apiClient->getSerializer()->toQueryValue($search_criteria_filter_groups_filters_condition_type);
}
I'm able to get a response back from Magento. So I have a couple of questions
So is there an issue with the JSON Magento is publishing causing the generated Swagger code to be buggy? Or is there some other step I've messed up in generating the client?
It feels like something's not right, because if you look at the blog article and the generated Swagger documentation, Swagger is suggesting the filter_groups parameter is a string, when really it should be an array of objects.
I have been writing a custom auth provider in Symfony2. Everything works so far, but when I enter a wrong password a get an Internal Server error displaying: "LDAP authentication failed".
Now, this is the message that I want to display, but I'd like to display it above my login form and NOT throw an internal server error. In my listener, I have the following:
try {
$authToken= $this->authenticationManager->authenticate($token);
$this->securityContext->setToken($authToken);
return;
} catch (AuthenticationException $failed) {
throw new BadCredentialsException($failed->getMessage(), 0);
}
So is there anyone who can tell me what I need to do to show the user a message, instead of throwing an internal server error?
Thanks in advance.
You can manually add error to your login form in the controller. For example:
$form->get('username')
->addError(new FormError($message));
You should have a controler action that catch the same path of your form to catch the exception.
authentication process will be tryed before the form will be displayed.
You can see this example :
https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Controller/SecurityController.php
So basically I want to be able to somehow do a few if statements to check what exception is being thrown in order for me to echo out some appropriate error messages, e.g.
IF exception is a duplicate record exception in MySQL
THEN echo "User Already exists";
So below I have caught the exception and it prints the default exception error message however this doesn't look good for the user so I want to check what the error is, then print out my own appropriate error message that users would be able to recognise... such as 'User Already Exists'.
try{
$query = "INSERT INTO user VALUES ('', 0, $safe_email, '$hashed_password')";
$result = $db->query($query);
echo '<script type="text/javascript"> alert(\'You have successfully registered.\n A confirmation email has been sent to you.\'); window.location = \'index.php\'; </script>';
}
catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
You should check if the user exists in a "non exceptional" way first, since it's impossible, or at least pretty tricky, to get relevant and consistent information out of the MySQL exception.
For example, if you suddenly decide to add an id field to your table and set it as a primary key, your algorithm would break. If you manage to parse the MySQL error by identifying the error number or something, you're also very tightly coupled to your database and it might be tricky to switch to MariaDB or Postgres or whatever...
Leave the exceptions for the truly exceptional cases, such as
User A and B tries to sign up as "Adam" at roughly the same time
Your server checks UserModel->usernameExists("Adam") of something like that, it returns false in both cases.
Your registration controller continues the registration process for both users, user A gets registered but user B receives an exception, which is actually exceptional and due to this stupid race condition).
If user A registers two weeks before user B tries to register, however, UserModel->usernameExists("Adam") would just return true for user B, and you could show a nice error - or just show that the username is taken, in the registration form.
I'm trying to interact with an Azure Queue using a REST proxy courtesy of the Windows Azure SDK for PHP. Whilst there are plenty of code samples here, I want to check whether a queue exists so that I can create it if necessary, before adding a message to it.
try {
// setup connection string for accessing queue storage
$connectionString = 'DefaultEndpointsProtocol=' . PROTOCOL . ';AccountName=' . ACCOUNT_NAME . ';AccountKey=' . ACCOUNT_KEY;
// create queue REST proxy
$queueRestProxy = ServicesBuilder::getInstance()->createQueueService($connectionString);
// create message
$queueRestProxy->createMessage(QUEUE_NAME, 'Hello World!');
} catch(ServiceException $e){
// Handle exception based on error codes and messages.
// Error codes and messages are here:
// http://msdn.microsoft.com/en-us/library/windowsazure/dd179446.aspx
$code = $e->getCode();
$error_message = $e->getMessage();
echo $code.": ".$error_message."<br />";
}
Creating a queue is as simple as this...
$queueRestProxy->createQueue(QUEUE_NAME);
Should I simply include the queue creation code prior to creating a message or is there a more efficient way to ascertain whether the queue exists before interacting with it?
Normally in other Windows Azure SDKs I have seen methods like createQueueIfNotExists and I'm surprised that this method is missing from PHP SDK. Basically the way this function works is that it tries to create a queue. If the queue by the same name exists in storage, storage service throws a Conflict (409) error.
Since this function is not there, you could do the same i.e. try to create the queue inside its own try/catch block and check the error code. If the error code is 409, you continue otherwise you rethrow the exception. Something like the code below:
try {
// setup connection string for accessing queue storage
$connectionString = 'DefaultEndpointsProtocol=' . PROTOCOL . ';AccountName=' . ACCOUNT_NAME . ';AccountKey=' . ACCOUNT_KEY;
// create queue REST proxy
$queueRestProxy = ServicesBuilder::getInstance()->createQueueService($connectionString);
try {
// now try to create the queue.
$queueRestProxy->createQueue(QUEUE_NAME);
} catch(ServiceException $e){
$code = $e->getCode();
//Now check if the $code is 409 - Conflict. If the error code is indeed 409, you continue otherwise throw the error
}
// create message
$queueRestProxy->createMessage(QUEUE_NAME, 'Hello World!');
} catch(ServiceException $e){
// Handle exception based on error codes and messages.
// Error codes and messages are here:
// http://msdn.microsoft.com/en-us/library/windowsazure/dd179446.aspx
$code = $e->getCode();
$error_message = $e->getMessage();
echo $code.": ".$error_message."<br />";
}
P.S. I have not tried to execute the code, so it may throw errors. This is just to give you an idea.
I've posted an answer below for completeness and to make it easy for people to see the answer at a glance.
Should I simply include the queue creation code prior to creating a
message or is there a more efficient way to ascertain whether the
queue exists before interacting with it?
There are two ways to approach this...
Include the createQueue statement prior to creating a message, but wrap this statement in a try-catch block as directed by Guarav Mantri's answer i.e. ignore 409 errors, but throw an exception for any other types of error.
For information, when you include a createQueue statement prior to creating a message...
if a queue of the same name already exists and the metadata
associated with the existing queue is the same as that passed to the
createQueue statement then the queue will not be created and the
Queue REST Proxy will internally receive a 204 (No Content) status code, but this
response code is not made available to the programmer. So,
essentially, the createQueue statement doesn't cause an
error/exception to be raised in this scenario.
if a queue of the same name already exists and the metadata
associated with the existing queue isn't the same as that passed
to the createQueue statement then the queue will not be created and
the Queue REST Proxy will receive a 409 (Conflict) status code and will raise an
exception which allows the programmer to access this response code and the associated QueueAlreadyExists message.
Source: Create Queue (REST API) - see Remarks section
Create a queueExists function and call it to decide whether or not queue creation is necessary. Here is one way to implement such a function...
public function queueExists($queueRestProxy, $queueName) {
$result = FALSE;
$listQueuesResult = $queueRestProxy->listQueues();
$queues = $listQueuesResult->getQueues();
foreach($queues as $queue) {
if ($queue->getName() === $queueName) {
$result = TRUE;
break;
}
}
return $result;
}
Hope this helps someone!