return new Response return empty data - php

In cotroller i have getVilla metod which return json response.
I get one villa by id from database in $villa variable, and this work fine. When i print_r($villa) i have villa object with all data.
But when i push $villa in response with
json_encode: json_encode(['villa' => $villa]), villa is empty...
villa: {}
/**
* #Route("/ajax/{id}", name="app_post_front_ajax_villa")
* #param $id
* #param EntityManagerInterface $em
* #return Response
*/
public function getVilla($id, EntityManagerInterface $em): Response
{
$repository = $em->getRepository(Villa::class);
$villa = $repository->findOneBy(['id' => $id]);
return new Response(json_encode([
'villa' => $villa,
]));
}

You are returning a json response from a response so you should use JsonResponse instead:
use Symfony\Component\HttpFoundation\JsonResponse;
//...
return new JsonResponse([
'villa' => $villa,
]);
However, your array contain an object $villa, not an array.
So you should either make a new array from your villa object or serialize it.
The easy way would be to make a new array from villa :
public function getVilla($id, EntityManagerInterface $em): Response
{
$repository = $em->getRepository(Villa::class);
$villa = $repository->findOneBy(['id' => $id]);
if($villa){
$villaArray['id'] = $villa->getId();
$villaArray['cityNameOrSomething'] = $villa->getCityName();
//Do the same for other attribute you want to get in your json
}else{
$villaArray = [];
}
return new Response([
'villa' => $villaArray,
]);
}
The other way would be to use the serializer component so that you do not have to make a new array.
Just follow the Symfony Documentation on the usage to find the one you want to use.

Related

How to add image on push notification using brozot / Laravel-FCM

