How to make all scripts not run when api response error? - laravel

I use laravel and I use command laravel to synchronize my database
My command laravel to call api to synchronize like this :
<?php
namespace App\Console\Commands;
...
class MySynchronize extends Command
{
...
public function handle()
{
DB::statement("SET foreign_key_checks=0");
Vendor::truncate();
Location::truncate();
Item::truncate();
DB::statement("SET foreign_key_checks=1");
$requestContent = [
'auth' => ['Administrator', 'www.Secret.com', 'ntlm']
];
//call api vendor
try {
$client = new GuzzleHttpClient();
$apiRequest = $client->request('GET', "http://www.secret.com:1234/ODATA/ODataV4/Company('secret2018')/Vendor", $requestContent);
$jsonResponse = json_decode($apiRequest->getBody(), true);
$data = [];
foreach ($jsonResponse['value'] as $value) {
$created_at = Carbon::now();
$last_modified_at = Carbon::parse($value['Last_Date_Modified']);
$data[] = [
'id' => $value['Code'],
'name' => $value['Name'],
'last_modified_at' => $last_modified_at,
'created_at'=> $created_at,
'updated_at'=> $created_at
];
}
DB::table('vendors')->insert($data);
} catch (RequestException $re) {
// For handling exception.
}
//call api location
try {
$client = new GuzzleHttpClient();
$apiRequest = $client->request('GET', "http://www.secret.com:1234/ODATA/ODataV4/Company('secret2018')/Location", $requestContent);
$jsonResponse = json_decode($apiRequest->getBody(), true);
$data = [];
foreach ($jsonResponse['value'] as $value) {
$created_at = Carbon::now();
$data[] = [
'id' => $value['Code'],
'description' => $value['Name'],
'created_at'=> $created_at,
'updated_at'=> $created_at
];
}
DB::table('locations')->insert($data);
} catch (RequestException $re) {
// For handling exception.
}
//call api item
try {
$client = new GuzzleHttpClient();
$apiRequest = $client->request('GET', "http://www.secret.com:1234/ODATA/ODataV4/Company('secret2018')/Item", $requestContent);
$jsonResponse = json_decode($apiRequest->getBody(), true);
$data = [];
foreach ($jsonResponse['value'] as $value) {
$last_modified_at = Carbon::parse($value['Last_Date_Modified']);
$created_at = Carbon::now();
$data[] = [
'id' => $value['Code'],
'description' => $value['Description'],
'vendor_code' => $value['Vendor_Code']?$value['Vendor_Code']:null,
'last_modified_at' => $last_modified_at,
'created_at'=> $created_at,
'updated_at'=> $created_at
];
}
\DB::table('items')->insert($data);
} catch (RequestException $re) {
// For handling exception.
}
// send output
echo 'synchronize success';
}
}
First I delete all data in the table using truncate. If it is deleted then it will call the api for the insert process to table
My problem is when an error occurs on the api server. For example, server is died or another error. It makes the data in my database empty because I've run truncate
How do I improve the script so that when an error occurs on the api, truncate is not executed?
What is the best way? Do you use try catch in the try catch to handle it?

You should take a look at DB transactions: https://laravel.com/docs/5.7/database#database-transactions
If an exception is thrown within the transaction Closure, the transaction will automatically be rolled back.
So something like that could work:
public function handle()
{
DB::transaction(function () {
// your DB statements
try {
// external API calls
} catch (SomeException $e) {
// If for any reasons you want to catch the exception inside the closure
// (logging maybe?), make sure to rethrow it.
// Otherwise, Laravel won't know it needs to rollback the DB changes
throw $e;
}
});
}

Related

Facebook uploading image with laravel framework

