Jump to content



Highest Reputation Content


#8885 One Mod Rewrite Rule Won'T Work

Posted by HartleySan on 28 July 2012 - 10:59 AM

If "hiv" is never followed by an e, you could change the one regex as follows:
^hiv[^e]|aids[a-z_\-\./]*$
  • 4


#6644 Just Started This Book Today!

Posted by rob on 26 March 2012 - 10:53 AM

It does affect something it affects the source code layout, which is the whole point of using it, to make source code more readable.
  • 4


#14402 Really Disturbing

Posted by margaux on 1 May 2013 - 4:56 PM

Hey xto, I'm going to try to say this in the nicest way possible -  You're in danger of trying people's patience not because you ask questions, we like questions, but because you ask questions in a way that doesn't provide the information needed to try to answer them.

 

1. please read the forum guidelines - Look for the little grey text bottom right of most pages, labelled Guidelines

2. please post only RELEVANT code and error messages within code tags. We don't need to see the entire output from your error message. It's actually distracting. Use code tags which are on the edit bar and they look like <>

3. post the relevant CODE, you keep posting the error message but not any code.

4. You should start a new thread for each new question. One reason for doing so is that other people with the same question can search and find your thread. If your question is part of another thread, it won't be found and won't help others.

5. You're asking questions that you should be able to solve 1 because the level of  experience for this book expects you know some basic debugging strategies and 2. with a little bit of online searching you would get some pointers as to where to look for the cause of your error.

 

I really shouldn't answer your question given the above but ...

 

somewhere in your code you are referencing an array value using 'sale_price' as the index, which doesn't exist. I'm going to hazard a guess that you have a line that includes $row['sale_price']. From the error dump you posted, you will see there is no index 'sale_price' but there is one named 'price'. Given what info you've provided that's all I can help with. If this doesn't help solve the problem, start a new thread and post the code that is causing the error :)


  • 4


#15287 Use Data Type Enum For Form Drop-Down Options

Posted by margaux on 2 July 2013 - 3:10 PM

You're close. You have not stored your result anywhere with mysqli_fetch_array, so you won't be able to access the returned data.

$table_name = "collection";
$column_name = "PENDING";

echo "<select name=\"$column_name\"><option>Select one</option>";
$q = "SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_NAME = '$table_name' AND COLUMN_NAME = '$column_name'";
$r = mysqli_query($dbc, $q);

$row = mysqli_fetch_array($r);

$enumList = explode(",", str_replace("'", "", substr($row['COLUMN_TYPE'], 5, (strlen($row['COLUMN_TYPE'])-6))));
foreach($enumList as $value)
    echo "<option value=\"$value\">$value</option>";

echo "</select>";

  • 3


#14154 Multiple Mysql_Fetch_Array That Drives Me Nuts

Posted by HartleySan on 18 April 2013 - 3:12 PM

Hmmm... I'm not entirely sure what you're going for, but I'm definitely seeing some serious inefficiencies. While I don't know the sizes of your tables (i.e., how many records each one contains), you seem to be grabbing everything from the purchases table, and within that while loop, you are then grabbing everything from the other two tables where a certain value equals a certain value in the purchases table.
 
Also, a lot of the math you're doing (for example, adding up values for the amount of a given order) and formatting of the date can be done on the DB side, which can further speed things up.
In general, I think your goal should be to format all your data exactly the way you want to print it out to the screen by using one query. That may not be possible, and I'm not entirely sure what you want, but I'm thinking that we *may* be able to get everything you want in one query. I will attempt to do so below, but I can't guarantee that it'll work.
 
To start with, I'm trying really hard to figure out what exactly you're going for, but it's a bit abstract with the variables you're using. I'm not sure if you're using those variables on purpose to disguise your code for this thread, or if you're really using those variables in your code, but either way, I would definitely recommend using more logical variable names.
 
Anyway, here's my interpretation of your code:
You're printing out a table of purchase orders. The first column is the row number (which you do not seem to be properly incrementing within the outer while loop). The second column is the ID of a purchase order that a customer has made. The third column is the name of the customer (and it looks like you're storing their first and last name in one column in the customers table, which I would recommend against). The fourth column is the date and time of the purchase. The fifth column is the total amount of the purchase order formatted in dollars and cents. Lastly, I'm not sure what the last two columns are, but they aren't coming from DB data, so I'll ignore those for now.
 
Assuming my interpretation above is correct, I think you need to do an inner join across three tables with the purchases table being the main table. Also, I think you need to group your purchases together by the purchase ID, so that you can use an aggregate function to add up the price of the individual items within each specific order.
Does that make sense?
 
