Doctrine ODM / PHP / MongoDB - ReferenceOne ID changed or nulled when flushed - php

I'm trying to do a simple ReferenceOne with MongoDB/Doctrine, but I
get a really weird problem:
My ID:4e63611cbc347053a2000001
Create the Privilege Object
Check what's the Privilege->User Id
4e63611cbc347053a2000001
Persist it
Create the Event Object
Persist it
Check what's the Event->Privilege->User Id
4e63611cbc347053a2000001/OK/0
Flush it
Get my document id
4e6546d6bc34700605000012
Check what's the Event->Privilege->User Id
4e6546d6bc34700605000013/NOK/0
As you can see here, I create a Privilege Object where I reference a
User, I persist it => all ok. No I create a Event Object, I embed the
Privilege in it, check the id => all ok.
Now I flush it, and the user->id gets changed, I have no idea why this
happens.
I tried removing the cascade to see how it behaves and I just end up
with a null $id.
Any help would be welcome to understand what I'm doing wrong!
Here is the code I use:
echo "My ID:".$identity->getId()."<br />";
echo "Create the Privilege Object<br />";
$privilege = new \Entity\ODM\Event\Privilege();
$privilege->setUser($identity);
$privilege->setRole("admin");
echo "Check what's the Privilege->User Id<br />";
echo $privilege->getUser()->getId()."<br />";
echo "Persist it<br />";
$dm->persist($privilege);
echo "Create the Event Object<br />";
$event = new \Entity\ODM\Event();
$event->setName("My Event 222");
$event->setDate("25/08/2012");
$event->setUrl("myevent222");
$event->addPrivilege($privilege);
echo "Persist it<br />";
$dm->persist($event);
echo "Check what's the Event->Privilege->User Id<br />";
$privs = $event->getPrivileges();
$output = $identity->getId();
$i = 0;
foreach($privs as $priv)
{
if($priv->getUser()->getId() == '4e63611cbc347053a2000001')
$output .= "/OK/".$i."<br />";
else
$output .= "/NOK/".$i."<br />";
$i++;
echo $output;
}
echo "Flush it<br />";
$dm->flush();
echo "Get my document id<br/>";
$id = $event->getId();
echo $id."<br/>";
$privs = null;
$priv = null;
echo "Check what's the Event->Privilege->User Id<br />";
$privs = $event->getPrivileges();
$output = $identity->getId();
$i = 0;
foreach($privs as $priv)
{
if($priv->getUser()->getId() == '4e63611cbc347053a2000001')
$output .= "/OK/".$i."<br />";
else
$output .= "/NOK/".$i."<br />";
$i++;
echo $output;
}
Trimmed Entities:
class Event {
/**
* #Id
*/
protected $id;
/**
* #EmbedMany(targetDocument="\Entity\ODM\Event\Privilege")
*/
protected $privileges = array();
}
class Privilege {
/**
* #Id
*/
protected $id;
/**
* #ReferenceOne(targetDocument="\Entity\ODM\User",
cascade={"persist"})
*/
protected $user;
/**
* #param field_type $user
*/
public function setUser(\Entity\ODM\User $user) {
$this->user = $user;
}
}

For some reason the code here works perfectly fine under symfony2.
The problem is coming from the way I implemented doctrine in Zend (modified Bisna) - Closing this question.

Related

PHP How do I add an object to an array?

