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.
Related
I am trying to get a reply text message from Clickatell using their Rest API, when I call the parseReplyCallback function when their system posts to my page - it seems to be null or I am not sure how to get the variables it is returning. What I would like to do is have all of the variables returned insert into a SQL database so I can use it elsewhere.
I have tried quite a few things, using various styles of getting the variables such as $_POST, $results['text'], $results->text, and so forth each time I can't seem to get any information out of it. I can't just var_dump or anything because I can't see any backend or console so I am pretty much in the blind, hoping someone else is using this system and has it working fine.
require __DIR__.'/clickatell/src/Rest.php';
use clickatell\ClickatellException;
use clickatell\Rest;
$Rest = new Rest("j8VKw3sJTZuVfQGVC7jdhA");
// Incoming traffic callbacks (MO/Two Way callbacks)
$Rest->parseReplyCallback(function ($result) {
//mysqli_query($con,"INSERT INTO `SMSCHAT` (`text`) VALUES ('$result')");
$mesageId = mysqli_real_escape_string($con,$result['messageId']);
$text = mysqli_real_escape_string($con,$result['text']);
$replyMessageId = mysqli_real_escape_string($con,$result['replyMessageId']);
$to = mysqli_real_escape_string($con,$result['toNumber']);
$from = mysqli_real_escape_string($con,$result['fromNumber']);
$charset = mysqli_real_escape_string($con,$result['charset']);
$udh = mysqli_real_escape_string($con,$result['udh']);
$network = mysqli_real_escape_string($con,$result['network']);
$keyword = mysqli_real_escape_string($con,$result['keyword']);
$timestamp = mysqli_real_escape_string($con,$result['timestamp']);
//do mysqli_query
});
I'd like for it to break the result into individual variables (because I plan on doing other things such as an auto-reply, etc) and upload it to the SQL database scrubbed.
Either doesn't create the table entry or gives me a blank one altogether in that first test where I put the result in the text field.
From a Clickatell point of view, although we understand what you're asking - it's unfortunately outside the scope of support that we offer on our products.
If you would like more information on our REST API functionality, please feel free to find it here: https://www.clickatell.com/developers/api-documentation/rest-api-reply-callback/
If you don't succeed in setting up the callbacks, please feel free to log a support ticket here: https://www.clickatell.com/contact/contact-support/ and one of our team members will reach out and try to assist where possible.
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
} ...
}
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 :)
Alright, I was put on hold because it wasn't clear what I am asking, so let me rephrase. I have this variable:
$town->streets
I declare it like so:
$town->streets[$i] = new street;
$town->streets[$i] = (Object)newStreet();
Of course I do it inside a for loop.
The newStreet() function generates a random number of houses for the street, each house has some attributes, such as type, tenants, is it a shop or library, what items there are inside if so, and so on. Right afterwards I echo the attributes of shop type houses to see if they are different.
As intended, every shop has different attributes. Now, right afterwards I have some code and after that I do the same echoing for houses again. However now each shop is the same as the last shop of the array, meaning that it somehow got overwritten inside some code. I am not accessing the houses, but am modifying other variables inside the streets. Yet I don't know why the houses and shops are getting overwritten.
The code does its task, meaning that cores and streets are distributed as I wanted to, so there are no actual errors, the objects' structure has never been a problem before, even though I have multiple objects structured like this. I am also aware that putting an object in a variable just creates a reference to it (or so I was told), but I still don't see why it is partially modified when I am not even accessing those parts at all.
some code is as follows:
$town->cores[0] = new core;
$town->cores[0]->id = 0;
for($i = 0;$i < $streetnum;$i++){
if($town->streets[$i]->start == -1){
$cid = round(mt_rand(0,count($town->cores)-1));
$town->streets[$i]->start = $cid;
if(count($town->cores) > 1 && round(mt_rand(0,10)) > 8){//PICK EXISTING CORE
$ends = $town->cores;
unset($ends[$cid]);
$town->streets[$i]->end = $ends[array_rand($ends,1)]->id;
}else{//NEW CORE
$town->streets[$i]->end = count($town->cores);
$town->cores[$town->streets[$i]->end] = new core;
$town->cores[$town->streets[$i]->end]->id = $town->streets[$i]->end;
}
}
}
}
My homepage contains weather for three cities around the world as displayed in the image
In the home page I declare 3 variables storing the RSS URL for each city
$newYorkWeatherSource = 'http://weather.yahooapis.com/forecastrss?p=USNY0996&u=f';
$londonWeatherSource = 'http://weather.yahooapis.com/forecastrss?p=UKXX0085&u=c';
$parisWeatherSource = 'http://weather.yahooapis.com/forecastrss?p=FRXX0076&u=c';
I pull identical tags out of the three URL's displayed above and use 3 identical functions apart apart from the variable passed into it.
Below shows the variable being passed into the function. Obviously other functions are used before $weather can be returned.
function new_york_current_weather($newYorkWeatherSource) {
// Get XML data from source
if (isset($newYorkWeatherSource)) {
$feed = file_get_contents($newYorkWeatherSource);
} else {
echo 'Feed not found. Check URL';
}
checkWeatherFeedExists($feed);
$xml = new SimpleXmlElement($feed);
$weather = get_dateTime($xml);
$weather = get_temperature_and_convert($xml);
$weather = get_conditions($xml);
$weather = get_icon($xml);
return $weather;
}
As I mentioned, I current repeat this function 3 times just replacing the $newYorkWeatherSource variable that is passed in the above example. Any ideas how I could reuse this function 3 times but yet pass in different URL to keep my homepage showing weather from the 3 cities? Ofcourse, it's easy to reuse the function if each city was represented on individual pages but the purpose is to keep them together for comparison.
Any ideas?
Thanks in advance.
As I mentioned, I current repeat this function 3 times just replacing the $newYorkWeatherSource variable that is passed in the above example. Any ideas how I could reuse this function 3 times but yet pass in different URL to keep my homepage showing weather from the 3 cities?
Maybe I'm entirely missing the point of your question, but are you asking how to rename the function and variables? Because, if so, it's just a matter of search and replace on the first few lines of the function...
function get_current_weather($rss_url) {
// Get XML data from source
if (isset($rss_url)) {
$feed = file_get_contents($rss_url);
} else {
echo 'Feed not found. Check URL';
}
// ...
Simply replace the city-specific functions with one starting out like this, and call it three times, one time for each specific city RSS feed URL.
From the comments:
but I'm just wondering what I will do with the 3 RSS URL variables because I can't replace rename them all to $rss_url as I will just be overwriting them until eventually the only URL will be Paris
I believe you may be suffering from a misunderstanding about PHP variable scope. Let's take this snippet as an example:
function bark($dog) {
echo 'The dog says ', $dog, ".\n";
}
$cat = 'meow';
bark($cat);
This code will emit The dog says meow. When you call the bark function with a variable, PHP takes a copy of the data* and passes it into the function as the variable name specified in the function. You don't need to name the variable the same thing both inside and outside. In fact, you can't** even see variables defined outside of a function:
function i_see_you() {
echo 'The dog heard the cat say ', $cat, ".\n";
}
$cat = 'meow';
i_see_you();
This code will emit The dog heard the cat say ., as $cat is out of scope here.
Getting back to the problem at hand, we still have three weather URLs.
$newYorkWeatherSource = 'http://weather.yahooapis.com/forecastrss?p=USNY0996&u=f';
$londonWeatherSource = 'http://weather.yahooapis.com/forecastrss?p=UKXX0085&u=c';
$parisWeatherSource = 'http://weather.yahooapis.com/forecastrss?p=FRXX0076&u=c';
All you need to do in order to make things work is:
echo get_current_weather($newYorkWeatherSource);
echo get_current_weather($londonWeatherSource);
echo get_current_weather($parisWeatherSource);
Inside the function, the proper variable with the proper name will have the proper data, and the right thing will happen.
*: PHP uses something called "copy-on-write", which does what you think it might do. It's completely safe to pass around variables containing large data. It will not consume unexpected amounts of memory. There's no need to use references. In fact, forget I ever said anything about references, you don't need them right now.
**: It's possible to see variables from the global scope by using the global keyword. Globals are bad practice and lead to spaghetti code. You might want to read more about variable scope in PHP.