Anyway, here's the query that I'm *thinking* will work (but I can't guarantee that it does or that it's what you want):
SELECT c.cust_id, c.name AS cust_name, p.po_id AS order_num, p.cust_id, DATE_FORMAT(p.timestamp, '%m %d, %Y') AS date, o.po_id, SUM(o.delivered * o.srp) AS amount
FROM customers AS c, purchases AS p, po_content AS o
WHERE c.cust_id = p.cust_id AND p.po_id = o.po_id
GROUP BY o.po_id
ORDER BY p.timestamp ASC
LIMIT $start $display;
 
A few notes about the query:
1) For your query, a join is essential. Specifically, two inner joins on the purchases table is what you need. Joins are tricky at first, but they're essential for most DBs, so I'd recommend studying up on them.
 
2) Only select the columns you need. Using SELECT * for three separate queries is getting you a lot of data you don't need, and is very inefficient.
 
3) Use aliases (e.g., "AS c", "AS p", etc.) on the tables to make typing out the query shorter and easier. Also, aliases are essential for being able to easily reference the results of aggregate functions, formatted, dates, etc.
 
4) Format the timestamp on the SQL side using the DATE_FORMAT function. It's faster and easier. Also, give the formatted date an alias to make it easier to access on the PHP side. Here's more info on the DATE_FORMAT function:
 
5) I'd calculate the total amount of each order on the SQL side. To do so, you need to use the SUM aggregate function, and also use the GROUP BY clause to group your results together by order number so that you are adding up the correct grouping of items. Also, I'd assign an alias to the result of the SUM function.
 
6) The "ASC" part of the query is not necessary, since that's the default ordering. I left it anyway to avoid any further confusion.
 
7) I used "o" as the alias of the po_content table, as it seems like a table of orders to me.
 
That will hopefully handle the query side of things.
Unfortunately, I think there are some other issues with your code as well:
1) You're not incrementing $rownum in the while loop.
 
2) You're assigning your $bgcolor value to the entire table, not individual table rows. Also, I'm pretty sure the resulting HTML will be syntactically invalid and not work.
 
3) You're creating a new table each time through the while loop.
 
4) You're putting a div within a td for the total, which I wouldn't do.
 
Point being, without sounding too harsh, I think your code has some serious issues and needs some re-working. I get the feeling that you might be getting a bit too ambitious about your personal project without first understanding all the basics you need.
I don't mean to say that you shouldn't be ambitious, but I think you should probably go back to the book for a bit and bone up on queries with joins, HTML and PHP syntax, as well as think more about the logic of your while loop and the type of HTML that it is creating.
 
