Laravel 5 REST client CRUD - php

Is there a way in Laravel 5 to do a CRUD using REST? I have a REST API already using CodeIgniter and I want my Laravel application to communicate with it.
So let's say I have this url to get all gender: http://api.local/api/api_gender/gender
In my controller, it seems I can do something like this:
$results = json_decode(file_get_contents('http://api.local/api/api_gender/gender/'));
But I dont know if this is the right way to do it.
Now, how could I do it if I want to add a new gender in Laravel? In CI, I could simply use Phil's rest library and just use $this->rest->put('http://api.local/api/api_gender/gender/', $parameters)

I would use Guzzle, a very popular, flexible HTTP client for PHP. As far as I know, it is one of the most used packages to make HTTP requests in PHP.
$client = new GuzzleHttp\Client();
$client->put('http://api.local/api/api_gender/gender/', ['json' => ['foo' => 'bar']]);
// or
$client->put('http://api.local/api/api_gender/gender/', ['query' => ['foo' => 'bar']]);

Related

How can I integrate elasticsearch to mysql using php

I was working on a project which is required to use elasticsearch. I followed the guide: https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/index.html
It works perfectly for me:
require 'vendor/autoload.php';
use Elasticsearch\ClientBuilder;
$hosts = [
'myhost'
];
$client = ClientBuilder::create() // Instantiate a new ClientBuilder
->setHosts($hosts) // Set the hosts
->build();
$params = [
'index' => 'php-demo-index',
'type' => 'doc',
'id' => 'my_id',
'body' => ['testField' => 'abc']
];
$response = $client->index($params);
print_r($response);
Now, that's only a basic thing. Now, what I want is to integrate this with Mysql i.e. as I update or insert into my table in database, it get indexed automatically in elasticsearch.
I know, we have Logstash that can query db constantly after a given interval and index into elasticsearch. But, I want indexing to be happened automatically after insertion into db using PHP without logstash.
I know such a library in (nodeJs+mongodb) ie. mongoosastics: https://www.npmjs.com/package/mongoosastic. Is there any library available in php which can do such a task automatically. Please provide me the sample code, if you know one.
There is indeed libraries to automate this task. However it generally requires the use of an ORM like Doctrine in order gracefully hook in to your database implementation. If you are able to use the Symfony framework in your project there is a library called FOSElasticaBundle which keeps your indices in sync with your database operations.

Laravel dispatch plain json on queue

I have 2 simple questions overall. Im currently looking into some event handling in Laravel and would like to use RabbitMQ as my event store. Therefor i installed this package to start with: https://github.com/php-enqueue/enqueue-dev
To get started i registered it and i am able to push messages on to RabbitMQ:
$job = (new Sendemail())->onQueue('email')->onConnection('interop');
dispatch($job);
The problem however is that Laravel pushes a certain format on the queue and i can't figure out how to change that. An example message would be:
{
"job":"Illuminate\\\\Queue\\\\CallQueuedHandler#call",
"data":{
"command":"O:29:\\"Acme\\Jobs\\FooJob\\":4:{s:11:\\"fooBar\\";s:7:\\"abc-123\\";s:5:\\"queue\\";N;s:5:\\"delay\\";N;s:6:\\"\\u0000*\\u0000job\\";N;}"
}
}
So the question is, how can i change this? The main reason on this is that the consumer side is not even a PHP application which also can not interpret the PHP serialized model. Therefor im looking for a way to push a plain JSON object instead.
From the other hand i would also like to understand how you could build a custom listener? For the listener the same thing happens. Laravel tries to read the method but when i push plain JSON this will never work. Isn't there a way to register a handler on a topic and do further handling of the payload of the message within the handler itself?
There is a simple way for your purpose:
First install this package for rabbit:
vladimir-yuldashev/laravel-queue-rabbitmq
and in controller:
Queue::connection('rabbitmq')->pushRaw('{you can generate a json format here}', 'queue_name');
you can generate a json and put in this command.
There's a laravel-queue library that works with the php-enqueue library you linked to make it compatible with Laravel's built in queue system that Florian mentioned.
By default, it will still use a serialized object, but I think that can be overridden. If you look in Queue.php, createObjectPayload() on line 130 in the core Laravel Framework, that's where the job is being serialized.
If you extend the Queue class in the laravel-queue library, you should be able to change createObjectPayload to look something like this:
protected function createObjectPayload($job, $queue)
{
$payload = $this->withCreatePayloadHooks($queue, [
'displayName' => $this->getDisplayName($job),
'job' => 'Illuminate\Queue\CallQueuedHandler#call',
'maxTries' => $job->tries ?? null,
'timeout' => $job->timeout ?? null,
'timeoutAt' => $this->getJobExpiration($job),
'data' => [
'commandName' => $job,
'command' => $job,
],
]);
return array_merge($payload, [
'data' => [
'commandName' => get_class($job),
'command' => json_encode(clone $job),
],
]);
}
That should JSON encode the job data instead of serializing it. You may even be able to remove the encoding altogether, as I think it's already JSON encoded somewhere up the chain.