How to add image on push notification using brozot / Laravel-FCM ?
I'm sending notifications correctly, but I would like to know how can I send an image with the notification?
I tried this code but not working
$pushData = ['body' => $message, 'title'=>$title,'image'=>'image-url'];
$pushJsonData = json_encode($pushData);
if(count($tokens)>0)
{
$optionBuilder = new OptionsBuilder();
$optionBuilder->setTimeToLive(60*20);
$notificationBuilder = new PayloadNotificationBuilder($title);
$notificationBuilder->setClickAction('NOTIFICATION');
$notificationBuilder->setBody($message)->setSound('default');
$notificationBuilder->setTag(strtotime("now"));
$dataBuilder = new PayloadDataBuilder();
$dataBuilder->addData(['a_data' => $pushJsonData]);
$option = $optionBuilder->build();
$notification = $notificationBuilder->build();
$data = $dataBuilder->build();
$downstreamResponse = FCM::sendTo($tokens, $option, $notification, $data);
$downstreamResponse->numberSuccess();
$downstreamResponse->numberFailure();
$downstreamResponse->numberModification();
//return Array - you must remove all this tokens in your database
$downstreamResponse->tokensToDelete();
//return Array (key : oldToken, value : new token - you must change the token in your database )
$downstreamResponse->tokensToModify();
//return Array - you should try to resend the message to the tokens in the array
$downstreamResponse->tokensToRetry();
// return Array (key:token, value:errror) - in production you should remove from your database the tokens present in this array
$downstreamResponse->tokensWithError();
You need to create a custom script that herance the vendor script and add some properties on it.
Create a new path in app: app/Notifications/Message
Add a new script called CustomPayloadNotification.php
Here you need to:
Extends PayloadNotification (vendor);
Add a new variable $image;
Override __construct method, changing the parameter type to CustomPayloadNotificationBuilder. Set all the variables like is in PayloadNotification and also set the new variable $image.
Override toArray method, setting all the properties like is in PayloadNotification and also set a new property image with $image value.
Something like this:
<?php
namespace App\Notifications\Messages;
use LaravelFCM\Message\PayloadNotification;
use App\Notifications\Messages\CustomPayloadNotificationBuilder;
class CustomPayloadNotification extends PayloadNotification // Extends vendor script
{
protected $image; // New variable
/**
* CustomPayloadNotificationBuilder constructor.
*
* #param CustomPayloadNotificationBuilder $builder
*/
public function __construct(CustomPayloadNotificationBuilder $builder) // Change the type of parameter
{
$this->title = $builder->getTitle();
$this->body = $builder->getBody();
$this->icon = $builder->getIcon();
$this->sound = $builder->getSound();
$this->badge = $builder->getBadge();
$this->tag = $builder->getTag();
$this->color = $builder->getColor();
$this->clickAction = $builder->getClickAction();
$this->bodyLocationKey = $builder->getBodyLocationKey();
$this->bodyLocationArgs = $builder->getBodyLocationArgs();
$this->titleLocationKey = $builder->getTitleLocationKey();
$this->titleLocationArgs = $builder->getTitleLocationArgs();
$this->image = $builder->getImage(); // Set image
}
/**
* convert CustomPayloadNotification to array
*
* #return array
*/
function toArray()
{
$notification = [
'title' => $this->title,
'body' => $this->body,
'icon' => $this->icon,
'sound' => $this->sound,
'badge' => $this->badge,
'tag' => $this->tag,
'color' => $this->color,
'click_action' => $this->clickAction,
'body_loc_key' => $this->bodyLocationKey,
'body_loc_args' => $this->bodyLocationArgs,
'title_loc_key' => $this->titleLocationKey,
'title_loc_args' => $this->titleLocationArgs,
'image' => $this->image, // Set property image with $image value
];
// remove null values
$notification = array_filter($notification, function($value) {
return $value !== null;
});
return $notification;
}
}
Add a new script called CustomPayloadNotificationBuilder.php
Here you need to:
Extends PayloadNotificationBuild (vendor);
Add a new variable protected $image;
Create the set/get methods to $image;
Override build method, returning a new CustomPayloadNotification instead PayloadNotification.
Something like this:
<?php
namespace App\Notifications\Messages;
use LaravelFCM\Message\PayloadNotificationBuilder;
use App\Notifications\Messages\CustomPayloadNotification;
class CustomPayloadNotificationBuilder extends PayloadNotificationBuilder // Extends vendor script
{
protected $image; // New variable
/**
* Set image
*
* #param string $image
*
* #return CustomPayloadNotificationBuilder
*/
public function setImage($image)
{
$this->image = $image;
return $this;
}
/**
* Get image.
*
* #return null|string
*/
public function getImage()
{
return $this->image;
}
/**
* Build an CustomPayloadNotification
*
* #return CustomPayloadNotification
*/
public function build()
{
return new CustomPayloadNotification($this); // Change the object returned
}
}
Reference CustomPayloadNotificationBuilder instead PayloadNotificationBuilder scripts in your code.
Use the method setImage
Your code should be something like this:
use App\Notifications\Messages\CustomPayloadNotificationBuilder; // Add the reference on the top of your code
// No changes before here [...]
$notificationBuilder = new CustomPayloadNotificationBuilder($title); // Replace here
$notificationBuilder->setClickAction('NOTIFICATION');
$notificationBuilder->setBody($message)->setSound('default');
$notificationBuilder->setTag(strtotime("now"));
$notificationBuilder->setImage("Image URL here"); // Add an image
// No changes after here [...]
you need to do some change in vendor for this
Step-1 : Go to the following url I am sharing here-
Laravel-FCM-master\Laravel-FCM-master\src\Message\PayloadNotification.php
Step-2 : here you have to add a instance variable as
protected $image;
Step - 3 find the public function __construct(PayloadNotificationBuilder $builder)
step -4 add $this->image = $builder->getImage(); in this function.
step -5 find the public function toArray()
step -6 add here 'image' => $this->image,
step -7 save and exit.
step -8 then follow this url in vendor again Laravel-FCM-master\Laravel-FCM-master\src\Message\PayloadNotificationBuilder.php:
step -9 add in above page
/**
* Indicates the image that can be displayed in the notification
* Supports an url or internal image.
*
* #param string $image
*
* #return PayloadNotificationBuilder current instance of the builder
*/
public function setImage($image)
{
$this->image = $image;
return $this;
}
step - 10 then add
/**
* Get image.
*
* #return null|string
*/
public function getImage()
{
return $this->image;
}
step - 11 that's it, now you can easily able to add a new field in your controller where your code was written asked in question.
simply modify as
$notificationBuilder = new PayloadNotificationBuilder($title);
$notificationBuilder->setClickAction('NOTIFICATION');
$notificationBuilder->setBody($message)->setImage("https://yourdoamin.com/yourdesiredimage.jpeg")->setSound('default');
$notificationBuilder->setTag(strtotime("now"));
and send you will get exact what you are looking for.

Laravel Cashier paymentMethods() return always empty object result

Cashier Version: ^10.5
Laravel Version: ^6.0
PHP Version: 7.3.5
Database Driver & Version:
Description:
paymentMethods() retrieve always array with empty object.
public function userAllPaymentMethods(Request $request)
{
$user = User::find(5);
$paymentMethod = $user->paymentMethods();
return response($paymentMethod);
}
Result :
https://www.screencast.com/t/aqenaud77A
Also using Stripe PaymentMethod lib it's works.
public function userAllPaymentMethods(Request $request)
{
$user = User::find(5);
\Stripe\Stripe::setApiKey('{{KEY}}');
$paymentMethod = \Stripe\PaymentMethod::all([
'customer' => $user->stripe_id,
'type' => 'card',
]);
return response($paymentMethod);
}
Result :
https://www.screencast.com/t/X14ane7WyqS
GitHub : here
$paymentMethods = $user->paymentMethods()->map(function($paymentMethod){
return $paymentMethod->asStripePaymentMethod();
});
Here's a solution:
$paymentMethods = [];
foreach ($user->paymentMethods() as $paymentMethod) {
$paymentMethods[] = $paymentMethod->asStripePaymentMethod();
}
Just loop through the payment methods and using $paymentMethod->asStripePaymentMethod() will get the payment methods for the user.
I have the same issue. didn't have time to investigate in deep. I just realized that method paymentMethod in cashier/src/Billable.php returns nothing.
/**
* Get a collection of the entity's payment methods.
*
* #param array $parameters
* #return \Illuminate\Support\Collection|\Laravel\Cashier\PaymentMethod[]
*/
public function paymentMethods($parameters = [])
{
$this->assertCustomerExists();
$parameters = array_merge(['limit' => 24], $parameters);
// "type" is temporarily required by Stripe...
$paymentMethods = StripePaymentMethod::all(
['customer' => $this->stripe_id, 'type' => 'card'] + $parameters,
$this->stripeOptions()
);
return collect($paymentMethods->data)->map(function ($paymentMethod) {
return new PaymentMethod($this, $paymentMethod);
});
}
return new PaymentMethod($this, $paymentMethod); this will return nothing instead of $paymentMethod. The solution for me was to overwrite PaymentMethod in mu user model the same way you did with stripe Lib.
The problem is not related to stripe, I think you are getting the right data, the problem is $paymentMethod is not encodable to JSON, that's why you get an empty response, try adding dd($paymentMethod); before the return statement and check the result.

Symfony - render view by defined status

I defined status field in my db table like
$newPlay->setStatus(Plays::STATUS_PUBLISHED);
that is now saved in that db table.
I need to render a view with fields that have that status.
I made an api call for that but I keep getting an error
Controller "AppBundle\Website\Controller\PublishedTicketsController::publishedTicketsAction()" requires that you provide a value for the "$status" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one.
This is my api call..
/**
* #Route("/published-tickets", name="published_tickets")
* #param Request $request
* #return \Symfony\Component\HttpFoundation\Response
* #throws \Exception
*/
public function publishedTicketsAction(Request $request, $status)
{
$query = $this->getDoctrine()
->getRepository('AppBundle:Plays')->findBy(['status' => $status]);
return $this->render('#FrontTemplates/pages/published-tickets.html.twig', array(
'query' => $query,
'status' => $status
));
}
I have done it like this..
In my service..
public function publishedTicket()
{
$query = $this->getPlaysRepository()
->createQueryBuilder('t')
->select('t')
->where('t.status =:status')
->setParameter('status', Plays::STATUS_PUBLISHED)
->getQuery()
->getResult();
return $query;
}
and in my controller
$playPublish = $this->container->get('publish.tickets')->publishedTicket();
return $this->render('#FrontTemplates/pages/published-tickets.html.twig', array(
'playPublish' => $playPublish
));
this is the part I could't figure out..
->setParameter('status', Plays::STATUS_PUBLISHED)

return object's properties from related data in symfony json result

I am attempting to return a list of comments related to a an entity. The query results on when it runs and returns, the related field does not provide a meaningful result.
Here is the comment entity declarations
/**
* #var Books
*
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Books")
*/
private $imagefk;
/**
* #var User
*
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Users")
*/
private $userfk;
This is my controller snippets of codes that fetches all the comment a user commented to a particular book
private function serializeComments(Comments $cmt) {
return array(
'message' => $cmt->getMessage(),
'userid' => $cmt->getUserfk(),
'bookid' => $cmt->getBookfk(),
);
}
the below function calls the function above
public function getAllCommentsAction($books)
{
$messages = $em->getRepository("AppBundle")->findBy(
array(
"imagefk" => $books
)
);
$data = array();
foreach ($messages as $message)
{
array_push($data, $this->serializeComments($message));
}
$response = new Response(json_encode($data), 200);
$response->headers->set('Content-Type', 'application/json');
return $response;
}
Here is the result of attempt
[{"message":"This is comment for a user one","userid":{"__initializer__":{},"__cloner__":{},"__isInitialized__":false},"bookid":{"path":"http:\/\/10.0.2.2:88\/xxx\/web\/uploads\/pdf\/5ub3uy8zv09cee2avi11.pdf"}}
Please how can I return the objects properties from this result instead of this
"userid":{"__initializer__":{},"__cloner__":{},"__isInitialized__":false},"bookid":{"path":"http:\/\/10.0.2.2:88\/xxx\/web\/uploads\/pdf\/5ub3uy8zv09cee2avi11.pdf"
Try accessing the object properties:
'userid' => $cmt->getUserfk()->getId(),
instead of
'userid' => $cmt->getUserfk(),
Hope this help

How to include fractal transformed objects directly to collection meta without data key

I'm using league/fractal with JsonApiSerializer,
I've got users collection for json output.
Now I want to add some filters data to this json response (like users count for current filters).
I got this:
$resource = new Collection($dataProvider->getData(), new UserTransformer());
//the only way to include some not directly linked data i found is using setMeta():
$resource->setMetaValue('projects', $dataProvider->getProjects());
$resource->setMetaValue('somes', $dataProvider->getTasks());
But! 'projects' & 'somes' collections (yes, they are collection too) also included with 'data' key in it.
So, I've got this structure:
{
'data' => [
{//user1},{//user2},...
],
'meta' => {
'projects' => {
'data' => {...}
},
'somes' => {
'data' => {...}
}
}
}
but I want something like:
{
'data' => [
{//user1},{//user2},...
],
'meta' => {
'projects' => {...}, //there is no 'data' key
'somes' => {...} //there is no 'data' key
}
}
What should I do?
This is kinda hack but works fine without refactor Scope class which hardcoded in fractal's League\Fractal\Manager::createData() and is only way to use your own Scope class realization is to overload this method in Manager's extension.
<?php
use League\Fractal\Serializer\JsonApiSerializer;
/**
* Class EmbedSerializer
*/
class EmbedSerializer extends JsonApiSerializer
{
const RESOURCE_EMBEDDED_KEY = 'embedded';
/**
* Serialize a collection.
*
* #param string $resourceKey
* #param array $data
* #return array
*/
public function collection($resourceKey, array $data)
{
return $resourceKey === self::RESOURCE_EMBEDDED_KEY ? $data : [$resourceKey ?: 'data' => $data];
}
/**
* Serialize an item.
*
* #param string $resourceKey
* #param array $data
* #return array
*/
public function item($resourceKey, array $data)
{
return $resourceKey === self::RESOURCE_EMBEDDED_KEY ? $data : [$resourceKey ?: 'data' => [$data]];
}
}
So, now i could use it like:
/** #var $this->fractal League\Fractal\Manager */
$this->fractal->setSerializer(new EmbedSerializer());
$projectsCollection = $this->fractal->createData(
new Collection($projects, new UserProjectTransformer(), 'embedded')
)->toArray();
$resource = new Collection($users, new UserTransformer());
$resource->setMetaValue('projects', $projectsCollection);
That's all u need. Hope this will be helpful.

Categories