I'm trying to do my coding, but I ran into this issue. Thing is, I did it exactly the same like my first code, but it's working there.
ErrorException in CoinflipController.php line 115: Argument 1 passed
to App\Http\Controllers\CoinflipController::CoinflipToJson() must be
an instance of App\Models\Game\Coinflip\Coinflip, instance of
Illuminate\Database\Eloquent\Collection given, called in
C:\xampp\htdocs\site\app\Http\Controllers\CoinflipController.php on
line 104 and defined
Coinflip File
<?php
namespace App\Models\Game\Coinflip;
use Illuminate\Database\Eloquent\Model;
class Coinflip extends Model {
const STATUS_ACTIVE = 0;
const STATUS_ROLLING = 1;
const STATUS_ENDED = 2;
protected $table = 'coinflip';
protected $fillable = [
'status',
'winner_steam_id',
'winner_probability',
'winner_value',
'hash',
'ticket',
'seed',
'player1',
'player1_side',
];
protected $dates = [ 'draw_at' ];
protected $casts = [
'winner_steam_id' => 'string',
'winner_probability' => 'float',
'winner_value' => 'float',
'ticket' => 'double'
];
public function entry(){
return $this->hasMany( 'App\Models\Game\Coinflip\CoinflipEntry', 'coinflip_id' );
}
public function winner(){
return $this->hasOne( 'App\User', 'steam_id', 'winner_steam_id' );
}
public function getCommissionValue(){
$val = 0;
foreach( $this->entry as $entry ){
foreach( $entry->item as $item ){
if ( $item->status == CoinflipEntryItem::STATUS_COMMISIONED )
$val += (float)$item->price;
}
}
return $val;
}
}
CoinflipToJson Function (From 1st line is the Error)
public function CoinflipToJson( Coinflip $coinflip, $showExtra = false ){
$canDeposit1 = $coinflip->value * 0.10 + $coinflip->value;
$canDeposit2 = $coinflip->value - $coinflip->value * 0.10;
$data = [
'id' => $coinflip->id,
'hash' => $coinflip->hash,
'gameValue' => $coinflip->value,
'canDeposit1' => $canDeposit1,
'canDeposit2' => $canDeposit2,
'skinValue' => 0,
'skinCount' => 0,
'timeStart' => $coinflip->created_at->getTimestamp(),
'timeEnd' => $coinflip->draw_at ? $jackpot->draw_at->getTimestamp() : 0,
'timeEndIn' => $coinflip->draw_at ? $jackpot->draw_at->getTimestamp() - time() : -1,
'timeMax' => Setting::of('JackpotExtendTime', 15)->getValue(),
'entry' => []
];
if ( $showExtra ){
$data['winningPercentage'] = $coinflip->ticket;
$data['winnerId'] = $coinflip->winner_steam_id;
$data['secret'] = $coinflip->seed;
}
foreach( $coinflip->entry as $entry ){
$entryData = $this->entryToJson( $entry );
$data['entry'][] = $entryData;
$data['skinValue'] += $entryData['skinValue'];
$data['skinCount'] += $entryData['skinCount'];
}
return $data;
}
Code where I am calling it (Line 5)
public function current( Request $request ){
$coinflip = $this->getCurrentGame();
if($coinflip){
$data = [
'current' => $this->CoinflipToJson($coinflip)
];
return response()->json($data);
} else return response()->json(['error' => 'No Games']);
}
getCurrent Game Function
public function getCurrentGame(){
$coinflip = Coinflip::where('status', Coinflip::STATUS_ACTIVE)->get();
return $coinflip;
}
In your getCurrentGame() method, the get() method always returns a Collection, even if there was only one record. If you query will only ever return one record, you can just change get() to first(), and it will return the record instance, instead of a Collection.
Related
In my Laravel project, I've got a job set up which runs and attempts to notify a user based on their threshold and chosen alert metrics. I'm using the php end() method to get the last item in an array and then attempting to get whatever metric the user has chosen.
However, upon dumping the data, this isn't returning the last array item, it's returning every item and I'm not sure why?
When I dump my data, I'm getting this format instead of the last item in the array:
[2021-04-13 13:30:45] production.DEBUG: array (
0 =>
(object) array(
'event_category' => 'My Category',
'event_action' => 'My Event',
'event_count' => '2190',
'period_from' => '2021-04-13 00:00:00',
'period_to' => '2021-04-13 13:30:02',
'created_at' => '2021-04-13 13:30:06',
),
1 =>
(object) array(
'event_category' => 'My Category',
'event_action' => 'My Event',
'event_count' => '5184',
'period_from' => '2021-04-12 00:00:00',
'period_to' => '2021-04-12 23:57:02',
'created_at' => '2021-04-12 23:57:07',
),
2 =>
(object) array(
'event_category' => 'My Category',
'event_action' => 'My Event',
'event_count' => '3820',
'period_from' => '2021-04-11 00:00:00',
'period_to' => '2021-04-11 23:57:02',
'created_at' => '2021-04-11 23:57:07',
),
)
I should just be seeing the last item, amongst all of my code, the following is of significant value here:
/**
* Notify if data meets threshold & alert rules
*
* #return void
*/
public function notifyAlertThreshold($alerts, $data)
{
$newestDataPart = end($data) ?? null;
// alerts for data source
foreach ($alerts as $key => $alert) {
Log::debug($newestDataPart);
$metric = !isset($newestDataPart->{$alert->metric}) ? $newestDataPart : $newestDataPart->{$alert->metric};
}
}
In context, here's some mode of the code, but the primary question here, is why is my end() method not returning the last item?
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
$filters = json_decode($this->report->discovery_filters, true);
$this->reportStatus = 'complete';
$data = [];
foreach ($filters as $findableKey => $findable) {
/*
** If there are datasets on the findable objec, then we assume
** that we can build up a chart or some data structure.
*/
if (isset($findable['datasets'])) {
$pushableDatasets = [];
foreach ($findable['datasets'] as $datasetKey => $dataset) {
// query data
if (isset($dataset['query'])) {
$chartLabel = $findable['name'] ?? 'Untitled Chart';
$this->setDynamicChartOptions($chartLabel);
$additionFromField = $dataset['query']['additionFromField'] ?? '';
$resultData = [];
if ($dataset['query']['prefersConversionCalculation'] == 'yes') {
$totals = DB::table($dataset['query']['table'])
->select($dataset['query']['columns'])
->where($dataset['query']['calculateConversionFromTotals'])
->orderBy($dataset['query']['orderBy']['field'], $dataset['query']['orderBy']['direction'])
->get()
->chunk(100);
$goal = DB::table($dataset['query']['table'])
->select($dataset['query']['columns'])
->where($dataset['query']['calculateConversionByGoal'])
->orderBy($dataset['query']['orderBy']['field'], $dataset['query']['orderBy']['direction'])
->get()
->chunk(100);
$totals = $totals->flatten();
$goal = $goal->flatten();
$totalsGrouped = $this->groupData(
$totals,
$dataset['query']['groupBy'],
$dataset['query']['groupByFormat'],
$additionFromField
);
$goalsGrouped = $this->groupData(
$goal,
$dataset['query']['groupBy'],
$dataset['query']['groupByFormat'],
$additionFromField
);
$totalsGroupedFlattened = $totalsGrouped->flatten();
$goalsGroupedFlattened = $goalsGrouped->flatten();
$resultData = $this->getStructure($findable, $datasetKey, $goalsGroupedFlattened, $totalsGroupedFlattened);
array_push($pushableDatasets, $resultData);
} else {
$res = DB::table($dataset['query']['table'])
->select($dataset['query']['columns'])
->where($dataset['query']['filterBy'])
->orderBy($dataset['query']['orderBy']['field'], $dataset['query']['orderBy']['direction'])
->get()
->chunk(100);
$res = $res->flatten();
if (isset($dataset['query']['useGrouping']) && $dataset['query']['useGrouping'] == 'yes') {
$results = $this->groupData(
$res,
$dataset['query']['groupBy'],
$dataset['query']['groupByFormat'],
$additionFromField
);
// if we're using an addition function our array is already flattened
if (!empty($additionFromField)) {
$resultData = $results;
} else {
$resultData = $results->flatten();
}
array_push($pushableDatasets, $this->getStructure($findable, $datasetKey, $resultData));
}
}
$dataForAlerts = $resultData;
if ($dataset['query']['prefersConversionCalculation'] == 'yes') {
$dataForAlerts = $dataForAlerts['data'];
}
// alerting
$alerts = $this->getAlertThresholds($dataset['query']['table']);
$this->notifyAlertThreshold($alerts, $dataForAlerts);
}
}
$findable['datasets'] = $pushableDatasets;
}
array_push($data, $findable);
}
// no data or it's empty
if (!isset($data) || empty($data)) {
$this->reportStatus = 'error';
}
// create our report data entry
$this->updateReportData(false, $data);
}
I'm writing a recursive function like below:
private function getManager($employee)
{
$manager = $employee->manager;
if ($manager) {
array_push($this->managers, $manager->id);
$this->getManager($manager);
}
return;
}
This function receive an employee and find his manage. If find a manage, then push manager id into an array ($this->managers on line 5). Then call this function recursively and pass manager as an employee. If no manager found on line 3, then this function just return (line 8).
So my question is, is their any problem if i'm not return the recursive call at line 6 ($this->getManager($manager);)
Not sure if this is what you think, but it works.
function getManagers($employee)
{
$managers = [];
if (isset($employee->manager)) {
array_push($managers, $employee->manager->id);
array_push($managers, ...getManagers($employee->manager));
}
return $managers;
}
No, there is absolutely no benefit in writing the empty return. The method will halt regardless of the existence of the return.
Please observe the two methods below which show identical, error-less outcomes regardless of the return.
Code: (Demo)
class Management
{
private $managers = [];
function __construct($managerTree)
{
$this->getManager($managerTree);
var_export($this->managers);
echo "\n---\n";
$this->managers = [];
var_export($this->managers);
echo "\n---\n";
$this->getManager2($managerTree);
var_export($this->managers);
}
private function getManager(?object $employee): void
{
$manager = $employee->manager;
if ($manager) {
array_push($this->managers, $manager->id);
$this->getManager($manager);
}
return;
}
private function getManager2(?object $employee): void
{
$manager = $employee->manager;
if ($manager) {
array_push($this->managers, $manager->id);
$this->getManager($manager);
}
}
}
new Management(
(object) [
'id' => 3,
'manager' => (object) [
'id' => 2,
'manager' => (object) [
'id' => 1,
'manager' => null
]
]
]
);
Output:
array (
0 => 2,
1 => 1,
)
---
array (
)
---
array (
0 => 2,
1 => 1,
)
I want to get data from api request. I make a query on the value of oc52. Get $date array. The issuing server adds the MH prefix. Which generates itself relative to the name. I am trying to extract part of the array using the class.
This is the array I get when querying:
$data = [
[
'product' => 'CH C104.12',
'brand' => 'CH C104.12',
'price' => 12.34,
],
[
'product' => 'MH OC52',
'brand' => 'MH OC52',
'price' => 56.78,
],
[
'product' => 'WX WL7074-12',
'brand' => 'WX WL7074-12',
'price' => 90.12,
],
];
Here's the class I'm doing a search for
class ProductFilterIterator extends \FilterIterator
{
protected $filter;
public function __construct(\Iterator $iterator, $filter)
{
$this->filter = $filter;
parent::__construct($iterator);
}
public function accept() : bool
{
$current = $this->getInnerIterator()->current();
return $current['product'] == $this->filter;
}
}
$iterator = (new \ArrayObject($data))->getIterator();
$filter1 = new ProductFilterIterator($iterator, 'OC52');
foreach ($filter1 as $data) {
echo "<pre>";
var_dump($data);
echo "</pre>";
}
Does nothing reflect? If I write in line MH OC52:
$filter1 = new ProductFilterIterator($iterator, 'MH OC52');
Then everything works.
How do I implement it if I don't know the front - MH ???
If you just want to check the end of the string, this stores the length to check after storing the filter. Then in the main accept() method, it just looks at the last part of the string (using substr()) in the array to compare...
class ProductFilterIterator extends \FilterIterator
{
protected $filter;
protected $length;
public function __construct(\Iterator $iterator, $filter)
{
$this->filter = $filter;
$this->length = -strlen($filter);
parent::__construct($iterator);
}
public function accept() : bool
{
$current = $this->getInnerIterator()->current();
return substr($current['product'], $this->length) == $this->filter;
}
}
I have an array for showing users' contacts list to each other.
I want to add ->paginate(10) features for json response but I could not find where I must put it.
My index function:
public function index()
{
$contacts = [];
$user = request()->user();
// Loop through the contacts and format each one
Contact::for($user->id)->get()->each(function ($contact) use ($user, &$contacts) {
$friend = $contact->user1_id === $user->id ? $contact->user2 : $contact->user1;
$contacts[] = $friend->toArray() + ['room' => $contact->room->toArray()];
});
return response()->json($contacts);
}
You can create a collection for the contact and use LenfthAwarePaginator
class ContactResourceCollection extends ResourceCollection
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request
* #return array
*/
public function toArray($request)
{
$response = [
'data' => $this->collection,
];
if($this->resource instanceof LengthAwarePaginator)
{
$response['pagination'] = [
'total' => $this->resource->total(),
'lastPage' => $this->resource->lastPage(),
'perPage' => $this->resource->perPage(),
'currentPage' => $this->resource->currentPage(),
'nextPageUrl' => $this->resource->nextPageUrl(),
'previousPageUrl' => $this->resource->previousPageUrl(),
];
}
return $response;
}
}
In the controller method add this line:
return new UserResourceCollection($users);
Here is the total code
$contacts = Contact::where('user_id', $user->id)->paginate(12);
if($contacts->count()){
$pageIndex = array();
$lastPage = $contacts->lastPage();
$user = request()->user();
for($i= 2; $i<=$lastPage; $i++){
array_push($pageIndex, $i);
}
return response()->json([
'contacts' => $contacts->map(function ($contact) use ($user) {
if($contact->user1_id === $user->id){
return [
'friend' => $contact->user2,
'room' => $contact->room,
];
} else {
return [
'friend' => $contact->user1,
'room' => $contact->room,
];
}
})->toArray(),
'per_page' => $contacts->perPage(),
'on_first_page' => $contacts->onFirstPage(),
'last_page' => $contacts->lastPage(),
'first_page_url' => $contacts->url(1),
'next_page_url' => $contacts->nextPageUrl(),
'prev_page_url' => $contacts->previousPageUrl(),
'last_page_url' => $contacts->url($contacts->lastPage()),
'total' => $contacts->total(),
'pageIndexArray' => $pageIndex,
'errors' => false,
]);
} else {
// Do Nothing
}
Call
GET 'URL?page='+Page_index to get the response in JS (AJAX)
I am not sure but try : replace get() to paginate(10)
Contact::for($user->id)->paginate(10)->each(function ($contact) use ($user, &$contacts) {
$friend = $contact->user1_id === $user->id ? $contact->user2 : $contact->user1;
$contacts[] = $friend->toArray() + ['room' => $contact->room->toArray()];
});
Can you change the query into:
$contacts = Contact::for($user->id)->paginate(10);
Then after this query you can use for loop for $contact;
foreach ($contacts as $key => $contact)
{
$friend = $contact->user1_id === $user->id ? $contact->user2 : $contact->user1;
$contacts[] = $friend->toArray() + ['room' => $contact->room->toArray()];
}
Paginate first before get into loop/each.
I know this question is more data structures but since I am doing it in Symfony there might be a simpler way. I have a recursive function treeBuilder() I want to call on some data to create a hierarchy. Say a database of people and I want to create a tree structure if they live with their parents. I know I am passing an array of object to the function but it needs to be an array. I am pretty sure I need to rewrite this function so that it handles the the array of object but am stumped. I am not sure how to access the elements of the array to check the parentid. I know the code below is not correct but that is where I am at now.
Controller:
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('CompanyMyBundle:Org')->findAll();
var_dump($entities);
$tree=$this->treeBuilder($entities);
return array(
'entities' => $tree,
);
}
private function treeBuilder($ar, $pid=null)
{
$op=array();
foreach( $ar as $item ) {
// I know I have an array of objects
if( $item['ParentId'] == $pid ) {
$op[$item['Id']] = array(
'Street' => $item['Street'],
'ParentId' => $item['ParentId']
);
$children = self::treeBuilder( $ar, $item['Id'] );
if( $children ) {
$op[$item['Id']]['children'] = $children;
}
}
}
return $op;
}
var_dump($entities) from indexAction():
/export/www/working/symfony/src/Company/MyBundle/Controller/DepController.php:34:
array (size=60)
0 =>
object(Company\MyBundle\Entity\Org)[1556]
private 'Name' => string 'Me' (length=46)
private 'Street' => string '123 Sesame' (length=255)
private 'City' => string 'Myhometown' (length=255)
private 'ParentId' => int 0
private 'Id' => int 1
1 =>
object(Company\MyBundle\Entity\Org)[1557]
private 'Name' => string 'Me2' (length=46)
private 'Street' => string '123 Sesame' (length=255)
private 'City' => string 'Myhometown' (length=255)
private 'ParentId' => int 1
private 'Id' => int 2
If you need to get entities as arrays instead of objects, you would need to use Doctrine's hydrator:
$em = $this->getDoctrine()->getManager();
$orgRepo = $em->getRepository('CompanyMyBundle:Org');
$entities = $orgRepo->createQueryBuilder('org')
->getQuery()
->getResult(\Doctrine\ORM\AbstractQuery::HYDRATE_ARRAY);
Note:
I would suggest to leave entities as objects and use getters:
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('CompanyMyBundle:Org')->findAll();
$tree = $this->treeBuilder($entities);
return array(
'entities' => $tree,
);
}
private function treeBuilder($entities, $pid = null)
{
$op = array();
/** Org $entity */ //Type hinting, if you use autocompletion
foreach ($entities as $entity) {
if ($entity->getParentId() == $pid) {
$op[$entity->getId()] = [
'Street' => $entity->getStreet(),
'ParentId' => $entity->getParentId()
];
$children = self::treeBuilder($entities, $entity->getId());
if (!empty($children)) {
$op[$entity->geId()]['children'] = $children;
}
}
}
return $op;
}