I am trying to uploading image to the facebook page using GraphQL API
Bellow is some code I am using
use SammyK\LaravelFacebookSdk\LaravelFacebookSdk as Facebook;
try {
$token = $token ? $token : $this->access_token;
// $fb = app(Facebook::class);
$fb = new Facebook(array( 'appId' => '366774494090568', 'secret' => '9f847b900176325ce45d87dec94e81ea', 'fileUpload' => true));
//$fb->setFileUploadSupport(true);
//$fb->setDefaultAccessToken($token);
return $fb;
} catch (\Exception $e) {
throw $e;
}
$payload = unserialize($scheduledPost->payload);
$images = $payload['images'];
$timezone = $payload['scheduled']['publishTimezone'];
$appUrl = config("app.url");
$mediaIds = [];
$mediaCount = 0;
foreach($images as $image){
$relativePath = $image['relativePath'];
$fullPath = $appUrl."/".$relativePath;
$media = ["url" => $fullPath, "published" => false];
$uploadResponse = $this->uploadMedia($media);
$mediaId = $uploadResponse['id'];
$mediaIds["attached_media[$mediaCount]"] = "{'media_fbid': '$mediaId'}";
$mediaCount++;
}
public function uploadMedia($media)
{
$fb = $this->setAsCurrentUser($this->access_token);
$response = $fb->post("/{$this->original_id}/photos", $media);
return $response->getDecodedBody();
}
When I use setFileUploadSupport(true), there is error that function is not defined
If I use new Facebook with 'fileupload' => 'true' it gives me error like bellow
exception: "Symfony\Component\Debug\Exception\FatalThrowableError"
file: "C:\Users\king\Documents\work\01_Unicilix\API\vendor\sammyk\laravel-facebook-sdk\src\LaravelFacebookSdk\LaravelFacebookSdk.php"
line: 28
message: "Argument 1 passed to SammyK\LaravelFacebookSdk\LaravelFacebookSdk::__construct() must implement interface Illuminate\Contracts\Config\Repository, array given, called in C:\Users\king\Documents\work\01_Unicilix\API\app\Traits\Facebook\FacebookTrait.php on line 22
This code was very correct.
The problem was I can get storage image from url because of the server(ubunt) permmission.

Single column not being updated in laravel 5

I am tying to update a single column of a table messages and I have the following code:
public function messageSeen(Request $request){
$data = Message::find($request->id);
$success = Message::where('id', $request->id)->update(array('is_seen' => 1));
if($success){
return response()->json(['status'=>'success'], 200);
} else {
return response()->json(['status'=>'Data not updated'], 404);
}
}
I am getting the response Data not updated. If you question, does the column is_seen exists? then yes it does. Even I tried fetching the data having id $request->id, it gives the proper data. I wonder why is the data not being updated? Am I doing right thing to update column or is there an way out to update column in different way?
I tried the other way like the following:
public function messageSeen(Request $request){
$id = $request->id;
$result = Message::find($id);
dd($result->message);
$data = array();
$data['is_seen'] = 1;
$data['message'] = $result->message;
$data['user_id'] = $result->user_id;
$data['conversation_id'] = $result->conversation_id;
$this->messages->fill($data);
$success = $this->messages->save();
if($success){
return response()->json(['status'=>'success'], 200);
} else {
return response()->json(['status'=>'Data not updated'], 404);
}
}
But here I am getting unexpected thing with this method. Here I am being able to do dd($result) and being able to get data like this:
#attributes: array:9 [
"id" => 22
"message" => "How are you?\r\n"
"is_seen" => 0
"deleted_from_sender" => 0
"deleted_from_receiver" => 0
"user_id" => 2
"conversation_id" => 1
"created_at" => "2019-09-29 03:42:39"
"updated_at" => "2019-09-29 03:42:39"
]
however, if I tried to do dd($result->message) then I get null! What am I doing wrong?
I tried the following code:
public function messageSeen(Request $request){
$id = $request->id;
$result = Message::find($id);
$data = array();
$data['is_seen'] = 1;
$data['message'] = $result[0]['message'];
$data['user_id'] = $result[0]['user_id'];
$data['conversation_id'] = $result[0]['conversation_id'];
$this->messages->fill($data);
$success = $this->messages->save();
if($success){
return response()->json(['status'=>'success'], 200);
} else {
return response()->json(['status'=>'Data not updated'], 404);
}
}
and it worked but instead of updating it is adding new column when the message is seen. But first I don't understand why do I have to do $result[0]['key'] in the first place.
You need to specify which fields in your table can be mass assigned, by adding or updating the $fillable property of your model:
protected $fillable = [..., 'is_seen', 'message', ...];
This is required for the create() and update() methods, as those accept "mass" variables in the array you pass in. Whereas with save() you have to manually, explicitly, assign the properties on the model, so there is no risk of accidentally saving something you didn't mean to. And this is exactly the behaviour you are seeing - update() is not working, but save() is.
You should try this
public function messageSeen(Request $request) {
$input = Request::all();
$data = Message::find($input['id']);
if (!empty($data)) {
$update = array();
$update['is_seen'] = 1;
$success = Message::where('id', $input['id'])->update($update);
if ($success) {
return response()->json(['status' => 'success'], 200);
} else {
return response()->json(['status' => 'Something went wrong'], 400);
}
} else {
return response()->json(['status' => 'Data not updated'], 404);
}
}
Value depends on data type of is_seen are string or integer