PHP: how to send push notifications to Apple device

Our iOS app should receive push notification. Following this tutorial I implemented these methods in application delegate:
didRegisterForRemoteNotificationsWithDeviceToken
and
didFailToRegisterForRemoteNotificationsWithError
which are called by didFinishLaunchingWithOptions and it seems that the device is correctly registered in our MySQL service. Moreover, I have just created a pem sandbox certification that I will use for testing. Now, I need to know what I should do at the backend in PHP. Which code is required? We are using Zend framework so I should implement function preparetosend_apple()in my mapper and sendtoappleAction() in our controller but I don't know where to start from and how to test it. Thank you!
First thing is sending push notification directly from application is not a good idea as this call can be blocking one (means the rest of the codeblock will wait for its completion). So I suggest using background processor/message queuing services (like gearman, zero mq, etc.).
Secondly easiest solution will be using Parse like services. Parse allows registering the app using the certificates you mentioned and has SDK for php (composer based).
In the background service you just call the API from SDK. Like:
use Parse\ParseClient;
use Parse\ParseInstallation;
use Parse\ParsePush;
ParseClient::initialize($appId, $restKey, $masterKey, $curlDebug);
...
...
...
Using channel in parse
$response = ParsePush::send(array(
"channels" => ["channel-$userId"],
"data" => $data,
));
OR using custom query
$query = ParseInstallation::query();
$query->equalTo('userId', "user-$userId");
$response = ParsePush::send(array(
"where" => $query,
"data" => $data,
));
The best part of using parse - I will say using other interesting features like -- broadcast messages, device listings, etc.
Hope this may help you.

How to avoid sending a Guzzle request after instantiation?

Context: Laravel 5. Guzzle ~5.2. PHP 5.4. I'm building a class to interact with an external API. I'm providing this class with a Guzzle client using a Service Provider, to avoid instantiating the client within a method.
I want to cache the results. If the user is asking for something that is found in the cache, return it instead of performing a request to said API.
Problem: If I build up a Guzzle client and don't perform a request, the application crashes. Not even a stack trace from PHP. Actually, if I'm using Laravel's artisan serve, a Windows error message shows up saying, PHP CLI has stopped working.
For now, I'm passing the Guzzle client to the method on my class, every single time I call it.
Is there a way to just instantiate the Guzzle client without sending a request? What other route would you choose to achieve this? Is that intended behaviour?
tl;dr RTM
Longer version (from the docs):
Creating Requests
You can create a request without sending it. This is useful for building up requests over time or sending requests in concurrently.
$request = $client->createRequest('GET', 'http://httpbin.org', [
'headers' => ['X-Foo' => 'Bar']
]);
// Modify the request as needed
$request->setHeader('Baz', 'bar');
After creating a request, you can send it with the client’s send() method.
$response = $client->send($request);
from here:
http://docs.guzzlephp.org/en/stable/quickstart.html#making-a-request
use GuzzleHttp\Psr7\Request;
$client = new Client([
// Base URI is used with relative requests
'base_uri' => 'http://httpbin.org',
// You can set any number of default request options.
'timeout' => 2.0,
]);
$request = new Request('PUT', 'http://httpbin.org/put');
$response = $client->send($request, ['timeout' => 2]);

