Is Api Result the same as the frontend result? - php

In my code I am trying to get access my data bank through query builder, everything works I am able to get access to everything as a string (which this is what I want), everything but my date is returned as a class DateTime object in my Frontend, the intersting part for me through Api I am getting my date as a string and not as a class DateTime object and I cant understand why I am getting two different results when I am using the same methods same query builder and my Question is why am I getting two different results? is it possible to get different result through Api? and if so why? and is there a way to convert the class DateTime object to a string?
Api Controller
public function indexAction()
{
$request = $this->Request();
$limit = $request->getParam('limit', 1000);
$offset = $request->getParam('start', 0);
$sort = $request->getParam('sort', []);
$filter = $request->getParam('filter', []);
$result = $this->resource->getList($offset, $limit, $filter, $sort);
$view = $this->View();
$view->assign($result);
$view->assign('success', true);
}
Fronend Controller
public function listAction()
{
$feedback= $this->resource->getList(0, 10, null, null);
$this->View()->assign('feedback', $feedback);
}
QueryBuilder
protected function getBaseQuery()
{
$builder = $this->getManager()->createQueryBuilder();
$builder->select(['feedback', 'user_id.firstname','user_id.lastname',])
->from(FeedbackModel::class, 'feedback')
->leftJoin('feedback.customer', 'user_id');
return $builder;
}
getList function
public function getList($offset, $limit, $filter, $sort)
{
$this->checkPrivilege('read');
$builder = $this->getBaseQuery();
$builder->setFirstResult($offset)
->setMaxResults($limit);
if (!empty($filter)){
$builder->addFilter($filter);
}
if (!empty($sort)){
$builder->addOrderBy($sort);
}
$query = $builder->getQuery();
$query->setHydrationMode($this->getResultMode());
$paginator = $this->getManager()->createPaginator($query);
$totalResult = $paginator->count();
$feedback = $paginator->getIterator()->getArrayCopy();
return ['data' => $feedback , 'total' => $totalResult];
}
Api result
data
0
0
id 1
feedback "this shop is boring"
date "2022-12-07T00:00:00+0100"
public true
firstname "some"
lastname "thing"
total 1
success true
Frontend Result
0 => Array (3)
0 => Array (4)
id => 1
feedback => "this shop is boring"
date => DateTime Object (0)
public => true
firstname => "some"
lastname => "thing"
total => 1
->nocache = null

How I fixed my Problem and what it was:
With the help of #ADyson I found out what the problem was. I was tackling the problem from the wrong way though I didn't need to convert my DateTime to string neither in my Model, in my Controller or my Query-builder the only problem was the way I was calling it, there is a way of calling date objects like this in smarty and its by using |date:'dd.MM.y' in my case it was {$feedbacks.date|date:'dd.MM.y'} this get the date inside of the class and converts it to a string at the same time and like that I got to call the date that I want.
To answer my Original Question:
Api and Frontend don't give different result but a different Format which is for the human eye a bit different with the use of different Tools such as PHPStorm Debugger, Postman and Smarty Debugger I got to see the different result, why I am getting these Kind of results and the data inside of the class DateTime in my case.
what helped me find a solution my to problem
PHPStorm Debugger.
Smarty Debugger
Postman

Related

Putting a limit on doctrine queries

I'm working on a site to make an inventory of series.
public function category(string $categoryName): Response
{
$categoryInfos = $this->getDoctrine()
->getRepository(Category::class)
->findOneByName($categoryName);
$programs = $this->getDoctrine()
->getRepository(Program::class)
->findByCategory($categoryInfos);
return $this->render('wild/category.html.twig', ['programs' => $programs, 'category' => $categoryInfos]);
}
This function allows me to retrieve all programs belonging to the specified category.
I would now like to limit the number of programs to 3 in my request.
$programs = $this->getDoctrine()
->getRepository(Program::class)
->findByCategory($categoryInfos)
->setMaxResults(3);
But this shows me the error:
-> Call to a member function setMaxResults() on array
What did I do wrong?
I get lost in the symfony doc, being new ^^
You are calling a method inside repository class that returns an array and you cannot execute setMaxResults() on arrays.
If you want to set the size of result you should set it inside findByCategory() method in ProgramRepository.php

How will Google Ads API react incase an array becomes empty?

