compare a single field from an object array - php

I'm revamping the packaging screen in our inventory system. The user opens a package and inserts/removes the items in it, and when he presses Save, a json array of all the parts that are in the package is sent to a PHP endpoint which takes care of saving the package in the database.
So far everything is good, I have created my functions to send data between PHP and javascript. However, even though the json array that javascript sends to PHP contains all the info on the products (as javascript needed to retrieve it anyway to fill in the grid in the gui), I still have to validate everything in PHP because I can't be sure that the user didn't tampered with the data from the console before trying to save.
With that said, in PHP, I receive the json array, which I use the IDs to load a list of proper objects into an array. I'm doing this:
$in = str_repeat('?,', count($itemIDs) - 1) . '?';
$sql = "SELECT * FROM tbProduct WHERE nID IN ($in)";
$sttmt = $db->prepare($sql);
$sttmt->execute($itemIDs);
$res = $sttmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($res as $key => $productInfo) {
$prod = new tbProduct($db);
$prod->loadFromArray($productInfo);
}
so far so good, I now have an array of tbProduct, which is my class for the products.
What I now have to do is run a validation on this array of objects to make sure all these objets are in the proper status to be packaged together. These validations include making sure all the products have the same status, that none of the products are assembly parts, that all the products have the same owner, etc. This way, even if the array was tampered with in the browser's console, I'll be sure to use the information from the DB anyway.
So I need a way to validate this. I could just do a foreach, store everything that needs to be checked from the very first item in variables, and just compare each subsequent item to these variables, but I'm sure there are better ways to do this. I need something that will be as efficient as possible. My packages can(and will) contain several hundreds of products, so the solution needs to be fast.
What would be the best way of doing this?
Thank you!

You can do it during the loop that's processing all the data returned by the query. Set a variable to the first object, then you can compare other elements to it.
$res = $sttmt->fetchAll(PDO::FETCH_ASSOC);
$firstprod = new tbProduct($db);
$firstprod->loadFromArray(array_shift($res));
foreach ($res as $key => $productInfo) {
$prod = new tbProduct($db);
$prod->loadFromArray($productInfo);
if ($prod->status != $firstprod->status) {
// report inconsistent status
} elseif ($prod->owner != $firstprod->owner) {
// report inconsistent owner
} elseif ($prod->type != "assembly") {
// report that it must ba an assembly part
} ...
}

Related

How to put mutual followers/followings at top of the array when calling get followers/following api?

I'm calling a get API for a list of followers of another user, I want to put the users who I already follow on top of the list. How can I do that efficiently in laravel
this is how I have done it,
$user_details = User::with('followings:name,username,about_me,photo_url,leader_id as id')->where('id', $userId)->select('id')->first();
$my_details = User::with('followings:leader_id as id')->where('id', $request->logged_in_user->id)->select('id')->first()->toArray();
$ids = array_column($my_details['followings'], 'id');
$sortedfollowings = [];
foreach ($followings as $key => $value) {
if(in_array($value->id, $ids)){
array_unshift($sortedfollowings, $value);
} else {
array_push($sortedfollowings, $value);
}
}
I'm sorting list using foreach and if else, but it's not efficient when the list is like million followers.
This is more of an algorithm type of issue. This also depends on if you're using a package or not. Being this said, and not that much information provided and/or examples of what you've tried, I'll proceed explaining the process:
1.- A foreach loop that checks through your followings.
2.- Inside that loop, you add a conditional (if) that checks if any of your followings follow the id of the user profile you're visiting.
3.- Add into an array the users that follow that account.
4.- Send that array separately to your front-end.
5.- Merge that array in the beginning of the whole fetch.
6.- Exclude duplicates.
Again, I don't know which front-end you're using. I don't have any sample code, so I just proceeded with an explanation of how it can work.
This is a matter of loops and array manipulation.

parsing paginated json from web service