Can Slim PHP make request to other services?

I'm currently building an AngularJS application with a PHP backend. The routing is done using Slim PHP and I've found an AngularJs module to do token-based authentication. In the module example for the backend they use Laravel and a client called GuzzleHttp\Client(). Now, I'm not sure what GuzzleHttp do that Slim PHP don't (if any) but I'm trying to follow along their example but I don't want to install 2 frameworks that could essentially do the same thing.
So I have my routing done so that when a request is made to the backend (auth/google) it'll do this:
public function google()
{
$app = \Slim\Slim::getInstance();
$request = $app->request()->getBody();
$body = json_decode($request);
$accessTokenUrl = 'https://accounts.google.com/o/oauth2/token';
$peopleApiUrl = 'https://www.googleapis.com/plus/v1/people/me/openIdConnect';
$params = array(
'code' => $body->code,
'client_id' => $body->clientId,
'redirect_uri' => $body->redirectUri,
'grant_type' => 'authorization_code',
'client_secret' => GOOGLE_SECRET
);
$client = new GuzzleHttp\Client();
// Step 1. Exchange authorization code for access token.
$accessTokenResponse = $client->post($accessTokenUrl, ['body' => $params]);
$accessToken = $accessTokenResponse->json()['access_token'];
$headers = array('Authorization' => 'Bearer ' . $accessToken);
// Step 2. Retrieve profile information about the current user.
$profileResponse = $client->get($peopleApiUrl, ['headers' => $headers]);
$profile = $profileResponse->json();
// Step 3a. If user is already signed in then link accounts.
if (Request::header('Authorization'))
{
$user = User::where('google', '=', $profile['sub']);
if ($user->first())
{
return Response::json(array('message' => 'There is already a Google account that belongs to you'), 409);
}
$token = explode(' ', Request::header('Authorization'))[1];
$payloadObject = JWT::decode($token, Config::get('secrets.TOKEN_SECRET'));
$payload = json_decode(json_encode($payloadObject), true);
$user = User::find($payload['sub']);
$user->google = $profile['sub'];
$user->displayName = $user->displayName || $profile['name'];
$user->save();
return Response::json(array('token' => $this->createToken($user)));
}
// Step 3b. Create a new user account or return an existing one.
else
{
$user = User::where('google', '=', $profile['sub']);
if ($user->first())
{
return Response::json(array('token' => $this->createToken($user->first())));
}
$user = new User;
$user->google = $profile['sub'];
$user->displayName = $profile['name'];
$user->save();
return Response::json(array('token' => $this->createToken($user)));
}
}
Now this won't work because I don't have GuzzleHttp installed but my question is: can I do this in Slim PHP or do I need GuzzleHttp to complement it?
Guzzle is a code based HTTP client package/framework which also contains DOM crawling functionality not a micro-framework, thus it is not analogous to Slim.
From their Readme:
Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and trivial to integrate with web services.
Slim does not provide this functionality directly because it doesnt fall under what Slim is meant to do which is transform HTTP requests into HTTP responses (and the core things that need to happen in between).
Since your example is in Guzzle and it implements what you are trying to do i would probably use Guzzle. However, you could do the same types of thing (ie. interact with an external web service) using cURL, ext/http, or another HTTP client package. There are several.
Slim is a micro-framework that provides basically client requests and responses, coming from the application. It means that Slim responds to request, it doesn't make requests to external HTTP, for instance. The idea of Slim is to provide routes, do stuff when it comes and responds to the client.
If you need to use external calls, you'll need to use any HTTP Client, that'll provide the "ability" to make requests and threat with the response. You can use curl natively (all the others are only "interfaces" to curl) or a lib.
While Slim and Guzzle have a lot in common ie they both deal with psr-7 requests and responses
There is one key difference
Slim Deals with processing requests and sending responses
Guzzle Deals with sending requests and processing responses
as such they are not interchangeable and deal with opposite ends of the communication pipeline
so if your processing requests that someone has sent to you you need slim or something similar
if you are sending requests to someone else then you need guzzle or something similar

Categories