Expected Result:
I have several echo statements and I should be getting something like this:
index1
Question->addChoice1
Choice1
Choice2
Question->addChoice2
index2
Actual Results:
index1
Question->addChoice1
Choice1
Choice2
Its failing at:
$this.$choices[] = new Choice($obj);
I have no idea why its doing this, but its almost 3AM here so maybe I'm just too brain-dead to see it. please help.
index.php
$QUESTIONS = array();
for ($chapter=1; $chapter<=count($max_chapter); $chapter++) {
$question_qry = "SELECT * FROM $tbl_questions WHERE chapter=$chapter ORDER BY RAND() LIMIT $max_chapter[$chapter]";
$question_req = mysql_query($question_qry);
while ($question_obj = mysql_fetch_object($question_req)) {
$newQuestion = new Question($question_obj);
$choice_qry = "SELECT * FROM $tbl_choices WHERE question=$question_obj->reference ORDER BY choice ASC;";
$choice_req = mysql_query($choice_qry);
while ($choice_obj = mysql_fetch_object($choice_req)) {
echo "index1<br>";
$newQuestion->addChoice($choice_obj);
echo "index2<br>";
}
$QUESTIONS[] = $newQuestion;
echo '<pre>'; print_r($newQuestion); echo '</pre>';
}
}
shuffle($QUESTIONS);
echo '<pre>'; print_r($QUESTIONS); echo '</pre>';
question.php
class Question {
private $chapter;
private $topic;
private $reference;
private $question_name;
private $question_correct;
private $special;
private $pic;
private $choices = array();
function __construct($obj) {
$this->chapter = $obj->chapter;
$this->topic = $obj->topic;
$this->reference = $obj->reference;
$this->question_name = $obj->question_name;
$this->question_correct = $obj->question_correct;
$this->special = $obj->special;
$this->pic = $obj->pic;
}
public function addChoice($obj){
echo "Question->addChoice1<br>";
$this.$choices[] = new Choice($obj);
echo "Question->addChoice2<br>";
}
...
choice.php
class Choice {
private $chapter;
private $question;
private $choice;
private $choice_name;
private $choice_explanation;
function __construct($obj) {
echo "Choice1<br>";
$this->chapter = $obj->chapter;
$this->question = $obj->question;
$this->choice = $obj->choice;
$this->choice_name = $obj->choice_name;
$this->choice_explanation = $obj->choice_explanation;
echo "Choice2<br>";
}
...
Results
In PHP you have to use -> to call object properties, not .. . is concatenation.
So just replace $this.$choices[] with $this->choices[]
Typical typo for people who haven't worked much with PHP, but have experience in other languages.

Call a PHP file from another one multiple times (+ file reading)

What I am trying to do is read a value from blankVoteOB.txt, delete the value and repeat this process multiple times.
blankVote.php
global $cur_random;
for ($i=0; $i<2; $i++){
include 'readWriteRandomBV.php';
$random[$i]=$cur_random;
echo $random[$i];
echo ',';
}
readWriteRandomBV.php (reads current line from file blankVoteOB.txt and then deletes the line)
<?php
$dir = "blankVoteOB.txt";
$file = fopen($dir, "r") or exit("Unable to open file!");
global $lines;
global $line_no;
global $all_lines;
global $writelines;
global $cur_random;
$lines = "";
$line_no=0;
while(!feof($file)) {
$line_no++;
$line = fgets($file);
$all_lines .= $line."<br>";
if($line_no > 1)
$writelines .= $line;
else{
$curran = trim($line);
$cur_random = $curran;
}
}
fclose($file);
$fh = fopen($dir, 'w') or die("ERROR! Cannot open $file file!");
fwrite($fh, $writelines);
fclose($fh);
?>
Before running the PHPs, blankVoteOB.txt looks like this:
313328804459
159078851698
226414688415
380287830671
301815692106
2991355110
After being ran, it becomes:
159078851698
226414688415
380287830671
301815692106
2991355110
226414688415
380287830671
301815692106
2991355110
What I want is:
226414688415
380287830671
301815692106
2991355110
What am I doing wrong here?
I suggest you use an array to store the ballots, and then use array_shift to get the first item from the array.
I prefer using classes so I made a lottery class which allows you to "draw" the first item in the array.
If you run the code below and match the text output to the code you can see what it does.
See it live here: https://ideone.com/T8stdB
<?php
namespace Lottery;
class Lotto {
protected $lots;
public function __construct($lots = [])
{
$this->lots = $lots;
}
public function draw() {
return array_shift($this->lots);
}
}
namespace BallotGuy;
use Lottery\Lotto;
$lotto = new Lotto([313328804459,
159078851698,
226414688415,
380287830671,
301815692106,
2991355110,
]);
echo "Lotto status at this point\n";
echo "===========================================================\n";
var_dump($lotto);
echo "===========================================================\n";
echo "Drawn: " . $lotto->draw()."\n";
echo "\nLotto status at this point\n";
echo "===========================================================\n";
var_dump($lotto);
echo "===========================================================\n";
$saved = serialize($lotto);
//file_put_contents('ballots.txt',$saved);
/**
* setting to null to emulate script ending
*/
$lotto = null;
echo "Lotto set to null 'script' ends sort to speak here\n";
echo "\nLotto status at this point\n";
echo "===========================================================\n";
var_dump($lotto);
echo "===========================================================\n";
echo "Loading lotto from file\n";
//$saved = file_get_contents('ballots.txt');
$lotto = unserialize($saved);
echo "\nLotto status at this point\n";
echo "===========================================================\n";
var_dump($lotto);
echo "===========================================================\n";
echo "Drawn: ". $lotto->draw()."\n";
echo "\nLotto status at this point\n";
echo "===========================================================\n";
var_dump($lotto);
echo "===========================================================\n";
A version without the superfluos var_dumping
See it live https://ideone.com/YNKIM4
<?php
namespace Lottery;
class Lotto {
protected $lots;
public function __construct($lots = [])
{
$this->lots = $lots;
}
public function draw() {
return array_shift($this->lots);
}
}
namespace BallotGuy;
use Lottery\Lotto;
/**
* initialize lotto object
*/
$lotto = new Lotto([313328804459,
159078851698,
226414688415,
380287830671,
301815692106,
2991355110,
]);
echo "Drawn: " . $lotto->draw()."\n";
echo "Writing lotto to file. Ending script(j/k)\n";
$saved = serialize($lotto);
file_put_contents('ballots.txt',$saved);
/**
* setting to null to emulate script ending
*/
$lotto = null;
$saved = null;
echo "Loading lotto from file\n";
$saved = file_get_contents('ballots.txt');
$lotto = unserialize($saved);
echo "Drawn: ". $lotto->draw()."\n";
var_dump($lotto);

PHP array getting duplicate values

I am working on displaying information from my database. When I did print_r in the model/itemTile.php below to check on my array, $this->display, I noticed it had stored 2 copies of the data from my database. I checked my database, and there was definitely only one copy of the data.
I created a counter variable, $this->counter, to see what the surrounding while loop was doing. The original data had 6 non-duplicating rows. As you may see in the jpg attached below, the program increments and echo the counter to 6, then it does the "print_r($this->display)" line that is outside of the while loop, then for some strange reason goes back to the while loop, increment the counter, and print the $this->counter and $this->display again!
I can remove the duplicate, but I would much prefer to figure out why exactly there are two copies of the value to begin with.
Since this was originally a PHP class project that focus on MVC, everything is placed into controller, model, and view. I have included the relevant model and view code below:
Jpg:
PHP Site
model/itemTile.php
<?php
require_once('siteInfo.php');
class itemTile implements siteInfo {
private $term;
private $session;
private $result;
private $display = array();
private $counter = 0;
public function __construct($session) {
$this->session = $session;
}
public function getContent() {
$this->result = $this->session->db->prepare("SELECT productName, sciName, price FROM products");
$this->result->execute();
$this->result->bind_result($pN, $sN, $pz);
while ($this->result->fetch()) {
if (array_key_exists($pN, $this->display)) {
$this->display[$pN]["price"][] = $pz;
} else {
$this->display += [
$pN => [ //Product Name was used to id array because not all item have sciName,
"sciName" => [$sN], //and not all item have only 1 sku (1 item with different size = multiple pid).
"price" => [$pz]
]
];
}
$this->counter++;
echo $this->counter . "<br />";
}
$this->result->close();
print_r($this->display);
echo "<br />";
}
public function setContent() {
$this->getContent();
return $this->display;
}
}
?>
view/itemTile.php
<?php
class itemTileView {
private $model;
public function __construct(itemTile $model) {
$this->model = $model;
}
public function output(){
foreach ($this->model->setContent() as $item => $detail) {
$itemLink = preg_replace('/\s+/','_', $item);
echo "<div class= 'tileSpace'>";
echo "<a href='itemPages/" . $itemLink. "/home.php'>";
echo "<img alt='" . $item . "' src='itemPages/" . $itemLink . "/thumbnail.jpg' width='100' height='100'>";
echo "</a>";
echo "<p>" . $item . ": " . $detail["sciName"][0] . "</p>";
if (count($detail["price"]) > 1) {
echo "<p>" . min($detail["price"]). " - " . max($detail["price"]). "</p>";
} else {
echo "<p>" . $detail["price"][0] . "</p>";
}
echo "</div>";
}
}
}
?>
Can anyone spot where is the problem occurring?
use php function array_unique();
array_unique($arrayname);
using this you will get unique values from array.it avoids duplicate values

display multiple items with different statuses

I don’t know how to search the net for the answer and I’m not sure how to explain the problem, so I’m sorry if it’s not clear or if it’s been asked before.
Here’s the deal: I need to show some items which have different statuses (there’s “unanswered”, “in discussion” and “answered”). What’s happening now is that the unanswered questions are being shown, the correct text is being shown for the questions that are in discussion, but the text for the question that are answered is the same as the “in discussion”. When one of the questions is moved from “unanswered” to “in discussion”, the correct text is being show for the “answered” questions. When there are no “unanswered” questions, the text is correct for that item. But the other items are getting the same text as the “unanswered” and the questions that should be shown in “in discussion” aren’t visible.
Does someone know what I can do to fix this? I'll put some code below. Thanks!!!
overzicht.php
<?php
session_start();
if(!isset($_SESSION['views']))
{
header('Location: index.php');
}
else
{
$feedback = "";
try
{
include_once('classes/question.class.php');
$oQuestion = new Question();
$oQuestionsUnanswered = $oQuestion->getQuestionsUnanswered();
$oQuestionsInDiscussion = $oQuestion->getQuestionsInDiscussion();
$oQuestionsAnswered = $oQuestion->getQuestionsAnswered();
}
catch(Exception $e)
{
$feedback = $e->getMessage();
}
}
?>
To show the different items (this is repeated twice for the other 2 statuses, with other variables e.g $oQuestionsAnswered):
<h3>Vragen onbeantwoord:</h3>
<div id="questionUnanswered">
<?php
if(isset($oQuestionsUnanswered))
{
$unanswered_details = "";
while($arr_unanswered = mysqli_fetch_array($oQuestionsUnanswered))
{
$unanswered_details .= "<div class='head'>";
$unanswered_details .= "<div class='titel'>";
$unanswered_details .= "<a href='full_topic.php?id=".$arr_unanswered['bericht_id']."'>".$arr_unanswered['bericht_titel']."</a></div>";
$unanswered_details .= "<div class='datum'>" . $arr_unanswered['bericht_datum'] . "</div></div>";
}
echo $unanswered_details;
}
else
{
echo $feedback;
}
?>
</div>
question.class.php (this is also repeated for the other 2)
public function getQuestionsUnanswered()
{
include('connection.class.php');
$sql = "SELECT *
FROM tblbericht
WHERE fk_status_id = 3;";
$result = $conn->query($sql);
if($result->num_rows!=0)
{
return $result;
}
else
{
throw new Exception("Er zijn momenteel nog geen onbeantwoorde vragen");
}
mysqli_close($conn);
}
IMO you make a big mistake, you split the query moment from the fetch moment, so you can create an array of question objects, than you use it inside the page.
Here's a draft of your code adapted:
public function getQuestionsUnanswered()
{
include('connection.class.php');
$sql = "SELECT *
FROM tblbericht
WHERE fk_status_id = 3;";
$result = $conn->query($sql);
$_rv =array()
if($result->num_rows!=0)
{
while($arr = mysqli_fetch_array($result))
{
$_rv[] = new QuestionBean($arr);
}
}
else
{
throw new Exception("Er zijn momenteel nog geen onbeantwoorde vragen");
}
mysqli_close($conn);
return $_rv
}
Then
<h3>Vragen onbeantwoord:</h3>
<div id="questionUnanswered">
<?php
if(count($oQuestionsUnanswered))
{
$unanswered_details = "";
foreach( $oQuestionsUnanswered as $bean)
{
$unanswered_details .= "<div class='head'>";
$unanswered_details .= "<div class='titel'>";
$unanswered_details .= "<a href='full_topic.php?id=".$bean->bericht_id."'>".$bean->bericht_titel."</a></div>";
$unanswered_details .= "<div class='datum'>" . $bean->bericht_datum . "</div></div>";
}
echo $unanswered_details;
}
else
{
echo $feedback;
}
?>
</div>
Of course you can optimize it using 1 class for all kind of question and 1 function using the paramiter to select wich kind of question you need.
The type of question will be a parameter of QuestionBean.
QuestionBean is a Bean :)
As bean I mean a "simple" data object where each attributes has a getter and setter OR is public.
I use the __constructor as initializer with a function called populate:
class simpleBean{
public $id;
public function __construct($params){
// some logic as need
}
// simple populate
public function populate($params){
$valid = get_class_vars ( self );
foreach($params as $k => $v){
if(!isset($valid[$k]){
// if this key has no attrib matchig I skip it
continue;
}
$this->$k = $v;
}
}
}
class QuestionBean extend simpleBean{
public $attr1;
public function __construct($params){
// may be I've some common logic in parent
parent::__construc($params);
//
$this->populate($params);
}
}
Now after the
while($arr = mysqli_fetch_array($result))
{
$_rv[] = new QuestionBean($arr);
}
you will have an array ($rv) of beans, each bean is a single result row of your query, but it's an object, that's much better than a stupid array.

PHP entity class generator

I am creating entity (of entity-view-controller)(in other words, model of MVC) classes which theoreticlly match the databse table I have. Is there a tool which reads mysql table and creates a model class code? (NOT on execution, a code output is required)
I expect an output like
class{
public $columnname1;
public $columnname2;
public $columnname3;
public $columnname4;
public $columnname5;
public $columnname6;
function __construct(&$columnname1, &$columnname2){...}
function insert(&$columnname1, &$columnname2){}
function delete(&$columnname1){}
...
}
A tool which would also create insert,update and delete by id functions would help me a lot.
The tool may be free or paid.
PDO can fetch results into an object.
Design a class which matches your database/query structure, and use PDO::FETCH_INTO to fetch the result set into an already instantiated object. Misread the question, my bad.
To generate the class itself from the database structure, there are several projects (I haven't tested, but this came up on a very simple search).
db2php
PHP MySQL class generator
The following code is what I've used for a long time to create PHP models for MySQL and DB2 tables. I've got stubs in place for MSSQL, PGSQL and SQLite but have never needed to complete them.
Here's the code generator class:
<?php
/**
* #license http://opensource.org/licenses/MIT The MIT License
* #version 1.0.0_20130220000000
*/
/**
* This class will generate PHP source code for a "model" that interfaces with
* a database table.
*
* #license http://opensource.org/licenses/MIT The MIT License
* #version 1.0.0_20130220000000
*/
class db_code_generator{
private $closing_tag;
private $columns;
private $database;
private $host;
private $password;
private $port;
private $table;
private $type;
private $username;
/**
* Constructor. By default we will try to connect to a MySQL database on
* localhost.
*
* #param string $database The name of the database the user wants to connect
* to.
*
* #param string $table The name of the table to generate code for.
*
* #param string $username The username we should use to connect to the
* database.
*
* #param string $password The password we need to connect to the database.
*
* #param string $host The host or server we will try to connect to. If the
* user doesn't give us a host we default to localhost.
*
* #param string $port The port we should try to connect to. Typically this
* will not be passed so we default to NULL.
*
* #param string $type The type of database we are connecting to. Valid
* values are: db2, mssql, mysql, pgsql, sqlite.
*/
public function __construct($database = NULL,
$table = NULL,
$username = NULL,
$password = NULL,
$host = 'localhost',
$type = 'mysql',
$port = NULL,
$closing_tag = TRUE){
$this->database = $database;
$this->table = $table;
$this->username = $username;
$this->password = $password;
$this->host = $host;
$this->port = $port;
$this->type = $type;
$this->closing_tag = $closing_tag;
}
/**
* Generate the code for a model that represents a record in a table.
*
* #return string The PHP code generated for this model.
*/
public function get_code(){
$this->get_data_definition();
$code = $this->get_file_head();
$code .= $this->get_properties();
$code .= $this->get_ctor();
$code .= $this->get_dtor();
$code .= $this->get_method_stubs();
$code .= $this->get_file_foot();
return $code;
}
/**
* Create the code needed for the __construct function.
*
* #return string The PHP code for the __construct function.
*/
private function get_ctor(){
$code = "\t/**\n";
$code .= "\t * Constructor.\n";
$code .= "\t *\n";
$code .= "\t * #param mixed \$id The unique id for a record in this table. Defaults to NULL\n";
if ('db2' === $this->type){
$code .= "\n\t * #param string \$library The library where the physical file resides. Defaults to LIBRARY\n";
}
$code .= "\t *\n";
$code .= "\t * #see base_$this->type::__construct\n";
$code .= "\t */\n";
if ('db2' === $this->type){
$code .= "\tpublic function __construct(\$id = NULL, \$library = 'LIBRARY'){\n";
$code .= "\t\tparent::__construct(\$id, \$library);\n";
}else{
$code .= "\tpublic function __construct(\$id = NULL){\n";
$code .= "\t\tparent::__construct(\$id);\n";
}
$code .= "\t}\n\n";
return $code;
}
/**
* Connect to the requested database and get the data definition for the
* requested table.
*/
private function get_data_definition(){
try{
switch ($this->type){
case 'db2':
$this->get_data_definition_db2();
break;
case 'mssql':
$this->get_data_definition_mssql();
break;
case 'mysql':
$this->get_data_definition_mysql();
break;
case 'pgsql':
$this->get_data_definition_pgsql();
break;
case 'sqlite':
$this->get_data_definition_sqlite();
break;
}
}catch(PDOException $e){
}
}
/**
* Get data definition information for a DB2 table.
*/
private function get_data_definition_db2(){
$con = new PDO("odbc:DRIVER={iSeries Access ODBC Driver};SYSTEM=$this->host;PROTOCOL=TCPIP", $this->username, $this->password);
$sql = "SELECT COLUMN_NAME, COLUMN_SIZE, COLUMN_TEXT, DECIMAL_DIGITS, ORDINAL_POSITION, TYPE_NAME FROM SYSIBM.SQLCOLUMNS WHERE TABLE_SCHEM = '". strtoupper($this->database) ."' AND TABLE_NAME = '". strtoupper($this->table) ."'";
$statement = $con->prepare($sql);
if ($statement->execute()){
while ($row = $statement->fetch()){
if (NULL !== $row['DECIMAL_DIGITS']){
$decimal = $row['DECIMAL_DIGITS'];
}else{
$decimal = NULL;
}
if ('DECIMAL' === $row['TYPE_NAME'] && NULL !== $row['DECIMAL_DIGITS'] && '0' !== $row['DECIMAL_DIGITS']){
$type = 'float';
}else if ('DECIMAL' === $row['TYPE_NAME']){
$type = 'integer';
}else{
$type = strtolower($row['TYPE_NAME']);
}
if ('1' === $row['ORDINAL_POSITION']){
$key = 'PRI';
}else{
$key = NULL;
}
$this->columns[$row['COLUMN_NAME']] = array('allow_null' => TRUE,
'decimal' => $decimal,
'default' => NULL,
'extra' => NULL,
'key' => $key,
'length' => $row['COLUMN_SIZE'],
'name' => $row['COLUMN_NAME'],
'text' => $row['COLUMN_TEXT'],
'type' => $type);
}
ksort($this->columns);
}
}
/**
* Get data definition information for a MS SQL table.
*/
private function get_data_definition_mssql(){
return "The code for generating MS SQL models is not yet implemented.\n";
}
/**
* Get data definition information for a MySQL table.
*/
private function get_data_definition_mysql(){
$dsn = "mysql:host=$this->host;";
if (NULL !== $this->port){
$dsn .= "port=$this->port;";
}
$dsn .= "dbname=$this->database";
$con = new PDO($dsn, $this->username, $this->password);
$sql = "SHOW COLUMNS FROM $this->table";
$statement = $con->prepare($sql);
if ($statement->execute()){
while ($row = $statement->fetch()){
$this->columns[$row['Field']] = array('allow_null' => $row['Null'],
'decimal' => NULL,
'default' => $row['Default'],
'extra' => $row['Extra'],
'key' => $row['Key'],
'length' => NULL,
'name' => $row['Field'],
'text' => NULL,
'type' => $row['Type']);
}
ksort($this->columns);
}
}
/**
* Get data definition information for a PostgreSQL table.
*/
private function get_data_definition_pgsql(){
return "The code for generating PostgreSQL models is not yet implemented.\n";
}
/**
* Get data definition information for a SQLite table.
*/
private function get_data_definition_sqlite(){
return "The code for generating SQLite models is not yet implemented.\n";
}
/**
* Create the code needed for the __destruct function.
*
* #return string The PHP code for the __destruct function.
*/
private function get_dtor(){
$code = "\t/**\n";
$code .= "\t * Destructor.\n";
$code .= "\t */\n";
$code .= "\tpublic function __destruct(){\n";
$code .= "\t\tparent::__destruct();\n";
$code .= "\t}\n\n";
return $code;
}
/**
* Generate the code found at the end of the file - the closing brace, the
* ending PHP tag and a new line. Some PHP programmers prefer to not have a
* closing PHP tag while others want the closing tag and trailing newline -
* it probably just depends on their programming background. Regardless it's
* best to let everyone have things the way they want.
*/
private function get_file_foot(){
$code = '';
if ($this->closing_tag){
$code .= "}\n?>\n";
}else{
$code .= '}';
}
return $code;
}
/**
* Generate the code found at the beginning of the file - the PHPDocumentor
* doc block, the require_once for the correct base class and the class name.
*
* #return string The code generated for the beginning of the file.
*/
private function get_file_head(){
$code = "<?php\n";
$code .= "/**\n";
$code .= " * Please enter a description of this class.\n";
$code .= " *\n";
$code .= " * #author XXX <XXX#domain.com>\n";
$code .= " * #copyright Copyright (c) ". date('Y') ."\n";
$code .= " * #license http://www.gnu.org/licenses/gpl-3.0.html GPLv3\n";
$code .= " * #version ". date('Ymd') ."\n";
$code .= " */\n\n";
$code .= "require_once('base_$this->type.php');\n\n";
$code .= "class ". strtolower($this->table) ." extends base_$this->type{\n";
return $code;
}
/**
* Generate the code for a delete method stub.
*
* #return string The PHP code for the method stub.
*/
private function get_method_stub_delete(){
$code = "\t/**\n";
$code .= "\t * Override the delete method found in the base class.\n";
$code .= "\t *\n";
$code .= "\t * #param mixed \$id The unique record ID to be deleted.\n";
$code .= "\t *\n";
$code .= "\t * #return bool TRUE if a record was successfully deleted from the table, FALSE otherwise.\n";
$code .= "\t */\n";
$code .= "\tpublic function delete(\$id){\n";
$code .= "\t\treturn parent::delete(\$id);\n";
$code .= "\t}\n\n";
return $code;
}
/**
* Generate the code for an insert method stub.
*
* #return string The PHP code for the method stub.
*/
private function get_method_stub_insert(){
$code = "\t/**\n";
$code .= "\t * Override the insert method found in the base class.\n";
$code .= "\t *\n";
$code .= "\t * #param array \$parms An array of data, probably the \$_POST array.\n";
$code .= "\t * #param bool \$get_insert_id A flag indicating if we should get the autoincrement value of the record just created.\n";
$code .= "\t *\n";
$code .= "\t * #return bool TRUE if a record was successfully inserted into the table, FALSE otherwise.\n";
$code .= "\t */\n";
$code .= "\tpublic function insert(\$parms, \$get_insert_id = FALSE){\n";
$code .= "\t\treturn parent::insert(\$parms, \$get_insert_id);\n";
$code .= "\t}\n\n";
return $code;
}
/**
* Generate the code for an update method stub.
*
* #return string The PHP code for the method stub.
*/
private function get_method_stub_update(){
$code = "\t/**\n";
$code .= "\t * Override the update method found in the base class.\n";
$code .= "\t *\n";
$code .= "\t * #param array &\$parms An array of key=>value pairs - most likely the \$_POST array.\n";
$code .= "\t *\n";
$code .= "\t * #param integer \$limit The number of records to update. Defaults to NULL.\n";
$code .= "\t *\n";
$code .= "\t * #return bool TRUE if a record was successfully updated, FALSE otherwise.\n";
$code .= "\t */\n";
$code .= "\tpublic function update(\$parms, \$limit = NULL){\n";
$code .= "\t\treturn parent::update(\$parms, \$limit);\n";
$code .= "\t}\n\n";
return $code;
}
/**
* Create method stubs for create, delete and update.
*
* #return string The PHP code for these stubs.
*/
private function get_method_stubs(){
$code = $this->get_method_stub_delete();
$code .= $this->get_method_stub_insert();
$code .= $this->get_method_stub_update();
return $code;
}
private function get_properties(){
$code = '';
if (count($this->columns)){
foreach ($this->columns AS $index => $col){
$code .= "\t/**\n";
if (NULL !== $col['text']){
$code .= "\t * $col[text]\n";
}else{
$code .= "\t * Description\n";
}
$code .= "\t * #var ". $col['type'];
if (NULL !== $col['length']){
$code .= " ($col[length]";
if (NULL !== $col['decimal']){
$code .= ",$col[decimal]";
}
$code .= ")";
}
$code .= "\n\t */\n";
$temp_name = str_replace('#', '_', $col['name']);
$code .= "\tpublic \$$temp_name;\n\n";
}
}
return $code;
}
}
?>
and here's a simple page to use it:
<?php
/**
* #license GPLv3 (http://www.gnu.org/licenses/gpl-3.0.html)
* #version 1.0.0_20130220000000
*/
require_once('db_code_generator.php');
$table_type = array();
$table_type['db2'] = 'DB2/400 (db2)';
$table_type['mssql'] = 'Microsoft SQL Server (mssql)';
$table_type['mysql'] = 'MySQL (mysql)';
$table_type['pgsql'] = 'PostGRESQL (pgsql)';
$table_type['sqlite'] = 'SQLite (sqlite)';
$database = (isset($_POST['database'])) ? $_POST['database'] : 'my_database';
$host = (isset($_POST['host'])) ? $_POST['host'] : 'localhost';
$username = (isset($_POST['username'])) ? $_POST['username'] : 'root';
$password = (isset($_POST['password'])) ? $_POST['password'] : '';
$table = (isset($_POST['table'])) ? $_POST['table'] : '';
$type = (isset($_POST['type'])) ? $_POST['type'] : 'mysql';
$library = (isset($_POST['library'])) ? $_POST['library'] : 'LIBRARY';
$file = (isset($_POST['file'])) ? $_POST['file'] : 'STATES';
//---------------------------------------------------------------------------
?>
<div class="data_input">
<form action="" method="post">
<fieldset class="top">
<legend>Code Generator</legend>
<label for="host">Hostname or IP:
<input id="host" maxlength="32" name="host" tabindex="<?php echo $tabindex++; ?>" title="Enter the database host name" type="text" value="<?php echo $host; ?>" />
</label>
<br />
<label for="username">Username:
<input id="username" maxlength="32" name="username" tabindex="<?php echo $tabindex++; ?>" title="Enter the database username" type="text" value="<?php echo $username; ?>" />
</label>
<br />
<label for="password">Password:
<input id="password" maxlength="32" name="password" tabindex="<?php echo $tabindex++; ?>" title="Enter the database password" type="password" value="<?php echo $password; ?>" />
</label>
<br />
<label for="type">Type:
<select id="type" name="type" tabindex="<?php echo $tabindex++; ?>">
<?php
foreach ($table_type AS $key=>$value){
echo('<option ');
if ($key == $type){
echo 'selected="selected" ';
}
echo 'value="'. $key .'">'. $value .'</option>';
}
?>
</select>
</label>
<br />
</fieldset>
<fieldset class="top">
<legend>PostGRESQL/MSSQL/MySQL Parameters</legend>
<label for="database">Database:
<input id="database" maxlength="100" name="database" tabindex="<?php echo $tabindex++; ?>" title="Enter the database name" type="text" value="<?php echo $database; ?>" />
</label>
<br />
<label for="table">Table:
<input id="table" maxlength="100" name="table" tabindex="<?php echo $tabindex++; ?>" title="Enter the table name" type="text" value="<?php echo $table; ?>" />
</label>
<br />
</fieldset>
<fieldset class="top">
<legend>DB2 Parameters</legend>
<label for="library">Library:
<input id="library" maxlength="10" name="library" tabindex="<?php echo $tabindex++; ?>" title="Enter the library name" type="text" value="<?php echo $library; ?>" />
</label>
<br />
<label for="file">Physical File:
<input id="file" maxlength="10" name="file" tabindex="<?php echo $tabindex++; ?>" title="Enter the file name" type="text" value="<?php echo $file; ?>" />
</label>
<br />
</fieldset>
<fieldset class="bottom">
<button tabindex="<?php echo $tabindex++; ?>" type="submit">Generate!</button>
</fieldset>
</form>
</div>
<?php
if (isset($_POST['host'])){
if ('db2' == $_POST['type']){
$_POST['database'] = strtoupper($_POST['library']); // Library
$_POST['table'] = strtoupper($_POST['file']); // Physical file
$_POST['host'] = 'db2_host';
$_POST['username'] = 'db2_username';
$_POST['password'] = 'db2_password';
}
$object = new db_code_generator($_POST['database'], $_POST['table'], $_POST['username'], $_POST['password'], $_POST['host'], $_POST['type']);
echo('<textarea rows="75" style="margin-left : 50px; width : 90%;" onfocus="select()">'. $object->get_code() .'</textarea>');
}
?>
I understand you're looking for a ORM kind of a thing.
hope this helps
http://www.doctrine-project.org/
http://propelorm.org/
What about symfony? It does exactly what you say and you get a beastly good framework to go with it.
symfony 'compiles' classes for you based on a data model that you supply. It will make sure that compiled classes and MySQL database structure are in sync.
This approach is favorable over a Reflection based approach as it's simply too slow.
For what it's worth, Rafael Rocha shares code here.
Still, I strongly propose to use an ORM. Transforming MySQL structure back to a database-abstraction layer is anything but good...
Try this
https://github.com/rcarvello/mysqlreflection
A useful utility I built for the Object Relation Mapping of MySQL databases.
The utility generates automatically PHP classes for any tables of a given database schema.
The package is extracted from my personal PHP Web MVC Framework.
Yes, Doctrine is what you need.
Run a command, and you get all your tables' metadata in XML or YML format(choice is yours)
$ php app/console doctrine:mapping:convert xml ./src/Bundle/Resources/config/doctrine/metadata/orm --from-database --force
Once you generate the Metadata, command Doctrine to import the schema to build related entity classes you need. You will find all GET and SET functionality(read SELECT, UPDATE and INSERT) inside.
1.$ php app/console doctrine:mapping:import Bundle annotation
2.$ php app/console doctrine:generate:entities Bundle
Read details with Example here
Fat free framework allows you to work with existing tables using code like:
$user=new DB\SQL\Mapper($db,'users');
// or $user=new DB\Mongo\Mapper($db,'users');
// or $user=new DB\Jig\Mapper($db,'users');
$user->userID='jane';
$user->password=md5('secret');
$user->visits=0;
$user->save();
The code above creates new record in users table
I have written a PHP code which will automatically detect all the databases in MYSQL database, on selecting any of the database all of its related tables are loaded. You can select all the tables or any respective table to generate the Modal Class.
The following is the link to my repository
https://github.com/channaveer/EntityGenerator
This will automatically create Entity folder and dump all the entity class into that folder.
NOTE - Currently only supported for MYSQL
Hope it helps. Happy Coding!
I think you should make itout on your on. Every project and requirement of Model Code is different in my opinion. Two mysql queries will keep you in ease.
SHOW TABLES FROM db_NAME //this gives the table listing, so its Master Looper
DESC tbl_name //detail query that fetches column information of given table
DESC tbl_name will give Field, Type, Null, Key, Default and Extra Columns.
e.g. values seperated in pipes (|):
Id | int(11) | NO | PRI | NULL | auto_increment |
I followed these to make Model, controller and Viewer files supporting CRUD operation in Codeigniter 2 way back. It worked just fine.

Categories