I'm working with Google Adwords API in Laravel but I'm pretty new and I need help to understand one thing on a line of code where I got the question I used for this post.
The line is this:
$campaign_ids = array_filter(Arr::pluck($campaigns, 'googleId'));
Being part of this function:
public function reports(CampaignGroup $campaignGroup, string $dateFrom, string $dateTo, int $limit): array
{
$campaigns = [];
$campaigns = array_merge($campaigns, $campaignGroup->campaigns->toArray());
$campaign_ids = array_filter(Arr::pluck($campaigns, 'googleId'));
$cacheKey = sprintf('keyword_performance_report.%d.%d', $this->account->id, $limit);
$cacheTtl = DateInterval::createFromDateString($this->cacheTtl);
$definitionAdapter = new KeywordsPerformanceDefinitionAdapter($campaign_ids);
return Cache::remember($cacheKey, $cacheTtl, function () use ($definitionAdapter, $dateFrom, $dateTo, $campaign_ids, $limit) {
$definitionAdapter->applyFilters($campaign_ids, $dateFrom, $dateTo, $limit);
$definitionAdapter->getSelectorAdapter()->asSummary();
$response = $this->generate();
return $response['entries'];
});
}
I would like to understand what happening if that line will be come an empty array and Google will get that. I was unable to get that and I would like to understand what kind of exception can be throw here and what should I do to avoid such an issue.
In general, if you pass an empty $campaign_ids array, I would expect that statistics for all keywords would be returned, as no filtering by campaign is requested.
However, seeing as KeywordsPerformanceDefinitionAdapter looks to be some custom code of your application, it might obviously be possible that the actual behavior is different.
Can't you just test the scenario and take note of any error conditions encountered?

