An OOP version of a GPS NMEA Sentence. See the output of the example codes from under the below class definition.

<?php
/**
 * A class for generating and validating objects which represent GPS NMEA Sentences
 *
 * @author Jim Auldridge
 * @link http://www.codepedia.com/1/The+GPRMC+Sentence
 * @link http://www.codepedia.com/1/Calculating+and+Validating+NMEA+Checksums
 */
class GPS_NMEA_Sentence
{
  protected 
$Sentence;
  protected 
$Data;
  protected 
$Internal_Checksum;
  protected 
$Calculated_Checksum;

  protected 
$Valid_Command_Words = array('GPRMC');

  public 
$CommandWord 'GPRMC';
  public 
$SatelliteDerivedTime '';
  public 
$SatelliteFixStatus '';
  public 
$LatitudeDecimalDegrees '';
  public 
$LatitudeHemisphere '';
  public 
$LongitudeDecimalDegrees '';
  public 
$LongitudeHemisphere '';
  public 
$Speed '';
  public 
$Bearing '';
  public 
$UTCDate '';

  protected 
$Valid false;

  protected 
$in_error false;
  protected 
$error_str '';
  
/**
   * The constructor; If parapeter passed, implicitly calls ::setSentence()
   *
   * @access public
   * @param OPTIONAL STRING $GPS_NMEA_Sentence
   * @return void
   */
  
public function __construct($GPS_NMEA_Sentence null)
  {
    if(!
is_null($GPS_NMEA_Sentence))
    {
      
$this->setSentence($GPS_NMEA_Sentence);
    }
  }
  
/**
   * Set the ::Sentence property, implicitly calls ::parseSentence()
   *
   * @access public
   * @param STRING $GPS_NMEA_Sentence --The value to which ::Sentence should be set
   * @return OBJECT $this
   *
   */
  
public function setSentence($GPS_NMEA_Sentence)
  {
    if(
is_string($GPS_NMEA_Sentence) || empty($GPS_NMEA_Sentence))
      
$this->Sentence $GPS_NMEA_Sentence;
    else
      
$this->setError('Non string or empty value passed to '.__METHOD__);
    
$this->resetStatuses();
    
$this->parseSentence();
    return 
$this;
  }
  
/**
   * Set the Command Word for the Sentence
   *
   * @access public
   * @param STRING $value
   * return OBJECT $this
   */
  
public function setCommandWord($value)
  {
    
$this->CommandWord $value;
    return 
$this;
  }
  
/**
   * Set the Satellite Derived Time for the Sentence
   *
   * @access public
   * @param STRING $value
   * return OBJECT $this
   */
  
public function setSatelliteDerivedTime($value)
  {
    
$this->SatelliteDerivedTime $value;
    return 
$this;
  }
  
/**
   * Set the Satellite Fix Status for the Sentence
   *
   * @access public
   * @param STRING $value
   * return OBJECT $this
   */
  
public function setSatelliteFixStatus($value)
  {
    
$this->SatelliteFixStatus $value;
    return 
$this;
  }
  
/**
   * Set the Latitude Decimal Degrees for the Sentence
   *
   * @access public
   * @param STRING $value
   * return OBJECT $this
   */
  
public function setLatitudeDecimalDegrees($value)
  {
    
$this->LatitudeDecimalDegrees $value;
    return 
$this;
  }
  
/**
   * Set the Latitude Hemisphere for the Sentence
   *
   * @access public
   * @param STRING $value
   * return OBJECT $this
   */
  
public function setLatitudeHemisphere($value)
  {
    
$this->LatitudeHemisphere $value;
    return 
$this;
  }
  
/**
   * Set the Longitude Decimal Degrees for the Sentence
   *
   * @access public
   * @param STRING $value
   * return OBJECT $this
   */
  
public function setLongitudeDecimalDegrees($value)
  {
    
$this->LongitudeDecimalDegrees $value;
    return 
$this;
  }
  
/**
   * Set the Longitude Hemisphere for the Sentence
   *
   * @access public
   * @param STRING $value
   * return OBJECT $this
   */
  
public function setLongitudeHemisphere($value)
  {
    
$this->LongitudeHemisphere $value;
    return 
$this;
  }
  
/**
   * Set the Speed for the Sentence
   *
   * @access public
   * @param STRING $value
   * return OBJECT $this
   */
  
public function setSpeed($value)
  {
    
$this->Speed $value;
    return 
$this;
  }
  
/**
   * Set the Bearing for the Sentence
   *
   * @access public
   * @param STRING $value
   * return OBJECT $this
   */
  
public function setBearing($value)
  {
    
$this->Bearing $value;
    return 
$this;
  }
  
/**
   * Set the UTC Date for the Sentence
   *
   * @access public
   * @param STRING $value
   * return OBJECT $this
   */
  
public function setUTCDate($value)
  {
    
$this->UTCDate $value;
    return 
$this;
  }
  
/**
   * Return the ::Sentence property or null if in error or not valid
   *
   * @access public
   * @return MIXED
   */
  
public function getSentence()
  {
    return (!
$this->inError() && $this->isValid()) ? $this->Sentence null;
  }
  
/**
   * Return the Command Word property
   *
   * @access public
   * @return STRING
   */
  
public function getCommandWord()
  {
    return 
$this->CommandWord;
  }
  
/**
   * Return the Satellite Derived Time property
   *
   * @access public
   * @return STRING
   */
  
public function getSatelliteDerivedTime()
  {
    return 
$this->SatelliteDerivedTime;
  }
  
/**
   * Return the Satellite Fix Status property
   *
   * @access public
   * @return STRING
   */
  
public function getSatelliteFixStatus()
  {
    return 
$this->SatelliteFixStatus;
  }
  
/**
   * Return the Latitude Decimal Degrees property
   *
   * @access public
   * @return STRING
   */
  
public function getLatitudeDecimalDegrees()
  {
    return 
$this->LatitudeDecimalDegrees;
  }
  
/**
   * Return the Latitude Hemisphere property
   *
   * @access public
   * @return STRING
   */
  
public function getLatitudeHemisphere()
  {
    return 
$this->LatitudeHemisphere;
  }
  
/**
   * Return the Longitude Decimal Degrees property
   *
   * @access public
   * @return STRING
   */
  
public function getLongitudeDecimalDegrees()
  {
    return 
$this->LongitudeDecimalDegrees;
  }
  
/**
   * Return the Longitude Hemisphere property
   *
   * @access public
   * @return STRING
   */
  
public function getLongitudeHemisphere()
  {
    return 
$this->LongitudeHemisphere;
  }
  
/**
   * Return the Speed property
   *
   * @access public
   * @return STRING
   */
  
public function getSpeed()
  {
    return 
$this->Speed;
  }
  
/**
   * Return the Bearing property
   *
   * @access public
   * @return STRING
   */
  
public function getBearing()
  {
    return 
$this->Bearing;
  }
  
/**
   * Return the UTC Date property
   *
   * @access public
   * @return STRING
   */
  
public function getUTCDate()
  {
    return 
$this->UTCDate;
  }
  
/**
   * Extract and validate ::Sentence string
   *
   * @access public
   * @return OBJECT $this
   */
  
public function parseSentence()
  {
    if(!
$this->inError())
    {
      
$this->extractDataFromSentence();
      
$this->calculateChecksum();
      
$this->extractWordsFromData();
      
$this->extractInternalChecksum();
      
$this->Valid = !!($this->compareChecksums() && $this->validCommandWord());
    }
    return 
$this;
  }
  
/**
   * Compile properties into a GPS NMEA Sentence string, validate them and write to ::Sentence property.  If you have been modifying the object and are having trouble even though you believe everything should be correct, try calling ::resetStatuses();
   *
   * @access public
   * @return OBJECT $this
   */
  
public function writeSentence()
  {
    if(!
$this->inError())
    {
      
$this->Data "$this->CommandWord,$this->SatelliteDerivedTime,$this->SatelliteFixStatus,$this->LatitudeDecimalDegrees,$this->LatitudeHemisphere,$this->LongitudeDecimalDegrees,$this->LongitudeHemisphere,$this->Speed,$this->Bearing,$this->UTCDate";
      
$this->calculateChecksum();
      
$this->Internal_Checksum $this->Calculated_Checksum;
      
$this->Valid = !!($this->compareChecksums() && $this->validCommandWord());
      
$this->Sentence '$'.$this->Data.'*'.$this->Internal_Checksum;
    }
    return 
$this;
  }
  
/**
   * Return ::Valid property (which is set when data checks are run--used to know if your data is currently good or bad)
   *
   * @access public
   * @return BOOLEAN
   */
  
public function isValid()
  {
    return 
$this->Valid;
  }
  
/**
   * Return ::in_error property (which is true when an error has occured)
   *
   * @access public
   * @return BOOLEAN
   */
  
public function inError()
  {
    return 
$this->in_error;
  }
  
/**
   * Return ::error_str property when inError, or null if not
   *
   * @access public
   * @return MIXED
   */
  
public function getErrorStr()
  {
    return 
$this->in_error $this->error_str null;
  }
  
/**
   * Write ::error_str property and set ::in_error to true
   *
   * @access protected
   * @return void
   */
  
protected function setError($error_str)
  {
    
$this->in_error true;
    
$this->error_str $error_str;
  }
  
/**
   * Reset the status properties
   *
   * @access public
   * @return OBJECT $this
   */
  
public function resetStatuses()
  {
    
$this->Valid false;
    
$this->in_error false;
    
$this->error_str '';
  }
  
/**
   * Extract data portion of sentence and set it to ::Data property or setError on failure
   *
   * @access protected
   * @return void
   */
  
protected function extractDataFromSentence()
  {
    if(!
$this->inError())
    {
      
preg_match('/^\$([^*]+)\*/',$this->Sentence,$GPS_NMEA_Data);
      if(
is_array($GPS_NMEA_Data) && !empty($GPS_NMEA_Data[1]))
        
$this->Data $GPS_NMEA_Data[1];
      else
        
$this->setError(__METHOD__.' could not extract data from '.__CLASS__.'::Sentence');
    }
  }
  
/**
   * Extract GPS NMEA 'words' from ::Data
   *
   * @access protected
   * @return void
   */
  
protected function extractWordsFromData()
  {
    if(!
$this->inError())
    {
      
$words explode(',',$this->Data);
      
$wordnames = array('CommandWord','SatelliteDerivedTime','SatelliteFixStatus','LatitudeDecimalDegrees','LatitudeHemisphere','LongitudeDecimalDegrees','LongitudeHemisphere','Speed','Bearing','UTCDate');
      for(
$i=0;$i<count($wordnames);$i++)
        
$this->$wordnames[$i] = empty($words[$i]) ? '' $words[$i];
    }
  }
  
/**
   * Extract checksum portion of sentence and set it to ::Internal_Checksum property or setError on failure
   *
   * @access protected
   * @return void
   */
  
protected function extractInternalChecksum()
  {
    if(!
$this->inError())
    {
       
preg_match('/\*([^,]+)(,|$)/',$this->Sentence,$GPS_NMEA_Internal_Checksum);
      if(
is_array($GPS_NMEA_Internal_Checksum) && !empty($GPS_NMEA_Internal_Checksum[1]))
        
$this->Internal_Checksum $GPS_NMEA_Internal_Checksum[1];
      else
        
$this->setError(__METHOD__.' could not extract internal checksum from '.__CLASS__.'::Sentence');
    }
  }
  
/**
   * Calculate checksum of ::Data and set ::Calculated_Checksum property
   *
   * @access protected
   * @return void
   */
  
protected function calculateChecksum()
  {
    if(!
$this->inError())
    {
      
$Calculated_Checksum 0;
      for(
$i=0;$i<strlen($this->Data);$i++)
        
$Calculated_Checksum = ($Calculated_Checksum ord($this->Data{$i}));
      
$this->Calculated_Checksum dechex($Calculated_Checksum);
    }
  }
  
/**
   * Compare ::Internal_Checksum and ::Calculated_Checksum properties.  On good compare return true, on bad return false and setError
   *
   * @access protected
   * @return void
   */
  
protected function compareChecksums()
  {
    
$return_value false;
    if(!
$this->inError())
    {
      if(
$this->Internal_Checksum === $this->Calculated_Checksum)
        
$return_value true;
      else
        
$this->setError(__METHOD__.' found checksum mismatch.');
    }
    return 
$return_value;
  }
  
/**
   * Ensure ::CommandWord property matches what a GPS NMEA Sentence Command Word should be.  On good compare return true, on bad return false and setError
   *
   * @access protected
   * @return void
   */
  
protected function validCommandWord()
  {
    
$return_value false;
    if(!
$this->inError())
    {
      if(isset(
$this->CommandWord) && in_array($this->CommandWord,$this->Valid_Command_Words))
        
$return_value true;
      else
        
$this->setError(__METHOD__.' detected empty or incorrect CommandWord in '.__CLASS__.'::Sentence');
    }
    return 
$return_value;
  }
}