Object of class Illuminate\Routing\Redirector could not be converted to string. srmklive/laravel-paypal

I am currently working on a paypal checkout using paypal and https://github.com/srmklive/laravel-paypal. I'm using the express checkout which I modified it a little bit to fit the requirements of the my project. During testing it is working in a couple of tries, paypal show and payment executes properly but when I tried to run the exact same code. I get this error I don't know what it means.
I tried to check my routes if it all of the errors happens to my routes but all of it are working properly. I also tried dump and die like dd("check") just to check if its really going to my controller and it does. I did this in the method "payCommission" (this where the I think the error happens)
This is my route for the controller
api.php
Route::get('service/commissionfee/payment' , 'api\service\ExpressPaymentController#payCommission');
Route::get('paypal/ec-checkout-success', 'api\service\ExpressPaymentController#payCommissionSuccess');
ExpressPaymentController.php
<?php
namespace App\Http\Controllers\api\service;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Srmklive\PayPal\Services\ExpressCheckout;
class ExpressPaymentController extends Controller
{
protected $provider;
public function __construct()
{
try {
$this->provider = new ExpressCheckout();
}
catch(\Exception $e){
dd($e);
}
}
public function payCommission(Request $request)
{
$recurring = false;
$cart = $this->getCheckoutData($recurring);
try {
$response = $this->provider->setExpressCheckout($cart, $recurring);
return redirect($response['paypal_link']);
} catch (\Exception $e) {
dd($e);
return response()->json(['code' => 'danger', 'message' => "Error processing PayPal payment"]);
}
}
public function payCommissionSuccess(Request $request)
{
$recurring = false;
$token = $request->get('token');
$PayerID = $request->get('PayerID');
$cart = $this->getCheckoutData($recurring);
// ? Verify Express Checkout Token
$response = $this->provider->getExpressCheckoutDetails($token);
if (in_array(strtoupper($response['ACK']), ['SUCCESS', 'SUCCESSWITHWARNING'])) {
if ($recurring === true) {
$response = $this->provider->createMonthlySubscription($response['TOKEN'], 9.99, $cart['subscription_desc']);
if (!empty($response['PROFILESTATUS']) && in_array($response['PROFILESTATUS'], ['ActiveProfile', 'PendingProfile'])) {
$status = 'Processed';
} else {
$status = 'Invalid';
}
} else {
// ? Perform transaction on PayPal
$payment_status = $this->provider->doExpressCheckoutPayment($cart, $token, $PayerID);
$status = $payment_status['PAYMENTINFO_0_PAYMENTSTATUS'];
}
return response()->json(['success' => "payment complete"]);
}
}
private function getCheckoutData($recurring = false)
{
$data = [];
$order_id = 1;
$data['items'] = [
[
'name' => 'Product 1',
'price' => 9.99,
'qty' => 1,
],
];
$data['return_url'] = url('api/paypal/ec-checkout-success');
// !
$data['invoice_id'] = config('paypal.invoice_prefix').'_'.$order_id;
$data['invoice_description'] = "Commission Fee payment";
$data['cancel_url'] = url('/');
$total = 0;
foreach ($data['items'] as $item) {
$total += $item['price'] * $item['qty'];
}
$data['total'] = $total;
return $data;
}
}
Error I am getting
Object of class Illuminate\Routing\Redirector could not be converted to string
Thank you in advance
you may just go to the config/paypal.php and edit
'invoice_prefix' => env('PAYPAL_INVOICE_PREFIX', 'Life_saver_'),
you may use _ underline in this like Life_saver_, dont forget use underline at the end too.

getting started in graphql-php: how to add resolver functions to schema from .graphql file?