I am trying to parse a large amount of JSON data generated from a remote web service. The output produced is paginated across 500 URIs and each URI contains 100 JSON objects. I need to match a property in each JSON object, it's DOI (a digital object identifier), against a corresponding field fetched from a local database and then update the record.
The issue I am having is controlling my looping constructs to seek out the matching JSON DOI while making sure that all the data has been parsed.
As you can see I have tried to use a combination of break and continue statements but I am not able to 'move' beyond the first URI.
I later introduced a flag variable to help control the loops without effect.
while($obj = $result->fetch_object()){
for($i=1;$i<=$outputs_json['meta']['response']['total-pages'];$i++){
$url = 'xxxxxxxxxxxxxxx&page%5Bnumber%5D='."$i".'&page%5Bsize%5D=100';
if($outputs = json_decode(file_get_contents($url),true)===false){
}
else{
try{
$outputs = json_decode(file_get_contents($url),true);
$j=0;
do{
$flag = false;
$doi = trim($outputs['data'][$j]['attributes']['identifiers']['dois'][0], '"');
if(!utf8_encode($obj->doi)===$doi) continue;
}else{
$flag = true;
$j++;
}
}while($j!==101);
if($flag===true) break;
} catch(Exception $e) {
}
}
}
}
}
What is the optimal approach that guarantees each JSON object at all URIs is parsed and that CRUD operations are only performed on my database when a fetched record's DOI field matches the DOI property of the incoming JSON data?
I'm not 100% sure I understand every aspect of your question but for me it would make sense to change the order of execution
fetch page from external service
decode json and iterate through all 100 objects
get one DOI
fetch corresponding record from database
change db record
when all json-objects are progressed - fetch next url
repeat until all 100 urls are fetched
I think it's not a good idea to fetch one record from local DB and try to find it in 100 different remote calls - instead it's better to base your workflow/loops on fetched remote data and try to find the corresponding elements in your local DB
If you think that approach will fit your task - I can of course help you with the code :)

Variables being changed by TeamSpeak API for PHP

I'm developing a tool for a website and I came up with an odd problem, or better, an odd situation.
I'm using the code bellow to retrieve data from the TeamSpeak server. I use this info to build a profile on a user.
$ts3 = TeamSpeak3::factory("serverquery://dadada:dadada#dadada:1234/");
// Get the clients list
$a=$ts3->clientList();
// Get the groups list
$b=$ts3->ServerGroupList();
// Get the channels list
$c=$ts3->channelList();
Now, the odd situation is that the output of this code block:
// Get the clients list
$a=$ts3->clientList();
// Get the groups list
$b=$ts3->ServerGroupList();
// Get the channels list
$c=$ts3->channelList();
echo "<pre>";print_r($a);die();
(Notice the print_r)
Is totally different from the output of this code block:
// Get the clients list
$a=$ts3->clientList();
// Get the groups list
#$b=$ts3->ServerGroupList();
// Get the channels list
#$c=$ts3->channelList();
echo "<pre>";print_r($a);die();
What I mean is, the functions I call after clientList() (which output I store in the variable $a) are changing that variable's contents. This is, they're kind of appending their output to the variable.
I've never learned PHP professionally, I'm just trying it out... Am I missing something about this language that justifies this behavior? If I am, what can I do to stop it?
Thank you all.
You're seeing parts of the "Object" in Object Oriented Programming
$ts3 represents an Object containing all the information needed, along with some methods (or functions) that let you get data from the object. Some of these methods will do different things to the object itself, in order to retrieve additional data needed for a particular method call.
Consider the following simple Object:
Bike
color
gears
function __construct($color, $gears)
this.color = $color; this.gears = $gears
function upgrade()
this.headlight = true; this.gears = 10;
Now, when you first create it, it only has two properties:
$myBike = new Bike('red',5);
// $myBike.color = 'red';
// $myBike.gears = 5;
...but once you upgrade, properties have changed, and new ones are added.
$myBike->upgrade();
// $myBike.color = 'red';
// $myBike.gears = 10;
// $myBike.headlight = true;
Objects usually pass references rather than copying data, in order to save memory.
...but if you want to make sure that you're getting a copy that won't change (i.e. does not use data references to the $ts3 object), clone the variable.
$a = clone($ts3->clientList());
Be warned, this will effectively double the memory and processor usage for that variable.

Assign variable to an array from Active Directory

