Jump to content

Andy-H

Members
  • Posts

    2,000
  • Joined

  • Last visited

  • Days Won

    1

Posts posted by Andy-H

  1. Filtering user input requires different implementations depending on what you will be doing with the data, i.e. if you're writing data to a persistence layer, you should use methods appropriate to the persistence layer and abstraction layer that you're using, a few examples:

     

    PDO:

    // create database handle
    $stmt = $dbh->prepare('SELECT * FROM users WHERE username = ? LIMIT 1');
    $stmt->execute(array($_POST['username'])); // we don't need to escape here as PDO prepared statements escape parameters for us
    

     

    mysql_* (which is deprecated, and will be moved into an extension, use PDO or MySQLi or something)

    // connect to database
    $result = mysql_query("SELECT * FROM users WHERE username = '". mysql_real_escape_string($_POST['username']) ."' LIMIT 1");
    

     

    HTML

    <?= echo htmlspecialchars($_POST['username'], ENT_QUOTES, 'UTF-8'); ?>
    <?= echo htmlentities($_POST['username'], ENT_QUOTES, 'UTF-8'); // replace with your character encoding ?>
    

    FYI: I would recomment htmlentities here as it translates all entities

     

    For a plain-text email, you won't need to escape your data, for a HTML email, you would escape it the same as you escape HTML output

  2. Hi Mark,

     

    I think you would be better splitting this into 4 tables, members, companies, area_codes and company_area_codes, see attachment.

     

    This way, companies can have multiple members, and their details do not need to be duplicated. They can also cover multiple area codes without duplication of the area code.

     

    Say you wanted to get all area codes that a company covers:

    SELECT ac.code FROM companies c
      INNER JOIN company_area_codes cac ON ( c.id = cac.company_id )
      INNER JOIN area_codes ac ON ( ac.id = cac.area_code_id )
    WHERE c.id = 1
    

    You can also, of course, join the members table using company_id to get coverage for a member etc.

    post-65947-0-23154300-1395871584_thumb.png

  3. You have created your $expectedKeys array incorrectly, you use:

     

    array($FName, $LName); // etc
    

     

    However, these variables are set to $_POST['fname'], $_POST['lname'] etc. This will result in an empty string, or the data posted, if the form has been submitted, so later in your script you are essentially calling:

     

    if ( !empty($_POST['']) )

     

    or

     

    if ( !empty($_POST['some_random_name']) )

     

    So you need to change your expected keys array to contain the relevant strings.

  4. Hi All,

     

    A friend of mine has asked me if I know of any PHP developers looking for work in the Manchester area, so I thought I'd post on here, in-case any of you guys were interested.

     

    The vacancy is at a commercial and leisure vehicle tracking company based in Stockport (SK1), they are currently expanding a small digital team due to growth.

     

    Ideal skills required are:

    • OO PHP
    • MySQL
    • HTML
    • CSS
    • Javascript
    • jQuery
    • Google maps API V3

     

    Experience with basic LAMP stack administration would also be advantageous.

     

    It's a relaxed work atmosphere and all the people that work there are really easy to get on with (I used to work there).

     

    They're offering a salary of between £22,000 and £27,000 depending on experience, and ideally want someone with 2+ years commercial experience or equivalent skill level.

     

    If you're interested the company is Phantom Ltd (http://phantom.uk.net) and you can apply via Monster (http://jobview.monster.co.uk/PHP-Web-Developer-Job-Stockport-North-West-UK-128645968.aspx)

     

    Regards,

     

    Andy

  5. Hi I am posting on behalf of a friend of mine who works for a leading digital agency in Manchester City Centre, they are currently recruiting for a PHP developer and an ASP.NET developer available for work in Manchester City Centre (http://www.reasondigital.com/contact-us/#contactusbottom).

     

    The role includes benefits such as:

    • Great transport links (about 5 minutes from both Manchester Picadilly and Manchester Victoria train stations)
    • Competitive salary (£26,000 - £32,000 DOE)
    • Work with major clients such as BBC, Save the Children and Meningitis Trust
    • A great company to work for with pleasant colleagues (I know two of their team personally)

    They're looking for someone with proficiency in (amongst other things):

    • (OO) PHP
    • MySQL
    • Javascript / jQuery
    • HTML/HTML 5
    • CSS

     

    For a full job description see: http://www.reasondigital.com/work-for-us/php-developer/

     

    NO AGENCIES PLEASE!

  6. I would use the

     

     

    o.draw(img);
    

     

    example, simply because the interface doesn't limit you to only drawing one image to your 'tileSheet', i.e. you may in future need to draw 4 images.

     

    As for memory footprint, I would assume no to little difference as the same amount of objects are created in the same scope.

  7. Sorry, just tested those examples, fixed a mistake:

     

    <?phpabstract class FilterableProperties {   protected $_data = array();   public function __set($key, $value) {    if ( !in_array($key, array_keys($this->_data)) )      return null;    $beforeFilter = "_before_set_{$key}";    if ( method_exists($this, $beforeFilter) ) {      $this->_data[$key] = call_user_func(array($this, $beforeFilter), $value);    } else {      $this->_data[$key] = $value;    }  }  public function __get($key) {    return isset($this->_data[$key]) ? $this->_data[$key] : null;  }}class Address extends FilterableProperties {  protected $_data = array('property_name_or_number', 'street', 'town', 'city', 'county', 'postcode', 'country');  // now these properties can not be accessed and are actually protected  protected $_country_code  = null;  protected $_country_codes = array(    'United Kingdom' => 'UK',    'United States'  => 'USA',    'France'         => 'FR',    'Germany'        => 'GER'    // ...  );   protected function _before_set_postcode($newPostcode) {    $newPostcode = strtoupper(preg_replace('/\s+/', '', $newPostcode));    if ( !preg_match("/^[A-Z]{1,2}[0-9]{2,3}[A-Z]{2}$/", $newPostcode) &&      !preg_match("/^[A-Z]{1,2}[0-9]{1}[A-Z]{1}[0-9]{1}[A-Z]{2}$/", $newPostcode) )       throw new Exception('Invalid postcode');    return substr($newPostcode, 0, -3) .' '. substr($newPostcode, -3);  }  protected function _before_set_country($newCountry) {    if ( !in_array($newCountry, array_keys($this->_country_codes)) )      throw new Exception('Invalid country');    $this->_country_code = $this->_country_codes[$newCountry];    return $newCountry;  }} $Address = new Address();$Address->postcode = 'S K 1 51 T W';var_dump($Address->postcode); // SK15 1TW

     
    Still, I guess one mistake in untested code at 00:30 isn't too bad lol
  8. __get and __set are "magic" hook methods, they are called whenever a property is accessed on an instance of a class, and whenever a property is assigned a value on an instance of a class that implement them respectively.

     

    They can be used to control how a property is inserted into or retrieved from an object, I.e. they allow you to run post and/or pre-processing tasks to control the data that the object contains. Take the Address example:

     

    abstract class FilterableProperties { // this would be better as a trait  public function __get($name) {    $property     = $this->_get_property($name);    $beforeFilter = "_before_get_{$name}";    if ( method_exists($this, $beforeFilter) )      return call_user_func(array($this, $beforeFilter), $this->property);    return $this->$property;  }  public function __set($name, $value) {    $property     = $this->_get_property($name);    $beforeFilter = "_before_set_{$name}";    if ( method_exists($this, $beforeFilter) ) {      $this->$property = call_user_func(array($this, $beforeFilter), $value);    } else {      $this->$property = $value;    }  }  protected function _get_property($name) {    $property = "_{$name}";    if ( !property_exists($this, $property) )      throw new Exception(sprintf('Property %s does not exist on %s', $name, get_class($this)));    return $property;  }}class Address extends FilterableProperties {  protected $_property_name_or_number = null;  protected $_street = null;  protected $_town = null;  protected $_city = null;  protected $_county = null;  protected $_postcode = null;  protected $_country = null;  protected $_country_code = null;   protected function _before_set_postcode($newPostcode) {    $newPostcode = strtoupper(preg_replace('/\s+/', '', $newPostcode));    if ( !preg_match("/^[A-Z]{1,2}[0-9]{2,3}[A-Z]{2}$/", $newPostcode) &&      !preg_match("/^[A-Z]{1,2}[0-9]{1}[A-Z]{1}[0-9]{1}[A-Z]{2}$/", $newPostcode) ) {      throw new Exception('Invalid postcode');    } else {      return substr($newPostcode, 0, -3) .' '. substr($newPostcode, -3);    }  }}
    

     

     

    Now you are prevented from updating an instance to contain an incorrectly formatted postal code.

     

    You could also do things like set a country code from an associative array when a country gets set, or create a white-list of allowed values and throw an exception if the value is not contained.

     

    They are also used for creating storage objects, like so:

     

    class Storage { // this would be better as a trait again
      protected $_data = array();
     
      public function __get($key) {
        if ( !isset($this->_data[$key]) ) return false;
        return $this->_data[$key];
      }
      public function __set($key, $value) {
        $this->_data[$key] = $value;
      }
    }
    

     

    It is actually better to write the first example in a style similar to this, it gives us control over which properties can be accessed.

     

    abstract class FilterableProperties { // this would be better as a trait   protected $_data = array();   public function __set($key, $value) {    if ( !isset($this->_data[$key]) )      return null;    $beforeFilter = "_before_set_{$key}";    if ( method_exists($this, $beforeFilter) ) {      $this->_data[$key] = call_user_func(array($this, $beforeFilter), $value);    } else {      $this->_data[$key] = $value;    }  }  public function __get($name) {    return isset($this->_data[$key]) ? $this->_data[$key] : null;  }}class Address extends FilterableProperties {  protected $_data = array('property_name_or_number', 'street', 'town', 'city', 'county', 'postcode', 'country');  // now these properties can not be accessed and are actually protected  protected $_country_code  = null;  protected $_country_codes = array(    'United Kingdom' => 'UK',    'United States'  => 'USA',    'France'         => 'FR',    'Germany'        => 'GER'    // ...  );   protected function _before_set_postcode($newPostcode) {    $newPostcode = strtoupper(preg_replace('/\s+/', '', $newPostcode));    if ( !preg_match("/^[A-Z]{1,2}[0-9]{2,3}[A-Z]{2}$/", $newPostcode) &&      !preg_match("/^[A-Z]{1,2}[0-9]{1}[A-Z]{1}[0-9]{1}[A-Z]{2}$/", $newPostcode) )       throw new Exception('Invalid postcode');    return substr($newPostcode, 0, -3) .' '. substr($newPostcode, -3);  }  protected function _before_set_country($newCountry) {    if ( !in_array($newCountry, array_keys($this->_country_codes)) )      throw new Exception('Invalid country');    $this->_country_code = $this->_country_codes[$newCountry];    return $newCountry;  }}
     
    Hope that helps.
  9. Try casting the id to integer and the title to string, like so:

     

    $courses     = array();$course_keys = array();foreach($result as $course) {   $course_key = array_search($course->id, $course_keys);   if ( $course_key === false ) {      $courses[] = array(         'id'         => (int)$course->id,         'name'       => $course->name,         'text_books' => array((string)$course->text_book)      );      $course_keys[] = $course->id;   } else {      $courses[$course_key]['text_books'][] = (string)$course->text_book;   }}
    

     

    //EDIT, I've had the same problem before, I can't remember exactly how I got around it but if the casting doesn't work, try casting to array and getting element 0, i.e.

     

    $id = (array)$course->id;
    $id = $id[0];
    

  10. That should have been:

     

    $courses     = array();$course_keys = array();foreach($result as $course) {   $course_key = array_search($course->id, $course_keys);   if ( $course_key === false ) {      $courses[] = array(         'id'         => $course->id,         'name'       => $course->name,         'text_books' => array($course->text_book)      );      $course_keys[] = $course->id;   } else {      $courses[$course_key]['text_books'][] = $course->text_book;   }}

     
    Missed the array brackets after $courses.
     
     
    This basically checks if the course ID exists, if it does it returns the index (key) for that ID and inserts a new text book, otherwise it adds a new array into the courses multi-dimensional array (containing the course id, name and first text book) and inserts the course ID as a new entry into the course_keys array, this way the course id's in both arrays have the same key, so array search on the course keys array will also return the key for the courses array.
  11. You would be better using a multi-dimensional array, as requinix said, it would be easier if we could see your source XML, but you will probably need something along the lines of:

     

    $courses     = array();
    $course_keys = array();
    foreach($result as $course) {
       $course_key = array_search($course->id, $course_keys);
       if ( $course_key === false ) {
          $courses = array(
             'id'         => $course->id,
             'name'       => $course->name,
             'text_books' => array($course->text_book)
          );
          $course_keys[] = $course->id;
       } else {
          $courses[$course_key]['text_books'][] = $course->text_book;
       }
    }
    

  12. What happens if you put session_start() before your session_save_path()?

     

    session start is supposed to be the very first line in your file, but not sure if that counts in regards to another session setting.

     

    If that's not the problem then you need to look at your login handler, specifically, where you're setting the username session variable. Make sure that's working.

     

    Denno

     

    From session_save_path

     

    Session data path. If specified, the path to which data is saved will be changed. session_save_path() needs to be called before session_start() for that purpose.

     

    Also, session_start isn't "supposed" to be the very first line in your file, although that is common practice, it just needs to be called before any output has been sent to the client.

     

    @OP

     

    Is there any reason you're modifying the session save path? Is the directory you're setting it to readable and writable by the user your server is running under? (probably www-data)

  13. Javascript can be disabled, so I wouldn't recommend relying on it for something like this, how important is it that each person only gets 10 hits every 30 minutes? No matter what you do you're always going to get the odd few.

     

    You could use a combination of IP address and user agent (you don't need javascript for this), i.e.

     

    access_logs

    id ip_address user_agent created_at

     

    Then do something like:

     

    <?phpfunction clientIP() {  if ( filter_var($_SERVER['HTTP_CLIENT_IP'], FILTER_VALIDATE_IP) ) {    return $_SERVER['HTTP_CLIENT_IP'];  } elseif ( filter_var($_SERVER['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP) ) {    return $_SERVER['HTTP_X_FORWARDED_FOR'];  }  return $_SERVER['REMOTE_ADDR'];} // if user is logged in don't do this, they can use more than 10 timestry {  // create mysql connection  $dbh  = new PDO('mysql:dbname=test;host=127.0.0.1', 'root', '');  $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);  // prepare statement  $stmt = $dbh->prepare('SELECT COUNT(*) FROM access_logs WHERE ip_address = ? AND user_agent = ? AND created_at >= (NOW() - INTERVAL 30 MINUTE) LIMIT 10');  $stmt->execute(array(clientIP(), $_SERVER['HTTP_USER_AGENT']));  $row  = $stmt->fetch(PDO::FETCH_NUM);  // now we have times used in last 30 minutes  $times_used = (int)$row[0];  if ( $times_used == 10 ) {    $errors[] = 'You can only use this 10 times every 30 minutes, to remove this restriction <a href="/register.php">Register now!</a>';  } else {    // allow it    // insert new record for IP / user agent  }} catch ( PDOException $e ) {  // handle error}

     
    Not tested.
  14. There will almost definitely be something open-source to do this, have you tried sourceforge? or googling "PHP file management" (assuming it has to be in PHP), if I were implementing it myself, I would probably be using the SPL's recursivedirectoryiterator, PHP also exposes the underlying OS commands for file/directory deletion/creation/modification, see:

     

    chmod

    mkdir

    fopen

    fread

    fwrite

    file_put_contents

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.