I want to delete data in xml but it can't - php

When I try to delete, I can't delete it properly. It will stuck at number 2
if(isset($_GET['action'])) {
$mahasiswaa = simplexml_load_file('input.xml');
$nim = $_GET['nim'];
$index = 0;
$i =1;
$i++;
foreach($mahasiswaa->mahasiswa as $mahasiswa){
if($mahasiswa['nim']==$nim){
$index = $i;
break;
}
}
unset($mahasiswaa->mahasiswa[$index]);
file_put_contents('input.xml', $mahasiswaa->asXML());
}

your $i variable is constantly 2, the i++ should probably be inside the loop?
also, if your condition is never met, $index is 0 and its use will likely lead to an error.
The code will act only on the first match, whats ok, if that is what you expect.

Related

DBAL inside of for loop doesn't work properly

I created a function inside a longer plug-in for shopware, which is supposed to create a random number for every row in the database that has a "NULL" value in the "vouchercode" column. Right now I replaced the for-loop condition with a fixed number, because I wanted to make sure the problem doesn't occur because of the for-loop condition.
The problem is, that the for-loop just has effect on the database once.
For instance: I have this table 's_plugin_tnev'. Inside of that table are 6 rows. 4 of these have "NULL" as value inside of the vouchercode column.
So as far as I understand my code. It should loop 5 times through the same table and every time update one of those "NULL"-value columns, meanwhile after every loop one of those "NULL"-value columns should be filled with a random number and therefore no longer be SELECTed nor UPDATEd by this for-loop.
Though as mentioned earlier this doesn't happen. The for loop just works once apparently.
Here is my code snippet:
public function generateCode()
{
//Repeat action 5 times
for($i = 0; $i <= 4; $i++)
{
$rand = 0;
//Creates 16 times a number and add it to the var
for ($i = 0; $i<15; $i++)
{
$rand .= mt_rand(0,9);
}
//On Checkoutcomplete add $rand to database table
$addInt = "UPDATE s_plugin_tnev SET vouchercode = $rand
WHERE vouchercode IS NULL
LIMIT 1";
$connect = Shopware()->Db()->query($addInt);
}
}
As you can see I use the DBAL Framework, because this is the best supported way by Shopware.
My idea would be that the mistake has something to do with the $connect variable or that DBAL is not communicating fast enough with the Database.
Maybe someone has more experience with DBAL and could help me out.
Thanks in advance,
Max K
You have two for loops with $i, so on your first iteration, at the end the $i value is 15 and the first loop is executed only once.
Try this instead :
public function generateCode()
{
//Repeat action 5 times
for($i = 0; $i <= 4; $i++)
{
$rand = 0;
//Creates 16 times a number and add it to the var
for ($j = 0; $j<15; $j++) // $j NOT $i <---
{
$rand .= mt_rand(0,9);
}
//On Checkoutcomplete add $rand to database table
$addInt = "UPDATE s_plugin_tnev SET vouchercode = $rand
WHERE vouchercode IS NULL
LIMIT 1";
$connect = Shopware()->Db()->query($addInt);
}
}

PHP loop sum from database