I am having trouble figuring out how to correct an issue I am having with the following code. I am trying to list the names and emails of all the people in my Active Directory. This code works. However, I also get the following warning when it is executed.
Warning: Cannot use a scalar value as an array.
From what I have read online I need to set " $name['mail']['0'] = "Not Found";" to an array. My question is how would I go about doing this. I have tried every way I could think of with no success. If anyone could provide me with some feedback it would be greatly appreciated.
foreach ($results as $name) {
if (!isset($name['mail']['0'])){
$name['mail']['0'] = "Not Found";
}
$allnames[$name['cn']['0']]['mail'] = $name['mail']['0'];
It looks like you are trying to assign the "Not Found" value BACK into the results of the ldap query you are running.
When I wrote code to get user information from ldap, I always inserted values into a different array (getting the fields I wanted) and then displayed THAT array out in the HTML:
foreach ($results as $name)
{
if (isset($name['mail']['0']))
// Check if it IS set, rather than not set and then append the data.
{
$allnames[$name['cn']['0']]['mail'] = $name['mail']['0'];
}
}
Then after you have all the fields you want you display the $allnames array.
Having said that, when I construct the array of user information, I make the array much much simpler - knowing what I want to display out, more along the lines of this:
foreach ($results as $name)
{
if (isset($name['mail']['0']))
// Check if it IS set, rather than not set and then append the data.
{
$allnames['mail'] = $name['mail']['0'];
}
}
You (or at least I) don't need to follow the ldap structure when making the array of information I have gathered, but rather I want to get specific fields from the directory and then display them by what they are - for example when I output the value in mail I might want to hyperlink it as an email address, so I keep it in an array element that I know by key and refer to later.

Wrong dataype for in_array

Good morning.
I'm currently trying to build a very basic caching system for one of my scripts. The cache is JSON data and contains only 1 key and it's value, but many individual fields, something like this;
{"Item1":"Item1 Description"}
{"Item2":"Item2 Description"}
{"Item3":"Item3 Description"}
What I'm intending to do is;
First check if a cache file is available
Then check if an item exists in the cache
Then add the new item along with it's description if it's not already in the cache...
...or return the item description if it's not there.
All data being stored is strings. The cache file doesn't store any other type of data.
I've put together a basic function but I'm having trouble getting it functioning;
function ItemIsInCache($CacheFile, $ItemId) {
if(file_exists($CacheFile)) {
$json = json_decode(file_get_contents($CacheFile, true));
if(in_array($ItemId, $json)) { // <<
$itemname = array_search($ItemId, $json);
return itemname;
} else {
$item[$itemId] = GrabItemName($ItemId);
$itemname = array_search($ItemId, $json); // <<
return $itemname;
}
} else {
$item[$ItemId] = GrabItemName($ItemId);
$ejson = json_encode($item);
file_put_contents($CacheFile, $ejson);
return $item[$ItemId];
}
}
Notes
GrabItemName is a different function that returns the description data based on the $ItemId.
The warnings I'm getting are Wrong datatype for second argument in both array_search() and in_array(), on lines 4 and lines 9 respectively (those are the line numbers in the above code - due to the nature of my script these numbers are later on) -- for simplicity, I've marked the problem lines with // <<.
The function is running in a loop which I've no problems with. The problems lie within this function.
What currently happens
Right now, if the cache doesn't exist, it creates it and adds the first item from the loop to the cache file in it's respective JSON format (that fires since the cache file doesn't exist, so after the final else statement).
However, items from the loop after that don't get added, presumably because the file exists and there's something wrong with the code.
The last part of the function works exactly as I want it to but the first part does not.
Expected behaviour with fixed code
Check cache > Return description if item exists ELSE add new item to cache.
The items and their associated descriptions will NOT change, but I'm pulling them from a rate limited API, and I need to ensure I cache whatever I can for everyones benefit.
So, any ideas what I'm doing wrong with the function? I'm sure it's something incredibly simple that I'm overlooking.
Your file is not JSON for an erray. The correct JSON for an array is
[
{"Item1":"Item1 Description"},
{"Item2":"Item2 Description"},
{"Item3":"Item3 Description"}
]
You're missing the brackets around the array, so you just get a single object.
When creating the initial file, you need to do:
$ejson = json_encode(array($item));
so that it's initialized as an array of one item, not just an item.

Categories