/* ***** EXAMPLES ********* */

//Two valid GPS NMEA Sentence Strings
$GPS_Serial_Output_1 '$GPRMC,030748.000,A,4553.0146,N,07352.1516,W,0.25,0.00,171107,,,A*76,AUTO';
$GPS_Serial_Output_2 '$GPRMC,155123.000,A,4043.8432,N,07359.7653,W,0.15,83.25,200407,,*28';
//And a third that is bad
$GPS_Serial_Output_3 '$GPRMC,155213.000,A,4053.8432,N,07359.7653,W,0.15,83.25,200407,,*49';

//
$oGPS_NMEA_Sentence = new GPS_NMEA_Sentence($GPS_Serial_Output_1);
echo 
"\n\n<pre>\n";var_dump($oGPS_NMEA_Sentence);echo "\n</pre>\n\n";

$oGPS_NMEA_Sentence->setSentence($GPS_Serial_Output_2);
echo 
"\n\n<pre>\n";var_dump($oGPS_NMEA_Sentence);echo "\n</pre>\n\n";

$oGPS_NMEA_Sentence->setSentence($GPS_Serial_Output_3);
echo 
"\n\n<pre>\n";var_dump($oGPS_NMEA_Sentence);echo "\n</pre>\n\n";



//Make a new empty GPS NMEA Sentence Object
$brandNew = new GPS_NMEA_Sentence();
//Set some properties on it and write the sentence property
$brandNew->setLatitudeHemisphere('E')->setLongitudeHemisphere('S')->writeSentence();
//dump out the object to see what it looks like
echo "\n\n<pre>\n";var_dump($brandNew);echo "\n</pre>\n\n";
//echo the sentence property
echo $brandNew->getSentence().'<br />';
//Make a new sentence with the otput string of the original to see if it validates
$testingBrandNew = new GPS_NMEA_Sentence($brandNew->getSentence());
//Dump it and see what we got
echo "\n\n<pre>\n";var_dump($testingBrandNew);echo "\n</pre>\n\n";
?>