How to refactor php foreach using Laravel (Eloquent's) map collection function

I've just watched Adam Wathan's video on Refactoring Loops and Conditionals, and feel like I can use the map collection method in the sumLeagueStats method on my Team model (rather than the foreach).
I have a relationship on teams -> leagues, and the getLeagueStats function gets all of the stats (played, won, drew, lost, for, against, points) from the leagues table for the relevant team.
In the sumLeagueStats method I was going to use a foreach loop and loop through each stat by year, and take the sum of all of the played, etc, and return it, but having watched the above video,
class Team extends Model {
public function league()
{
return $this->hasMany('league');
}
public function getLeagueStats($year = [2018])
{
return $this->league()->whereIn('year', [$year])->get();
}
public function sumLeagueStats($year = [2018])
{
foreach {
...
return
}
/*
* Want to return a colleciton with the following:
*
$this->getLeagueStats()->sum('played');
$this->getLeagueStats()->sum('won');
$this->getLeagueStats()->sum('drew');
$this->getLeagueStats()->sum('lost');
$this->getLeagueStats()->sum('for');
$this->getLeagueStats()->sum('against');
$this->getLeagueStats()->sum('points');
*/
}
}
I'm new to Laravel, so firstly want to check. my suspicions are correct, and secondly looking for any insight/resource for more information, as the docs are slightly lacking).
Calling getLeagueStats everytime is making a request to your database everytime you call the sum method, so you can create a variable to work with and create a collection that represents the data :
$stats = $this->getLeagueStats();
return collect([
'played' => $stats->sum('played'),
'won' => $stats->sum('won'),
'drew' => $stats->sum('drew'),
'won' => $stats->sum('won'),
'lost' => $stats->sum('lost'),
'for' => $stats->sum('for'),
'points' => $stats->sum('points')
]);
is that a what you want ?

How can I take a big amount of GET parameters and filter a query depending on them cleanly?

I have this controller for a RESTful API I am building in Laravel Lumen which takes a relatively big amount of parameters and parses them into where queries, and data is fetched depending on if they were provided. For example,
GET /nodes?region=California
GET /nodes?ip=127.0.0.1
I am currently taking them in the constructor, building an array of the parameters (since I couldn't figure out how to get the raw get array in Lumen and it would be inconvenient because I already have other parameters there), and filtering out the null values (I am setting values to null if they are not in the query).
Now, when it comes to filtering the values each in the array, I am doing it by a foreach array. This is the cleanest way I could figure out to do it, without too much code (I don't want to make my controllers too fat.).
Is there any other way to do this cleanly, maybe with separation of functions/classes?
Here is my constructor code:
/**
* Get some values before using functions.
*
* #param Request $request Instance of request.
*/
public function __construct(Request $request)
{
$this->offset = (int) $request->input('offset', 0);
// TODO: I'm not sure how to implement this, code in question
$this->filters = [
'region' => $request->input('region', null),
'name' => $request->input('name', null),
'ip' => $request->input('ip', null)
];
$this->filters = array_filter($this->filters, function ($v) {
return !is_null($v);
});
// Set a sane SQL limit.
$this->limit = 5;
$this->request = $request;
}
And the controller code:
/**
* List all nodes.
*
* #return [string] [JSON containing list of nodes, if sorted.]
*/
public function all()
{
try {
// use filters provided
$data = Nodes::limit($this->limit)->offset($this->offset);
foreach ($this->filters as $filter => $value) {
$data->where($filter, $value);
}
$data = $data->get();
$response = $this->respond($data);
} catch (\Exception $e) {
$response = $this->respondServerError('Could not retrieve data from database.');
}
return $response;
}
So any time I have to do filtering of a resource-list in an API, here's how I do it.
First off though, before I begin, a quick tip concerning getting the Request object when you're in your controller method: If you add Request $request as a parameter for your all() function, you will have access to the $request variable there, same as your constructor. So the complete signature would be public function all(Request $request). Controller methods have the same magic dependency injection that other class constructors get in Laravel/Lumen. Alternatively, in your function you can always ask the app() function to give you an object of a specific class. Because the Request object is bound in the Container to just 'request', you can ask for the full class name, or just 'request': $request = app('request');
So once I have my request object, inside my controller method I like to go through each filter either as a group, or one-by-one, depending on how complex each filter is. Sometimes filters are complex, like a list of comma-separated IDs that need to be exploded into an array. If it's just simple string filters though, I tend to throw the list into an array and run through that.
Here's an example function to illustrate some ideas:
public function getIndex(Request $request)
{
//Create a User object to append WHERE clauses onto
$user = app('App\Models\User');
//Run through our simple text fields
foreach(['first_name', 'last_name', 'region', 'ip'] as $field) {
if ($request->has($field)) {
$user->where($field, $request->input($field));
}
}
//This field uses a LIKE match, handle it separately
if ($request->has('email')) {
$user->where('email', LIKE, '%' . $request->input('email') . '%');
}
//This field is a list of IDs
if ($request->has('id')) {
$ids = explode(',', $request->input('id'));
$user->whereIn('id', $ids);
}
//Use pagination
$users = $user->paginate(25);
/**
* Continue with the rest of response formatting below here
*/
}
You'll notice I used the paginate function to limit my results. When building an API endpoint that lists resources, you're going to want to put in your headers (my preference) or the response body information on how to get the first, previous, next, and last page of results. The Pagination feature in Laravel makes that easy, as it can construct most of the links using the links() method.
Unfortunately, you need to tell it what filter parameters were passed in the request so it can make sure it adds those to the links it generates. Otherwise you'll get links back without your filters, which doesn't do the client very much good for paging.
So here's a more complete example of recording filter parameters so they can be appended onto pagination links:
public function getIndex(Request $request)
{
//Create a User object to append WHERE clauses onto
$user = app('App\Models\User');
//List of filters we found to append to links later
$appends = [];
//Run through our simple text fields
foreach(['first_name', 'last_name', 'region', 'ip'] as $field) {
if ($request->has($field)) {
$appends[$field] = $request->input($field);
$user->where($field, $request->input($field));
}
}
//This field uses a LIKE match, handle it separately
if ($request->has('email')) {
$appends['email'] = $request->input('email');
$user->where('email', LIKE, '%' . $request->input('email') . '%');
}
//This field is a list of IDs
if ($request->has('id')) {
$appends['id'] = $request->input('id');
$ids = explode(',', $request->input('id'));
$user->whereIn('id', $ids);
}
//Use pagination
$users = $user->paginate(25);
//Make sure we append our filter parameters onto the pagination object
$users->appends($appends);
//Now calling $users->links() will return the correct links with the right filter info
/**
* Continue with the rest of response formatting below here
*/
}
Pagination documentation can be found here: https://laravel.com/docs/5.2/pagination
For an example of how pagination linking can be awesomely done, check out Github's API documentation: https://developer.github.com/v3/#pagination
In the end it's not too far off from what you were doing, conceptually. The advantage here is that you move the code into the method that needs it, instead of having it run in your constructor every single time the controller is initialized, even if a different method will be called.
Hope that helps!

Returning object in a function Laravel 4

I am trying to access a functions variable from another function in the same class. i am fairly new to the concept and I can get it to work in another function but when I try to create it's own function I get an Trying to get property of non-object I know what that means but it's confusing as to what needs to be returned in my function since it does work in my other function.
Function getting the error
public function getEditTotal($id) {
$techs = $this->technician();
$tech = $techs->tech;
var_dump($tech); die;
return View::make('report.edit', array('pageTitle' => 'Edit Report Total', 'id' => $id, 'tech' => $tech));
}`
The function I am trying to call
public function technician() {
$tech = DB::table('technician')
->get();
return $tech;
}
I had that same $tech variable in this function and it worked perfectly fine if I called $this->setComplete($id) instead.
Returned statement in the setComplete($id) function
return View::make('report.total', array('pageTitle' => 'Reporting', 'id' => $id, 'tech' => $tech, 'status' => $status));
I am sure it's just the way it's being returned since that variable is being returned in setComplete($id) in the array. I just don't know how to strictly call it in the technician() function.
When you call $techs = $this->technician(); you are setting the $techs to be whatever the value of the $tech variable in the technician function. That is going to be the result of DB::table('technician')
->get();
Theoretically this should be an array of objects where each object represents one row in the technician table.
If you want to know what's going on, add a var_dump($tech) inside the your technician() function, just prior to the return $tech statement.
Since you indicate it is working as expected, you're getting an array of objects. I'm not sure what you want to do with those, but inside the controller:
foreach ($techs as $tech) {
echo $tech->somefieldInTech;
}
or perhaps
echo $techs[0]->somefieldInTech;
So to be clear, in your laravel template, you might want to pass the entire $techs and foreach through it in the template, although from your code it's not clear what you need to do with the data.

Categories