I'm totally new to GraphQL and wanted to play arouund with graphql-php in order to build a simple API to get started. I'm currently reading the docs and trying out the examples, but I'm stuck quite at the beginning.
I want my schema to be stored in a schema.graphql file instead of building it manually, so I followed the docs on how to do that and it is indeed working:
<?php
// graph-ql is installed via composer
require('../vendor/autoload.php');
use GraphQL\Language\Parser;
use GraphQL\Utils\BuildSchema;
use GraphQL\Utils\AST;
use GraphQL\GraphQL;
try {
$cacheFilename = 'cached_schema.php';
// caching, as recommended in the docs, is disabled for testing
// if (!file_exists($cacheFilename)) {
$document = Parser::parse(file_get_contents('./schema.graphql'));
file_put_contents($cacheFilename, "<?php\nreturn " . var_export(AST::toArray($document), true) . ';');
/*} else {
$document = AST::fromArray(require $cacheFilename); // fromArray() is a lazy operation as well
}*/
$typeConfigDecorator = function($typeConfig, $typeDefinitionNode) {
// In the docs, this function is just empty, but I needed to return the $typeConfig, otherwise I got an error
return $typeConfig;
};
$schema = BuildSchema::build($document, $typeConfigDecorator);
$context = (object)array();
// this has been taken from one of the examples provided in the repo
$rawInput = file_get_contents('php://input');
$input = json_decode($rawInput, true);
$query = $input['query'];
$variableValues = isset($input['variables']) ? $input['variables'] : null;
$rootValue = ['prefix' => 'You said: '];
$result = GraphQL::executeQuery($schema, $query, $rootValue, $context, $variableValues);
$output = $result->toArray();
} catch (\Exception $e) {
$output = [
'error' => [
'message' => $e->getMessage()
]
];
}
header('Content-Type: application/json; charset=UTF-8');
echo json_encode($output);
This is what my schema.graphql file looks like:
schema {
query: Query
}
type Query {
products: [Product!]!
}
type Product {
id: ID!,
type: ProductType
}
enum ProductType {
HDRI,
SEMISPHERICAL_HDRI,
SOUND
}
I can query it for example with
query {
__schema {types{name}}
}
and this will return the metadata as expected. But of course now I want to query for actual product data and get that from a database, and for that I'd need to define a resolver function.
The docs at http://webonyx.github.io/graphql-php/type-system/type-language/ state: "By default, such schema is created without any resolvers. We have to rely on default field resolver and root value in order to execute a query against this schema." - but there is no example for doing this.
How can I add resolver functions for each of the types/fields?
This approach works without instantiating a Server. In my case, I already have a server and can read HTTP data, all I needed was to read the GraphQL schema and run the query. First I read the schema from a file:
$schemaContent = // file_get_contents or whatever works for you
$schemaDocument = GraphQL\Language\Parser::parse($schemaContent);
$schemaBuilder = new GraphQL\Utils\BuildSchema($schemaDocument);
$schema = $schemaBuilder->buildSchema();
Then I execute the query passing a custom field resolver:
$fieldResolver = function() {
return call_user_func_array([$this, 'defaultFieldResolver'], func_get_args());
};
$result = GraphQL\GraphQL::executeQuery(
$schema,
$query, // this was grabbed from the HTTP post data
null,
$appContext, // custom context
$variables, // this was grabbed from the HTTP post data
null,
$fieldResolver // HERE, custom field resolver
);
The field resolver looks like this:
private static function defaultFieldResolver(
$source,
$args,
$context,
\GraphQL\Type\Definition\ResolveInfo $info
) {
$fieldName = $info->fieldName;
$parentType = $info->parentType->name;
if ($source === NULL) {
// this is the root value, return value depending on $fieldName
// ...
} else {
// Depending on field type ($parentType), I call different field resolvers.
// Since our system is big, we implemented a bootstrapping mechanism
// so modules can register field resolvers in this class depending on field type
// ...
// If no field resolver was defined for this $parentType,
// we just rely on the default field resolver provided by graphql-php (copy/paste).
$fieldName = $info->fieldName;
$property = null;
if (is_array($source) || $source instanceof \ArrayAccess) {
if (isset($source[$fieldName])) {
$property = $source[$fieldName];
}
} else if (is_object($source)) {
if (isset($source->{$fieldName})) {
$property = $source->{$fieldName};
}
}
return $property instanceof \Closure
? $property($source, $args, $context)
: $property;
}
}
Here's what I ended up doing...
$rootResolver = array(
'emptyCart' => function($root, $args, $context, $info) {
global $rootResolver;
initSession();
$_SESSION['CART']->clear();
return $rootResolver['getCart']($root, $args, $context, $info);
},
'addCartProduct' => function($root, $args, $context, $info) {
global $rootResolver;
...
return $rootResolver['getCart']($root, $args, $context, $info);
},
'removeCartProduct' => function($root, $args, $context, $info) {
global $rootResolver;
...
return $rootResolver['getCart']($root, $args, $context, $info);
},
'getCart' => function($root, $args, $context, $info) {
initSession();
return array(
'count' => $_SESSION['CART']->quantity(),
'total' => $_SESSION['CART']->total(),
'products' => $_SESSION['CART']->getProductData()
);
},
and then in the config
$config = ServerConfig::create()
->setSchema($schema)
->setRootValue($rootResolver)
->setContext($context)
->setDebug(DEBUG_MODE)
->setQueryBatching(true)
;
$server = new StandardServer($config);
It feels rather hack-ish to me, and I should probably outsource the resolvers into separate files, but it works... Still baffled that there are no simple examples for this task, maybe in an even better way than my solution...
I'm using root value for this:
<?php
require("vendor/autoload.php") ;
require("exemplo-graphql.php");
require("Usuario.php");
use GraphQL\GraphQL;
use GraphQL\Type\Schema;
use GraphQL\Utils\BuildSchema;
$query = $_REQUEST['query'];
$typeConfigDecorator = function($typeConfig, $typeDefinitionNode) {
$name = $typeConfig['name'];
// ... add missing options to $typeConfig based on type $name
return $typeConfig;
};
$contents = file_get_contents('schema.graphql');
$schema = BuildSchema::build($contents, $typeConfigDecorator);
// $rawInput = file_get_contents('php://input');
$input = json_decode($query, true);
$query = $input['query'];
$variableValues = isset($input['variables']) ? $input['variables'] : null;
try {
// $rootValue = ['prefix' => 'You said: '];
$rootValue = [
'usuario' => function($root, $args, $context, $info) {
$usuario = new Usuario();
$usuario->setNome("aqui tem um teste");
$usuario->setEmail("aqui tem um email");
return $usuario;
},
'echo' => function($root, $args, $context, $info) {
return "aqui tem um echooo";
},
'adicionarUsuario' => function ($root, $args, $context, $info) {
$usuario = new Usuario();
$usuario->setNome("aqui tem um teste");
$usuario->setEmail("aqui tem um email");
return $usuario;
}
];
$result = GraphQL::executeQuery($schema, $query, $rootValue, null,
$variableValues);
if ($result->errors) {
$output = [
'errors' => [
[
'message' => $result->errors
]
]
];
} else {
$output = $result->toArray();
}
} catch (\Exception $e) {
$output = [
'errors' => [
[
'message' => $e->getMessage()
]
]
];
}
header('Content-Type: application/json');
echo json_encode($output);
By default, schema which was created by using BuildSchema::build() was created without any resolvers. So we need to define our custom resolvers as follows:
$contents = file_get_contents($this->projectDir.'/config/schema.graphql');
$typeConfigDecorator = function($typeConfig, $typeDefinitionNode) {
$name = $typeConfig['name'];
if ($name === 'Query') {
$typeConfig['resolveField'] =
function ($source, $args, $context, ResolveInfo $info) {
if ($info->fieldDefinition->name == 'login') {
if ($args['userName'] === 'test' && $args['password'] === '1234') {
return "Valid User.";
} else {
return "Invalid User";
}
} elseif ($info->fieldDefinition->name == 'validateUser') {
if ($args['age'] < 18) {
return ['userId' => $args['userId'], 'category' => 'Not eligible for voting'];
}
}
}
}
;
}
return $typeConfig;
};
$schema = BuildSchema::build($contents, $typeConfigDecorator);
The above example I have added resolvers for my two queries namely 'login' and 'validateUser.'
No need to define any root values and defaultFieldResolver. Our custom resolvers are enough.

Laravel4 Doesnt show old::input()

New to laravel4 and cant get the basic things to work such as:
function doRegister() {
try {
$email = Input::get('email');
$type = Input::get('type'); // <-- Data from radio button
# Check if email exists
if ( User::where('email','=',$email)->count() > 0 ) {
# This account already exists
throw new Exception( 'This email already in use by someone else.' );
}
} catch (Exception $e) {
return Redirect::to('/')->withInput()->with('message', $e->getMessage() );
}
}
Now on the homepage controller (which is /) I cant read the value of Input::old('type');
and it returns empty. How come?
Try this instead:
function doRegister()
{
$rules = array('email' => 'required|email|unique:users');
$validator = Validator::make(Input::all(), $rules);
if ($validator->fails()) {
return Redirect::to('/')->withInput()>withErrors($validator);
}
else {
$email = Input::get('email');
$type = Input::get('type');
// Register...
}
}
You can retrieve validation errors using:
$errors->first('email');

Resources