Anyway, below, I'm going to present the PHP I would use for your situation. Again, please keep in mind that I'm doing my best to piece together exactly what you want (and I'm not entirely sure), so I could be way off on this.
// I'm assuming that $agent and $encoder are already defined above.
 
$row_num = 1;
 
$total = 0;
 
$bg_color = '#FFF';
 
$q = "SELECT c.cust_id, c.name AS cust_name, p.po_id AS order_num, p.cust_id, DATE_FORMAT(p.timestamp, '%m %d, %Y') AS date, o.po_id, SUM(o.delivered * o.srp) AS amount FROM customers AS c, purchases AS p, po_content AS o WHERE c.cust_id = p.cust_id AND p.po_id = o.po_id GROUP BY o.po_id ORDER BY p.timestamp ASC LIMIT $start $display;";
// I'm assuming that $start and $display are already defined above.
 
$r = mysqli_query($dbc, $r);
// I am assuming that $dbc is already defined above. You also seem to have omitted this argument in your code.
 
echo '<table class="order_details">';
// I'd use CSS to properly format the table instead of the inline attributes you're using.
// As such, I have assigned a class to the table for that exact reason.
// Also, your table doesn't have any headers, but you may want to add them along with thead, th, tbody, and tfoot tags.
 
while ($row = mysqli_fetch_array($r, MYSQLI_ASSOC)) {
  
  echo '<tr style="background-color: ' . $bg_color . ';">
  
  <td>' . $row_num . '</td>
  
  <td>' . $row['order_num'] . '</td>
  
  <td>' . $row['cust_name'] . '</td>
  
  <td>' . $row['date'] . '</td>
  
  <td>' . number_format($row['amount'], 2) . '</td>
  
  <td>' . $agent . '</td>
  
  <td>' . $encoder . '</td>
  
  </tr>';
  
  $row_num++; // Don't forget to increment this.
  
  $total += $row['amount']; // This is the summation of the unformatted amounts, which could cause issues.
  
  $bg_color = ($row_num % 2 === 0) ? '#F3F3F3' : '#FFF'; // Ternary operation for brevity
  
}
 
echo '<tr style="background-color: ' . $bg_color . ';">
 
<td colspan="4" class="total_row">Total</td>
 
<td>' . number_format($total, 2) . '</td>
 
</tr>';
// Formatted to line up with the amount column.
// Also, note that I handled the total the same way you did, but if you calculate the total on the
// unformatted amount values, then you may get a discrepancy in which the amounts don't add up to the total.
// Also, again, I'd use CSS (not inline HTML) to align "Total" to the right.
// Lastly, you may want to put the total in a tfoot element.
 
Well, I think that's about it.
After all this writing, I really hope that I got close to what you wanted, and that this post is of some use.
Please let me know.
Thanks.

  • 3


#13112 Forms In Javascript Or Php?

Posted by HartleySan on 19 February 2013 - 10:38 AM

Awesomo, to give you a concrete example, I'm going to use Jonathon's example above because I think it's a good example.
First off, you'll want to attach a JS event handler to the form so that when the form is submitted, JS intercepts the form submission and allows you to do whatever you need to before the form is actually submitted.
This can be accomplished as follows:
 
document.forms[0].onsubmit = function () {
  
  return false;
  
};
 
On any HTML page that contains at least one form, JS provides you with the forms array, which is a property of the document object. forms[0] always applies to the first form on the page. You can adjust the array index as need be.
The return false statement actually stops the form from being submitted. (Don't worry though, as we'll actually force the form to be submitted in a second, assuming everything is okay.)
 
Next, let's imagine that we have a user name text input that must be only letters and numbers, as Jonathon said. Here's a simple JS regex we can write to test for that:
 
document.forms[0].onsubmit = function () {
  
  if (/^[A-Za-z0-9]+$/.test(this.elements[0].value)) {
  
  }
  
  return false;
  
};
 
The above if statement tests that the user name text input contains only letters (either uppercase or lowercase) and numbers (and is not an empty string). I should note that I make several assumptions with this code:
The user name text input is the first input in the form. This can be seen by the this.elements[0] in the if statement. In this case, this refers to the form object we're interested in, and elements is an array attached to all JS form objects that allows you to access all the inputs items in the form. Naturally, elements[0] refers to the first element in the form. If you'd rather check the user name text input by ID (assuming the ID is "username"), you can replace this.elements[0] with document.getElementById('username'). The value property at the end will give you the actual string entered into the text input object.
 
If the above if statement evaluates to true, then we can assume that the user name does in fact only contain letters and numbers. That being the case, we should then submit the form normally.
However, if the if statement returns false, then we should change the border of the user name text input to red.
The following code will do just that:
 
document.forms[0].onsubmit = function () {
  
  if (/^[A-Za-z0-9]+$/.test(this.elements[0].value)) {
    
    this.submit();
    
  } else {
    
    this.elements[0].style.border = '#F00 solid 2px';
    
  }
  
  return false;
  
};
 
As before, this refers to the form object in question. this.submit() will actually submit the form as if JS never intercepted the form submit request in the first place.
If the if statement fails, then we use this.elements[0] (or document.getElementById('username'), if you want) to reference the user name text input object, and then change the border to a 2-pixel red border.
 
That's the basic concept to simple JS form validation built on top of standard PHP form validation.
One of the keys to this method is that you only submit the form when everything is okay.
And naturally, the concepts above can be rinsed and repeated as many times as necessary to validate all your form input.
I hope that helps.

  • 3


#11560 Simple Question On Php Form Validation...

Posted by HartleySan on 8 December 2012 - 12:32 AM

When you execute the header(Location: 'somelocation.php#contact'); line, you're reloading the page, which causes the $_POST array, $errors variable, etc. to no longer exist. This essentially amounts to the same thing as having never performed any validation at all (and thus the $errors variable not existing, which is why your "Please fix the errors" line is never printed out).

A better solution would be to put the anchor jump (i.e., the fragment part in the URL after the number sign (#)) in the URL specified for the action attribute of the contact form. For example, if the following is the opening tag for your contact form:

<form action="somelocation.php" method="post">

Then change it to the following:

<form action="somelocation.php#contact" method="post">

Of course, this assumes that somelocation.php refers to the original page the form is on (which seems to be the case according to what you said).
By doing the above, you can very easily get the jump you want and still properly validate everything.

In terms of outputting a thank you message upon successful validation, I'd do something like the following:

if (!$errors) {

  // Validation was successful. Output a thank you message.

} else {

  // Either there was an error or this is the first time the page was loaded.
  // Load the page with the form and any necessary sticky values and error messages.

}

Hope that helps.
  • 3


#11339 Ch. 11 Using Unlink() With A Reset Button Possible?

Posted by Antonio Conte on 27 November 2012 - 10:43 PM

This can absolutely be done via GET. What you would do is using IDs as the get value. Save the filenames to an array on the form ID => "name". You then build links the same way, but with ?remove=$ID. You cast $_GET['id'] to an integer, find the filename in array by using the ID, build a full path where you add the filename, then use unlink() to delete the file.

An easy way to do this would be something like:


$handle = ""; // open file

$file_array = array(); // The file names

while ( ($file = readdir($handle)) !== false )
{
    if ($entry != "." && $entry != "..")
    {
	   $file_array[] = $file;
    } // Read files to array
}

// Simple delete
if ( ! empty($_GET) )
{
   
    $upload_dir = "uploadsDirectoryHere/"; // Upload dir
    $file_id = (int) $_GET['delete']; // File_array ID

    // Make sure file is found
    if ( array_key_exists($file_id, $file_array) )
    {
		 $delete_file = $upload_dir . $file_array[$file_id];

		 // Make sure file exists
		 if ( file_exists($delete_file) )
		 {
			  unset(file_array[$file_id]); // Remove from file array
			  unlink($delete_file); // Actually delete file here
		 }
    }

// Print out file names and links for deleting them
foreach ( $file_array as $id => $filename )
{
    echo $filename . '<a href="page.php?delete='.$id.'">Delete file</a>;
}

Not tested, but that should be the basic idea. Sorry about errors/etc. Beginning to get tired here.
  • 3


#11126 Activation

Posted by swisse on 16 November 2012 - 6:25 AM

Hi uncfelt1147,

I'm no expert in PHP, just like you I'm a newbie. I find your query statement a little bit long with all those \n's.
This is the code from Larry's book:

$q = "UPDATE users SET active=NULL WHERE (email='" . mysqli_real_escape_string($dbc, $_GET['x']) . "' AND active='" .mysqli_real_escape_string($dbc, $_GET['y']) . "') LIMIT 1";

I check always with phpMyAdmin that the person I'm activating is recorded in my database.
  • 3


#10822 Access All Objects Of A Class

Posted by Edward on 31 October 2012 - 7:11 AM

Yes you can do this by creating a static array, then you can assign each new instance of the newly created class to that array. This method is often used when storing active database connections.
  • 3


#10794 How Do You Learn To Really Write Php By Yourself?

Posted by Antonio Conte on 30 October 2012 - 7:30 PM

Programming is all about actions to data. When you have been programming for a while, you can identify that you need to do this and that to the data to achive a result.

To take your calculator example. What does a calculator do? It computes answers out of operations performed on numbers, right? That's a pretty abstract description of a calculator, but it's a start. We must then decide what operations, actions, this calculator should be able to perform. Let's say we want to able to multiply two numbers, how can we code that?

Let's make a simple plan:
1. We need a form with two HTML input fields.
2. We need to make sure the form is submitted by the user
3. We need to make sure both fields have valid values
4. We need to display error messages if not
5. We need to calculate the answer and display it to the user.

This applies to all programming. My first programming teacher forced us to always write down all steps needed to achieve the wanted result. I think you should do the same. When you want to solve the problem, sit down and write a step-by-step plan on how to solve it. You don't need to follow that plan in the end, but you'll begin to see that planning pays off in the end.

Hope that helps a bit.
  • 3


#10649 Advanced Question - What Is Happening In This For In Loop?

Posted by HartleySan on 24 October 2012 - 2:53 AM

When you ask for more "explicit" code to accomplish the same thing, I assume that you're really asking, "What's a simple way to accomplish the same thing?"

I'm not sure if there's a simpler way, as "simpler" code might actually be more confusing for a JS guru, but for demonstration purposes, I have put together some sample code that achieves the same thing without the use of closures (at least, not in the sense that you're thinking about) and without the use of the map method.

Keep in mind that my code is super simplistic, and I wouldn't actually recommend ever doing things this way, but for demonstration purposes, I think it serves its purpose well.

<!DOCTYPE html>

<html lang="en">

  <head>

    <meta charset="UTF-8">

    <title>Chaining alternative</title>

  </head>

  <body>

    <a href="#" id="link1">Link 1</a>

    <a href="#" id="link2">Link 2</a>

    <a href="#" id="link3">Link 3</a>

    <script>

      // this in these two functions is equal to the out array in function X.

      function color(x) {

        for (var i = 0; i < this.length; i++) {

          this[i].style.color = x;

        }

        return this;

      }

      function size(x) {

        for (var i = 0; i < this.length; i++) {

          this[i].style.fontSize = x;

        }

        return this;

      }

      function X(css) {

        var out = [];

        // For this simplified example, I'm assuming that css is always a tag name, not an ID.
        var tags = document.getElementsByTagName(css);

        for (var i = 0; i < tags.length; i++) {

          out.push(tags[i]);

        }

        out['color'] = color;

        out['size'] = size;

        return out;

      }

      X('a').color('red').size('24px');

    </script>

  </body>

</html>

Does that help clarify things at all?

I know that that one guy's code on the other site is very difficult, so don't feel bad if it doesn't all click right away. He has a ton of complex code (and sometimes JS-specific idiosyncrasies) all stuck together.

To reply to your three points of interest:

1) Yes, scope in JS is very interesting. The thing about JS is that functions are lexically scoped, meaning that they contain the scope in which they're defined, not in which they are called. This is different from C, for example.

2) Yes, I agree that the way the length property is calculated in JS is interesting, but that's just the way it's defined in the ECMA specs (for better or worse). To give some more explanation, if an array contains only associative indexes, since that's akin to an object (not an array) in JS, the length will be 0. Another interesting caveat is that if, for example, you have an array with only 1 element, but the index of that element is 5, then the length will be reported as 6 (as per what I said in my previous post (i.e., 5 + 1)).

3) Closures are basically used as a tricky way to freeze a variable's state in time. For example, you may have a constantly changing global variable, but if you want to retain the value of that variable at one specific time, then you need to use a closure. Remember that every time a function is called, a closure is created (just usually not a closure in the sense that's commonly talked about). This happens because whenever a function is called, all the variables passed to that function are frozen in the state that they are in when the function was called. It's prudent to remember that this is NOT the case with function references/function definitions; only function calls. Anyway, for the m example, if you just remember that m is equal a specific instance of meths[meth] each time through the for-in loop, then you should be fine.

Hope that helps (and by all means, fire back another comment if it doesn't).
  • 3


#10152 Pass A Multi Dimensional Array To Hidden Forms

Posted by HartleySan on 24 September 2012 - 6:26 AM

If you really want to, you can do something like the following:

<!DOCTYPE html>

<html lang="en">

  <head>

    <meta charset="UTF-8">

    <title>Test</title>

  </head>

  <body>

    <?php

      if (isset($_POST['submit'])) {

        echo '<pre>';

        print_r($_POST['data']);

        echo '</pre>';

      }

    ?>

    <form action="" method="post">

      <input type="hidden" name="data[]" value="0">

      <input type="hidden" name="data[0][]" value="Cheese">

      <input type="hidden" name="data[0][]" value="Bacon">

      <input type="hidden" name="data[]" value="1">

      <input type="hidden" name="data[1][]" value="Peppers">

      <input type="hidden" name="data[1][]" value="Fork">

      <input type="submit" name="submit" value="Submit">

    </form>

  </body>

</html>

However, I'm having trouble coming up with a reason you'd want to do that. As rob said, storing that data in a session would probably be better.
  • 3


#14255 Ch 6 'Can I Start Here?'

Posted by Antonio Conte on 22 April 2013 - 5:25 AM

I would really recommend you starting from the beginning with any book about introductory OOP. There's a solid learning curve at first when you switch from procedural to object-oriented programming, and most of that is due to the way you have to think about code. It's a very common mistake to jump straight into code, as many feel they already master coding to some degree. While that's true for many, the basic theory is insanely important, and has very little to do with coding skills. As I said earlier, it's a different approach to coding, not necessarily harder or more advanced.

 

I don't really remember the chapters in this book. You can probably skip some of the first chapters, but make sure you don't skip any OOP theory from the get go. While much of the stuff explained might seem below your current coding level, (and it likely is) it's fundamental in OOP. Make sure to don't blaze through theory because it seems simple. It'll pay of later to focus.

 

What I consider essential for understanding object-orientation:

- Theory about a Class and an Object. Read this thoroughly. Read it more than once.

- Theory about class structures and code planning (i.e what constitutes a class. This is very important and it's not obvious at first)

- Delegation. (A method should do only one specific job)

- Visibility (public, protected, private)

- Class scope and application scope.

- Polymorphism (building of existing classes)

 

Larry is very good at explaining all this, but make sure to take it slow from the start. It will really pay of later. Learning object-orientation is not tricky from a of coding skill level standpoint, but because of the theoretic foundation you need to write good code.

 

Good luck, and have fun. :)


  • 3