$st = $this->db->prepare("SELECT * FROM invoices WHERE group_id=?");
$st->execute(array($id));
if($st->rowCount() >= 1){
foreach ($st as $row) {
$counter = $row["paymentAmount"];
$start = 1;
for($start; $start < $st->rowCount(); $start++) {
$counter = $counter + $row["paymentAmount"];
}
}
It actually print out $row["paymentAmount"] + $row["paymentAmount"] and so on, depending on how many $row["paymentAmount"] there is. But the problem is that the last output from $row["paymentAmount"] is 2500.
There is:
10000
10000
2500
And the result is: 7500
I want it to be: 22500
And if the last result is 3000 it shall be 23000. So what I simply need is this code to take every row from the database, just not the latest one.
Edit: I want it outside of the SQL query
You don't need PHP logic for something like this. The functionality is built right into SQL.
SELECT SUM(paymentAmount) FROM invoices WHERE group_id=?
You should let your database handle the sum unless you have a legitimate reason why it needs to be handled in PHP. The database is more efficient with this type of operation and you avoid a loop in PHP.
SELECT SUM(paymentAmount) AS TotalPaymentAmount FROM invoices WHERE group_id = ?
You can then change your PHP to return just one row:
$row = $st->fetch();
echo $row["TotalPaymentAmount"];
If you need to do this calculation outside of SQL, just change your loop:
if($st->rowCount() >= 1){
//init the counter to 0 before you loop through your rows
$counter = 0;
//the foreach will iterate over your result set and add the paymentAmount to $counter.
foreach ($st as $row) {
$counter += $row["paymentAmount"];
}
//echo results outside of the loop
echo $counter;
}
If you need to code this outside SQL on purpose (e.g. because you need to do further processing for each row), then I'd code this as follows:
if ($st->rowCount() >= 1) {
$counter = 0;
foreach ($st as $row) {
$counter += $row["paymentAmount"];
}
}

For loops to open a file that has to variable in the name

Hello I may have a really dumb question.
What I have got is code that writes a json file, in the file name it automatically adds to variable that is incrementing a number. I want to make the code that opens the file and writes the data to the web page. Opening the files that are filename(1)(1).json works, but no other file opens.
This is the code to create the file.
$Array = array("User Index" => $UniqueIndex,"User Name" => $UniqueUserName,"Submition Index" => $SubmitionCount,"Time & Date" => $TimeDate,"Submition" => $_POST["submition"]);
$ArrayWrite = fopen("forumdata/forumsubmition/ForumSubmition($UniqueIndex)($SubmitionCount).json", "w");
fwrite($ArrayWrite, json_encode($Array));
fclose($ArrayWrite);
This is the code that tries to open the file.
for ($Count = 0; $Count <= $blarg; $Count += 1)
for ($Count2 =0; $Count2 <= $blarg2; $Count2 += 1)
if (file_exists("forumdata/forumsubmition/ForumSubmition($Count2)($Count).json"))
{
do
{
$ForumInfo = file_get_contents("forumdata/forumsubmition/ForumSubmition($Count2)($Count).json", "r");
$ForumInfo2 = json_decode($ForumInfo, true);
if ($ForumInfo2["Submition"] != null)
foreach($ForumInfo2 as $value)
echo "$value<br>";
}
while (file_exists($ForumInfo));
}
Why would you even have the Do While loop when you got 2 for loops that loops over the files?
Just do this:
for ($count = 0; $count <= $blarg; $count += 1)
for ($count2 =0; $count2 <= $blarg2; $count2 += 1)
if (file_exists("forumdata/forumsubmition/ForumSubmition($count2)($count).json"))
{
$forumInfo = file_get_contents("forumdata/forumsubmition/ForumSubmition($count2)($count).json", "r");
$formattedForumInfo = json_decode($forumInfo, true);
if ($formattedForumInfo["Submition"] != null)
foreach($formattedForumInfo as $value)
echo "$value<br>";
}
I also formatted your variables to camel cased instead of pascal cased.
The reason you shouldn't juse the do.. while loop is because you already have a second for loop that rounds through all $blarg2 counts. Then you have a if construction that checks if the file exists. That should be enough. No need to check again. Because if it dosn't exist it just jumps over it and goes to the next count in your second for loop.

Deleting one of a collection on parent update

I am trying to delete (or create) a models associated objects when it is updated. Each bar has several taps. When you create a bar, these tap objects are created, and you can update that number and additional taps will be created or deleted as necessary.
Originally I just wanted to use pop like this:
$taps=$bar->taps;
if ( $taps_old < $taps_new){
for ($i = $taps_old; $i < $taps_new; $i++) {
$tap = Growlertap::create(['growlerstation_id' => $id]);
}
}
elseif ($taps_old > $taps_new) {
for ($i = $taps_new; $i < $taps_old; $i++) {
$taps->pop();
}
which doesn't work but doesn't give me an error. I know the if statement is working fine because the code below works:
elseif ($taps_old > $taps_new) {
for ($i = $taps_new; $i < $taps_old; $i++) {
Beertap::where('bar_id', '=', $id)->first()->delete();
}
}
This seems to not be the simplest way to write this. Is there a better way to write this?
By the way, for those wondering, this is in my update function in my controller.
pop() will remove the last item in your local collection, but it won't persist that change to the database.
Assuming it's a Beertap object, something like this should work:
Warning: untested code
...
elseif ($taps_old > $taps_new) {
for ($i = $taps_new; $i < $taps_old; $i++) {
$delete_me = $taps->pop();
$delete_me->delete();
}
}
or more succinctly: $taps->pop()->delete();
This should work Unfortunately this doesn't work because the DELETE statement doesn't support offsets.
Beertap::where('bar_id')->skip($taps_new)->delete();
So it skips as many taps as you want to keep and deletes the rest. You might want to use orderBy if it matters which rows get deleted.
Update
This should totally work now. First get all id's to delete from the collection and then delete them with one query
$idsToDelete = $taps->slice($taps_new)->modelKeys();
Beertap::destroy($idsToDelete);
Update 2
You can optimize the creation process as well (so that it's done in a single query)
$data = [];
for ($i = $taps_old; $i < $taps_new; $i++) {
$data[] = ['growlerstation_id' => $id];
}
Beertap::insert($data);
Note that you will loose the Eloquent features like automatic timestamps and model events when choosing to use insert().

I need to have a variable IN my variable name, not AS my variable name

How would I do that?
According to PHP.net,
$a = "hi";
$hi = 2;
$$a; // returns 2
However, I need:
$i = 2;
$_POST['link$i']; // I need this to return the same thing as $_POST['link2']
Here is how I have my code.
for ($i = 1; $i <= 40; $i++)
{
if(!empty($link$i))
{
$link$i = mysql_real_escape_string($_POST['link$i']);
mysql_query("
INSERT INTO links (link, rimageid) VALUES
('".$link$i."', '".$id."') ");
} else { }
}
The reason I'm doing this is because I have a lot of text input fields posting their values to this file, and I'd like to define and insert each of their values via a for loop instead of manually inserting each single link into mysql.
Right now, I get:
Parse error: syntax error, unexpected T_VARIABLE, expecting ')' in C:\xampp\htdocs\new2.php on line 22
How would I go about doing this?
Thanks!
For array index concatenation, ok, but this code
for ($i = 1; $i <= 40; $i++)
{
if(!empty($link$i))
{
$link$i = mysql_real_escape_string($_POST['link$i']);
mysql_query("
INSERT INTO links (link, rimageid) VALUES
('".$link$i."', '".$id."') ");
} else { }
}
won't work as you expect, i.e. name a variable like the result it's not necessary, why would you want to do that? PHP doesn't care about the variable name and if it's coordinated with the result.
Just do:
for ($i = 1; $i <= 40; $i++)
{
if(!empty($_POST['link'.$i]))
{
$regular_variable_name = mysql_real_escape_string($_POST['link'.$i]);
mysql_query("INSERT INTO links (link, rimageid) VALUES ('".$regular_variable_name."', '".$id."') ");
} else { }
}
How about string concatenation?
$_POST['link'.$i];
You are receiving a syntax error because $link$i is not valid.
if you want the end value to be link2 then you need a solution like Nick Shepherd suggested.
It could be easier to see what is going on if you create the string that you want for the key first.
$key = 'link' . $i;
After that you can use the key whenever you want, in a conditional like
if (!empty($_POST[$key])) {
and again in your mysql_escape
mysql_real_escape_string($_POST[$key]);
$_POST['link' . $i];
This should solve your problem. For indexes of an array you can simply concatenate the string for the index that you are trying to resolve.
yep... you can do the following
$ = 2;
$link = "link" . $i;
if(isset($_POST[$link])){
//do something
}
or
$_POST[$link.$i]
the same goes for methods
$type = "Something";
$method = "get" . $type;
$this->$method(); //calls method -> getSomething()

Categories