dbscript
[ class tree: dbscript ] [ index: dbscript ] [ all elements ]

Source for file mysql.php

Documentation is available at mysql.php

  1. <?php
  2.  
  3.   /** 
  4.    * dbscript for PHP 4 & 5 - restful crud framework
  5.    * @version 0.1.2 -- 19-Feb-2007
  6.    * @author Brian Hendrickson <brian@dbscript.net>
  7.    * @link http://dbscript.net/
  8.    * @copyright Copyright 2007 Brian Hendrickson
  9.    * @license http://www.opensource.org/licenses/mit-license.php MIT License
  10.    * @package dbscript
  11.    */  
  12.  
  13.   /**
  14.    * MySQL
  15.    * 
  16.    * adapter for the MySQL database system
  17.    * 
  18.    * Usage:
  19.    * <code>
  20.    * $db = new MySQL ( 'hostname', 'database_name', 'username', 'password' );
  21.    * </code>
  22.    * 
  23.    * More info...
  24.    * {@link http://dbscript.net/mysql}
  25.    * 
  26.    * @package dbscript
  27.    * @author Brian Hendrickson <brian@dbscript.net>
  28.    * @access public
  29.    * @version 0.1.2
  30.    * @todo support array datatypes
  31.    */
  32.  
  33. class MySQL extends Database {
  34.   var $host;
  35.   var $user;
  36.   var $pass;
  37.   var $opt1;
  38.   var $opt2;
  39.   var $dbname;
  40.   function MySQL({
  41.     $this->db_open = false;
  42.     $this->models = array();
  43.     $this->recordsets = array();
  44.     $this->max_blob_length = 6144000;  // default max blob file size is 6MB
  45.     $this->max_string_length = 1024000;  // default max string length is 1MB
  46.     $this->datatype_map = array(
  47.       
  48.       'float' => 'float'// precise to 23 digits
  49.       'double' => 'float'// 24-53 digits
  50.       'decimal' => 'float'// double stored as string
  51.  
  52.       'int' => 'int',
  53.       'tinyint' => 'int',
  54.       'smallint' => 'int',
  55.       'mediumint' => 'int',
  56.       'bigint' => 'int',
  57.       
  58.       'char' => 'char',
  59.       'varchar' => 'char',
  60.       'tinytext' => 'char',
  61.       
  62.       'text' => 'text',
  63.       'mediumtext' => 'text',
  64.       'longtext' => 'text',
  65.       'bigtext' => 'text',
  66.       
  67.       'time' => 'time',
  68.       'timestamp' => 'time',
  69.       'datetime' => 'time',
  70.       
  71.       'date' => 'date',
  72.       
  73.       'boolean' => 'bool',
  74.       'bool' => 'bool',
  75.       
  76.       'blob' => 'blob',
  77.       'mediumblob' => 'blob',
  78.       'longblob' => 'blob'
  79.       
  80.     );
  81.     $args func_get_args();
  82.     $argnames array('host','dbname','user','pass','opt1','opt2');    for ($i 0$i count($args)$i++{
  83.       $this->$argnames[$i$args[$i];
  84.     }
  85.     $this->true_values = array('t','true','1',true);
  86.     $this->alias_array array();
  87.     $this->connect();
  88.   }
  89.   function connect(/* function to re/establish the DB connection */
  90.     $this->conn = mysql_connect($this->host,$this->user,$this->pass,$this->opt1,$this->opt2);
  91.     if (!$this->conn{
  92.        $this->db_open = false;
  93.        trigger_error("error in connect function of class MySQL in mysql.php ".@mysql_error($this->conn)E_USER_ERROR );
  94.     else {
  95.       $this->db_open = mysql_select_db($this->dbname);
  96.       if (!$this->db_open)
  97.         trigger_error(@mysql_error($this->conn)E_USER_ERROR );
  98.     }
  99.     return $this->db_open;
  100.   }
  101.   function escape_string$string /* watch for bad characters in each SQL query */
  102.     if (!(strlen($string0)) return $string}
  103.     $result @mysql_escape_string($string);
  104.     if (!$result && !(is_numeric($string))) {
  105.       trigger_error("error in escape_string in mysql.php ".@mysql_error($this->conn)E_USER_ERROR );
  106.     else {
  107.       return $result;
  108.     }
  109.   }
  110.   function get_result$sql$returnfalse NULL /* run an SQL query */
  111.     $request =request_object();
  112.     if (isset($request->params)) {
  113.       $request->set_param'currentquery'$sql );
  114.       trigger_before'get_result'$request$this );
  115.     }
  116.     $result @mysql_query$sql$this->conn );
  117.     if (!$result && $returnfalse == NULL{
  118.       trigger_error("error in get_result in mysql.php ".@mysql_error($this->conn)." ".$sqlE_USER_ERROR );
  119.       exit;
  120.     elseif (!$result && $returnfalse{
  121.       return false;
  122.     else {
  123.       return $result;
  124.     }
  125.   }
  126.   function next_primary_key($table,$pkfield,$sequence_name=NULL{
  127.     return "";
  128.   }
  129.   function last_insert_id&$result$pk$table /* returns the id of the most recently modified record */
  130.     $res @mysql_insert_id($this->conn);
  131.     if (!$res{
  132.       trigger_error("unable to determine last_insert_id in mysql.php ".@mysql_error($this->conn)E_USER_ERROR );
  133.     else {
  134.       return $res;
  135.     }
  136.   }
  137.   function result_value&$result$resultindex$field /* get a single value from a result set */
  138.     $res mysql_result$result$resultindex$field );
  139.     if (!$res && $res != 0{
  140.       trigger_error("error in result_value in mysql.php".@mysql_error($this->conn)E_USER_ERROR );
  141.     else {
  142.       return $res;
  143.     }
  144.   }
  145.   function close({
  146.     $args func_get_args();
  147.     mysql_close$this->conn );
  148.     if isset$args[0) ) {
  149.       if strlen($args[0]{
  150.         header"Location:" $args[0);
  151.         exit;
  152.       }
  153.     }
  154.   }
  155.   function &get_table($table{
  156.     if isset$this->models[$table) )
  157.       return $this->models[$table];
  158.     $data_model model_path(classify($table'.php';
  159.     if (file_exists($data_model))
  160.       require_once $data_model;
  161.     $this->models[$tablenew MySQLTable$table$this );
  162.     return $this->models[$table];
  163.   }
  164.   function &model($model{
  165.     return $this->get_table(tableize($model));
  166.   }
  167.   function fetch_array(&$result,$row=NULL{
  168.     if (is_numeric($row)) {
  169.       $this->seek_row$result$row );
  170.     }
  171.     return mysql_fetch_array$resultMYSQL_ASSOC );
  172.   }
  173.   function fetch_row(&$result,$row=NULL{
  174.     if (is_numeric($row)) {
  175.       $this->seek_row$result$row );
  176.     }
  177.     return mysql_fetch_row$result );
  178.   }
  179.   function seek_row(&$result,$row{
  180.     return mysql_data_seek$result$row );
  181.   }
  182.   function query_limit($limit,$offset{
  183.     return " LIMIT " $offset .  "," $limit;
  184.   }
  185.   function blob_value&$rec$field&$value {
  186.     $ret array();
  187.     $ret['t'$rec->table;
  188.     $ret['f'$field;
  189.     $ret['k'$rec->primary_key;
  190.     $ret['i'$rec->attributes[$rec->primary_key];
  191.     return $ret;
  192.   }
  193.   function sql_insert_for&$rec {
  194.     $sql "INSERT INTO " $rec->table " (";
  195.     $comma '';
  196.     $fields '';
  197.     $values '';
  198.     foreach (array_unique($rec->modified_fieldsAS $modified_field{
  199.       $datatype $this->get_mapped_datatype($this->models[$rec->table]->field_array[$modified_field]);
  200.       $this->pre_insert$rec$modified_field$datatype );
  201.       if !$datatype == 'blob' &&  !(strlen$rec->attributes[$modified_field) ) ) ) {
  202.         $fields .= $comma $modified_field;
  203.         $values .= $comma $this->quoted_insert_value$rec$modified_field );;
  204.         $comma ',';
  205.       }
  206.     }
  207.     $sql .= $fields ") VALUES (" $values ")";
  208.     return $sql;
  209.   }
  210.   function sql_update_for&$rec {
  211.     $sql "UPDATE ";
  212.     $sql .= $rec->table ' SET ';
  213.     $comma '';
  214.     foreach (array_unique($rec->modified_fieldsAS $modified_field{
  215.       $datatype $this->get_mapped_datatype($this->models[$rec->table]->field_array[$modified_field]);
  216.       $this->pre_update$rec$modified_field$datatype );
  217.       if !$datatype == 'blob' &&  !(strlen$rec->attributes[$modified_field) ) ) ) {
  218.         $sql .= $comma $this->quoted_update_value$rec$modified_field );
  219.         $comma ',';
  220.       }
  221.     }
  222.     $sql .= " WHERE " $rec->primary_key "='" $rec->attributes[$rec->primary_key"'";
  223.     return $sql;
  224.   }
  225.   function sql_select_for&$rec$id {
  226.     return "SELECT ".$rec->selecttext." FROM ".$rec->table." WHERE ".$rec->primary_key." = '".$id."'";
  227.   }
  228.   function sql_delete_for&$rec {
  229.     $sql 'DELETE FROM ' $rec->table ' WHERE ' $rec->primary_key ' = ' $rec->$pkfield;
  230.     return $sql;
  231.   }
  232.   function select_distinct$field$table$orderby {
  233.     return "SELECT DISTINCT $field$this->models[$table]->primary_key " FROM $table ORDER BY $orderby DESC";
  234.   }
  235.   function quoted_update_value&$rec$modified_field {
  236.     return $modified_field "='" $this->escape_string($rec->attributes[$modified_field]"'";
  237.   }
  238.   function quoted_insert_value&$rec$modified_field {
  239.     return "'" $this->escape_string($rec->attributes[$modified_field]"'";
  240.   }
  241.   function pre_insert&$rec$modified_field$datatype {
  242.     if (isset($this->models[$rec->table]->field_attrs[$modified_field]['required'])) {
  243.       if (!(strlen$rec->attributes[$modified_field0))
  244.         trigger_error"$modified_field is a required field"E_USER_ERROR );
  245.     }
  246.     if (isset($this->models[$rec->table]->field_attrs[$modified_field]['unique'])) {
  247.       $result $this->get_result("select ".$modified_field." from ".$rec->table." where ".$modified_field." = '".$rec->attributes[$modified_field]."'");
  248.       if ($this->num_rows($result0)
  249.         trigger_error"$modified_field must be unique!"E_USER_ERROR );
  250.     }
  251.     if ($datatype == 'time' && !(strlen($rec->attributes[$modified_field]0))
  252.       $rec->attributes[$modified_fielddate("Y-m-d H:i:s",strtotime("now"));
  253.     if ($datatype == 'blob')
  254.       $rec->attributes[$modified_field=$this->large_object_create$rec->table$rec->attributes[$modified_field);
  255.     if ($datatype == 'bool'{
  256.       if in_array$rec->attributes[$modified_field]$this->true_valuestrue ) ) {
  257.         $rec->attributes[$modified_field"1";
  258.       else {
  259.         $rec->attributes[$modified_field"false";
  260.       }
  261.     }
  262.   }
  263.   function pre_update&$rec$modified_field$datatype {
  264.     if (isset($this->models[$rec->table]->field_attrs[$modified_field]['required'])) {
  265.       if (!(strlen$rec->attributes[$modified_field0))
  266.         trigger_error"$modified_field is a required field"E_USER_ERROR );
  267.     }
  268.     if (isset($this->models[$rec->table]->field_attrs[$modified_field]['unique'])) {
  269.       $result $this->get_result("select ".$modified_field." from ".$rec->table." where ".$modified_field." = '".$rec->attributes[$modified_field]."' and ".$rec->primary_key." != '".$rec->attributes[$rec->primary_key]."'");
  270.       if ($this->num_rows($result0)
  271.         trigger_error"$modified_field must be unique!"E_USER_ERROR );
  272.     }
  273.     if ($datatype == 'bool'{
  274.       if in_array$rec->attributes[$modified_field]$this->true_valuestrue ) ) {
  275.         $rec->attributes[$modified_field"1";
  276.       else {
  277.         $rec->attributes[$modified_field"false";
  278.       }
  279.     }
  280.     if ( ($datatype == 'blob'&& (strlen$rec->attributes[$modified_field0) ) {
  281.       if strlen$rec->attributes[$modified_field{
  282.         $data =$this->large_object_create($rec->table,$rec->attributes[$modified_field]);
  283.         $rec->attributes[$modified_field=$data;
  284.       }
  285.     }
  286.   }
  287.   function post_insert&$rec&$result {
  288.     if (!$resulttrigger_error("Sorry, the record could not be saved due to a database error."E_USER_ERROR )}
  289.     $pkvalue $this->last_insert_id($result,NULL,NULL);
  290.     $pkfield $rec->primary_key;
  291.     $rec->attributes[$pkfield$pkvalue;
  292.     $rec->$pkfield =$rec->attributes[$pkfield];
  293.   }
  294.   function num_rows(&$result{
  295.     return @mysql_num_rows($result);
  296.   }
  297.   function num_fields(&$result{
  298.     return @mysql_num_fields($result);
  299.   }
  300.   function field_name(&$result$index{
  301.     return @mysql_field_name($result$index);
  302.   }
  303.   function large_object_create($table,$file{
  304.     $return false;
  305.     if (!(file_exists($file))) trigger_error("temporary file could not be found"E_USER_ERROR )}
  306.     $handle fopen($file,"r");
  307.     if (!$handletrigger_error("Error creating large object in fopen"E_USER_ERROR )}
  308.     $buffer fread($handle,filesize($file));
  309.     if (!$buffertrigger_error("Error creating large object in fread"E_USER_ERROR )}
  310.     $result fclose($handle);
  311.     if (!$resulttrigger_error("Error creating large object in fclose"E_USER_ERROR )}
  312.     else {
  313.       $return =$buffer;
  314.     }
  315.     return $return;
  316.   }
  317.   function large_object_fetch($table,$blobcol,$pkfield,$pkvalue$return=false{
  318.     // t f k i
  319.     $sql "SELECT $blobcol FROM $table WHERE $pkfield = '$pkvalue'";
  320.     $result $this->get_result($sql);
  321.     if ($return)
  322.       $return $this->result_value($result,0,$blobcol);
  323.     else
  324.       print $this->result_value($result,0,$blobcol);
  325.     return $return;
  326.   }
  327.   function large_object_delete($oid{
  328.     return true;
  329.   }
  330.   function add_table$table$field_array {
  331.     if (!(count($field_array)>0)) trigger_error"Error creating table, no fields are defined. Use \$model->auto_field and \$model->text_field etc."E_USER_ERROR );
  332.     $sql "CREATE TABLE $table (";
  333.     $comma "";
  334.     foreach $field_array as $field => $data_type {
  335.       $sql .= "$comma $field $data_type";
  336.       $comma ",";
  337.     }
  338.     $sql .= ")";
  339.     $result $this->get_result($sql);
  340.   }
  341.   function add_field$table$field$data_type {
  342.     $sql "ALTER TABLE $table ADD COLUMN $field $data_type";
  343.     $result $this->get_result($sql);
  344.   }
  345.   function has_table($t{
  346.     return in_array$t$this->get_tables()true );
  347.   }
  348.   function get_tables({
  349.     $tables array();
  350.     $sql =  "SHOW tables FROM ".$this->dbname;
  351.     $result $this->get_result($sql);
  352.     while ($arr $this->fetch_array($result)) {
  353.       foreach($arr as $key=>$value{
  354.         if (strtolower(str_replace'_'''$value)) != strtolower(classify($value)) )
  355.           $tables[$value;
  356.       }
  357.     }
  358.     return $tables;
  359.   }
  360.   function get_fields($table{
  361.     $datatypes array();
  362.     $sql "SHOW columns FROM $table";
  363.     $result $this->get_result($sqltrue);
  364.     if (!$resultreturn $datatypes;
  365.     while ($arr $this->fetch_array($result)) {
  366.       foreach($arr as $key=>$value{
  367.         if ($key == "Field"{
  368.           $field $value;
  369.         elseif ($key == "Type"{
  370.           $type $value;
  371.         elseif ($key == "Key"{
  372.           if ($value == "PRI"{
  373.             $datatypes[$table."_primary_key"$field// yuck
  374.           }
  375.         }
  376.       }
  377.       $datatypes[$field$type;
  378.     }
  379.     return $datatypes;
  380.   }
  381.   
  382. }
  383.  
  384.  
  385.   /**
  386.    * MySQL Table
  387.    * 
  388.    * data model for a single MySQL table
  389.    * 
  390.    * Usage:
  391.    * <code>
  392.    *   $people =& $db->model( 'people' );
  393.    * </code>
  394.    * 
  395.    * More info...
  396.    * {@link http://dbscript.net/mysqltable}
  397.    * 
  398.    * @package dbscript
  399.    * @author Brian Hendrickson <brian@dbscript.net>
  400.    * @access public
  401.    * @param string $table 
  402.    * @param object $db 
  403.    * @version 0.1.2
  404.    */
  405.  
  406. class MySQLTable extends Model {
  407.   
  408.   function MySQLTable$table&$db {
  409.     
  410.     $this->table = $table;
  411.     $db->models[$table=$this;
  412.     $this->params = array('resource'=>$table);
  413.     $this->access_list = array();
  414.     $this->relations = array();
  415.     $this->allowed_methods = array'get''post''put''delete' );
  416.     $this->field_array = $db->get_fields$this->table );
  417.     if count$this->field_array )
  418.       $this->exists = true;
  419.     else
  420.       $this->exists = false;
  421.     if (isset($this->field_array[$this->table."_primary_key"])) {
  422.       $this->set_primary_key$this->field_array[$this->table."_primary_key");
  423.       $this->field_array = drop_array_element($this->field_array,$this->table."_primary_key");
  424.     }
  425.     if class_existsclassify$table )))
  426.       $this->registerclassify$table ) );
  427.   }
  428.   
  429.   function auto_field$field {
  430.     $this->set_field$field"int(11) not null auto_increment primary key" );
  431.     $this->set_primary_key$field );
  432.   }
  433.  
  434.   function enum_field$field$values {
  435.     $this->set_field$field"enum"$values );
  436.   }
  437.   
  438.   function float_field$field {
  439.     $this->set_field$field"double" );
  440.   }
  441.   
  442.   function bool_field$field {
  443.     $this->set_field$field"bool" );
  444.   }
  445.   
  446.   function char_field$field {
  447.     $args func_get_args();
  448.     if (count($args)>1{
  449.       $len $args[1];
  450.     else {
  451.       $len "255";
  452.     }
  453.     $this->set_field$field"varchar($len));
  454.   }
  455.   
  456.   function date_field$field {
  457.     $this->set_field$field"date" );
  458.   }
  459.   
  460.   function file_field$field {
  461.     $this->set_field$field"longblob" );
  462.   }
  463.   
  464.   function int_field$field {
  465.     $this->set_field$field"int(11)" );
  466.   }
  467.   
  468.   function text_field$field {
  469.     $this->set_field$field"text" );
  470.   }
  471.   
  472.   function time_field$field {
  473.     $this->set_field$field"datetime" );
  474.   }
  475.   
  476.   function get_query$id=NULL$find_by=NULL {
  477.     $db =db_object();
  478.     trigger_before'get_query'$this$db );
  479.     $pkfield $this->primary_key;
  480.     if ($find_by == NULL)
  481.       $find_by $this->primary_key;
  482.     $relfields array();
  483.     $relfields $this->relations;
  484.     $table $this->table;
  485.     $fieldstring '';
  486.     $sql "SELECT " "\n";
  487.     if (!array_key_exists($pkfield,$this->field_array))
  488.       $sql .= "$table.$pkfield as \"$table.$pkfield\", "\n";
  489.     foreach ($this->field_array as $fieldname=>$datatypename{
  490.       if (!(!(strpos($fieldname,"."=== false)))
  491.         $fieldname $table "." $fieldname;
  492.       $fieldstring .= "$fieldname as \"$fieldname\", "\n";
  493.     }
  494.     $leftsql "";
  495.     $first true;
  496.     if (count($relfields0{
  497.       foreach ($relfields as $key=>$val{
  498.         $spl split("\.",$val["fkey"]);
  499.         if (($val["type"!= 'child-many'&& isset($db->models[$spl[0]]))
  500.           $leftsql .= "(";
  501.       }
  502.       $skippedrel false;
  503.       foreach ($relfields as $key=>$val{
  504.         $spl split("\.",$val["fkey"]);
  505.         if (($val["type"== 'child-many'|| !(isset($db->models[$spl[0]]))) {
  506.           if ($first)
  507.             $skippedrel true;
  508.           continue;
  509.         }
  510.         foreach ($db->models[$spl[0]]->field_array as $fieldname=>$datatypename{
  511.           $fieldstring .= $spl[0].".".$fieldname." as \"".$spl[0].".".$fieldname."\", " "\n";
  512.         }
  513.         if ($first)
  514.           $leftsql .= $table;
  515.         $leftsql .= " left join " $spl[0" on ".$table.".".$val["col"]." = " $val["fkey"];
  516.         $leftsql .= ")";
  517.         $first false;
  518.       }
  519.     }
  520.     $fieldstring substr($fieldstring,0,-3" " "\n";
  521.     $sql .= $fieldstring;
  522.     $sql .= "FROM ";
  523.     
  524.     $sql .= $leftsql;
  525.     
  526.     if (!(strlen($leftsql1))
  527.       $sql .= $table;
  528.     
  529.     if ($id != NULL{
  530.       $sql .= " WHERE $table.$find_by = '$id";
  531.     }
  532.  
  533.     if (!(isset($this->orderby))) {
  534.       $this->orderby = $table "." $pkfield;
  535.     }
  536.  
  537.     if (!(isset($this->order))) {
  538.       $this->order = "DESC";
  539.     }
  540.     
  541.     if (!(isset($this->offset))) {
  542.       $this->offset = 0;
  543.     }
  544.  
  545.     if (!(isset($this->limit))) {
  546.       $this->limit = 20;
  547.     }
  548.  
  549.     $sql .= " ORDER BY " $this->orderby . " ";
  550.  
  551.     $sql .= $this->order . $db->query_limit($this->limit,$this->offset);
  552.     
  553.     if (class_exists(classify($table))) {
  554.       $this->custom_class = classify($table);
  555.     }
  556.  
  557.     trigger_after'get_query'$this$db );
  558.  
  559.     return $sql;
  560.   
  561.   }
  562.   
  563. }
  564.  
  565. ?>

Documentation generated on Mon, 19 Feb 2007 10:24:54 -0800 by phpDocumentor 1.3.1