Usage of class constants inside strings and heredocs [message #170489] |
Tue, 02 November 2010 16:14 |
Giuseppe Sacco
Messages: 5 Registered: November 2010
Karma: 0
|
Junior Member |
|
|
Hi all,
I created a class that encapsulates all methods for accessing a
database table. That class have class constants for defining all table
fields. I would like to create strings that include those constants,
but I fail to see how I might do it.
a simple (and not working) example:
class myTable {
const F_CODE = "code";
const F_DESCRIPTIOM = "description";
const TABLENAME = "lookup";
public function insert($record)
{
$sql = <<<SQLQ
INSERT INTO {self::TABLENAME}
VALUES ({$record[self::F_CODE]},{$record[self::F_DESCRIPTION]}
SQLQ;
// ....
} // end method insert
} // end class myTable
So, again, my question is: how do I put constants inside strings or
heredocs?
Thank you very much,
Giuseppe
|
|
|
Re: Usage of class constants inside strings and heredocs [message #170490 is a reply to message #170489] |
Tue, 02 November 2010 16:47 |
alvaro.NOSPAMTHANX
Messages: 277 Registered: September 2010
Karma: 0
|
Senior Member |
|
|
El 02/11/2010 17:14, Giuseppe Sacco escribió/wrote:
> I created a class that encapsulates all methods for accessing a
> database table. That class have class constants for defining all table
> fields. I would like to create strings that include those constants,
> but I fail to see how I might do it.
>
> a simple (and not working) example:
>
> class myTable {
> const F_CODE = "code";
> const F_DESCRIPTIOM = "description";
> const TABLENAME = "lookup";
> public function insert($record)
> {
> $sql =<<<SQLQ
> INSERT INTO {self::TABLENAME}
> VALUES ({$record[self::F_CODE]},{$record[self::F_DESCRIPTION]}
> SQLQ;
>
> // ....
> } // end method insert
> } // end class myTable
"Not working" is a too simplistic description. Let's fix some syntax
errors and run your cod:
<?php
class myTable {
const F_CODE = "code";
const F_DESCRIPTION = "description";
const TABLENAME = "lookup";
public function insert($record)
{
$sql = <<<SQLQ
INSERT INTO {self::TABLENAME}
VALUES ({$record[self::F_CODE]},{$record[self::F_DESCRIPTION]})
SQLQ;
echo $sql;
} // end method insert
} // end class myTable
$record = array(
'code' => 'This is the code',
'description' => 'This is the description',
);
$foo = new myTable;
$foo->insert($record);
?>
INSERT INTO {self::TABLENAME}
VALUES (This is the code,This is the description)
> So, again, my question is: how do I put constants inside strings or
> heredocs?
Here's the documentation for the heredoc syntax:
http://es.php.net/manual/en/language.types.string.php#language.types.string .syntax.heredoc
Scroll down to "Variable parsing". As the title suggests, PHP only
parses variables, but there's a note to be taken into account:
"Functions, method calls, static class variables, and class constants
inside {$} work since PHP 5. However, the value accessed will be
interpreted as the name of a variable in the scope in which the string
is defined. Using single curly braces ({}) will not work for accessing
the return values of functions or methods or the values of class
constants or static class variables."
In simple words: it parses {self::TABLENAME} and then looks for a local
variable called $lookup. There is no replacement for two reasons:
- The syntax should be {${self::TABLENAME}}
- There is no such local variable
This does work as expected:
$tablename = self::TABLENAME;
$f_code = $record[self::F_CODE];
$f_description = $record[self::F_DESCRIPTION];
$sql = <<<SQLQ
INSERT INTO $tablename
VALUES ($f_code,$f_description)
SQLQ;
Make sure that heredoc is simplifying your code and not the opposite. To
build a simple templating system there're other alternatives like
sprintf() or strtr().
--
-- http://alvaro.es - Álvaro G. Vicario - Burgos, Spain
-- Mi sitio sobre programación web: http://borrame.com
-- Mi web de humor satinado: http://www.demogracia.com
--
|
|
|
|
Re: Usage of class constants inside strings and heredocs [message #170498 is a reply to message #170490] |
Wed, 03 November 2010 09:40 |
Giuseppe Sacco
Messages: 5 Registered: November 2010
Karma: 0
|
Junior Member |
|
|
Álvaro,
thanks for your prompt answer. I understood what you say about class
constants and I understood that it is not possible to use class
constants in heredoc or string text. I just would like to write that
in my opinion this would really improve readability: I need class
constants in order to define strings that should never be changeable,
and I think heredoc are wonderful for creating long and indented text.
I mean, I just wrote a very simple query, but real queries use as much
as 20 table fields.
Using sprintf and such, add runtime complexity for dinamically create
a static string.
Is there any other *static* way?
Thanks a lot,
Giuseppe Sacco
|
|
|
Re: Usage of class constants inside strings and heredocs [message #170500 is a reply to message #170498] |
Wed, 03 November 2010 12:07 |
Jerry Stuckle
Messages: 2598 Registered: September 2010
Karma: 0
|
Senior Member |
|
|
On 11/3/2010 5:40 AM, Giuseppe Sacco wrote:
> Álvaro,
> thanks for your prompt answer. I understood what you say about class
> constants and I understood that it is not possible to use class
> constants in heredoc or string text. I just would like to write that
> in my opinion this would really improve readability: I need class
> constants in order to define strings that should never be changeable,
> and I think heredoc are wonderful for creating long and indented text.
> I mean, I just wrote a very simple query, but real queries use as much
> as 20 table fields.
> Using sprintf and such, add runtime complexity for dinamically create
> a static string.
>
> Is there any other *static* way?
>
> Thanks a lot,
> Giuseppe Sacco
If you're trying to use class constants in heredoc or string text,
you're building the string dynamically anyway.
I agree with Micha - sprintf() is good for this; concatenation will also
work but is harder to read, imho.
And no, I don't think the complexity is that great at all, even for 20
fields.
--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex(at)attglobal(dot)net
==================
|
|
|
Re: Usage of class constants inside strings and heredocs [message #170509 is a reply to message #170500] |
Thu, 04 November 2010 09:01 |
Giuseppe Sacco
Messages: 5 Registered: November 2010
Karma: 0
|
Junior Member |
|
|
Hi all,
just to be sure: when you suggest to use sprintf(), do you mean
something like this?
<?php
class myTable {
const F_CODE = "code";
const F_DESCRIPTION = "description";
const TABLENAME = "lookup";
public function insert($record)
{
// simplified: does not escape strings, does not use prepared
statemnts
$sql = sprintf("INSERT INTO %s (%s,%s) VALUES ('%s', '%s')",
self::TABLENAME, self::F_CODE, self::F_DESCRIPTION,
$record[self::F_CODE], $record[self::F_DESCRIPTION]);
echo $sql;
} // end method insert
} // end class myTable
$record = array(
'code' => 'This is the code',
'description' => 'This is the description',
);
$foo = new myTable;
$foo->insert($record);
?>
|
|
|
Re: Usage of class constants inside strings and heredocs [message #170510 is a reply to message #170509] |
Thu, 04 November 2010 09:16 |
alvaro.NOSPAMTHANX
Messages: 277 Registered: September 2010
Karma: 0
|
Senior Member |
|
|
El 04/11/2010 10:01, Giuseppe Sacco escribió/wrote:
> Hi all,
> just to be sure: when you suggest to use sprintf(), do you mean
> something like this?
>
> <?php
>
> class myTable {
> const F_CODE = "code";
> const F_DESCRIPTION = "description";
> const TABLENAME = "lookup";
> public function insert($record)
> {
> // simplified: does not escape strings, does not use prepared
> statemnts
> $sql = sprintf("INSERT INTO %s (%s,%s) VALUES ('%s', '%s')",
> self::TABLENAME, self::F_CODE, self::F_DESCRIPTION,
> $record[self::F_CODE], $record[self::F_DESCRIPTION]);
>
> echo $sql;
> } // end method insert
>
> } // end class myTable
>
> $record = array(
> 'code' => 'This is the code',
> 'description' => 'This is the description',
> );
> $foo = new myTable;
> $foo->insert($record);
>
> ?>
IMHO this looks cleaner than your original approach but you can combine
all ideas to your liking, e.g.:
$sql = <<<SQLQ
INSERT
INTO %s (%s, %s)
VALUES ('%s', '%s')
SQLQ;
$sql = sprintf($sql,
self::TABLENAME, self::F_CODE, self::F_DESCRIPTION,
$record[self::F_CODE], record[self::F_DESCRIPTION]);
Or even:
$sql = sprintf(<<<SQLQ
INSERT
INTO %s (%s, %s)
VALUES ('%s', '%s')
SQLQ;
, self::TABLENAME, self::F_CODE, self::F_DESCRIPTION,
$record[self::F_CODE], $record[self::F_DESCRIPTION]);
I particularly love arrays and I tend to abuse them:
$sql = "INSERT
INTO {table} ({f_code}, {f_description})
VALUES ('{r_code}', '{r_description}')";
$replacements = array(
'{table}' => self::TABLENAME,
'{f_code}' => self::F_CODE,
'{f_description}' => self::F_DESCRIPTION,
'{r_code}' => $record[self::F_CODE],
'{r_description}' => $record[self::F_DESCRIPTION]
);
$sql = strtr($sql, $replacements);
You should not run out of ideas :)
--
-- http://alvaro.es - Álvaro G. Vicario - Burgos, Spain
-- Mi sitio sobre programación web: http://borrame.com
-- Mi web de humor satinado: http://www.demogracia.com
--
|
|
|
Re: Usage of class constants inside strings and heredocs [message #170513 is a reply to message #170510] |
Fri, 05 November 2010 08:41 |
Giuseppe Sacco
Messages: 5 Registered: November 2010
Karma: 0
|
Junior Member |
|
|
Hi all,
it seems none of these methods are really good (that's my opinion, of
course) when used in my scenario. I'll try to better depict what is my
source architecture in order to better explain the problem.
I have a few classes that should be used for accessing postgresql
database. The classes are a super class called Table and a few derived
classes, one for each table. The superclass provide methods for
creating insert and update statements. These statements are stored
into the database connection via pg_prepare(). Other Table method will
receive a record and actually call pg_execute() on the prepared
statement.
The super class will use reflection on $this for getting all field
names (declared as class constants) and prepare its statement.
Something similar to this:
class Table {
/*
* Create an SQL statement for pg_prepare()
*/
public function CreaInsertStatement() {
$fields = "";
$values = "";
$j = 1;
$c = new ReflectionClass(get_class($this));
foreach ($c->getConstants() as $key => $value) {
if ($j == 1) {
$fields = "$value";
$values = "\$1";
}
else {
$fields .= ",$value";
$values .= ",\$$j";
}
$j++;
}
$sql = "INSERT INTO {$this->nometabella} (${fields}) VALUES ($
{values})";
return $sql;
}
/*
* Take a record with only data and create a new array with
* all fields ordered as in CreaInsertStatement.
* The final array is to be used in pg_execute()
*/
public function ConvertiArrayPerInsert($assoc)
{
$v = array();
$j = 0;
$c = new ReflectionClass(get_class($this));
foreach ($c->getConstants() as $key => $value) {
$valore = $assoc[$value];
if (is_object($valore)) {
$classe = get_class($valore);
if ("DateTime" == $classe) {
// convert DateTime into string (TimeStamp) since pg_execute
// wouldn't convert it
/* @var $valore DateTime */
$valore = $valore->format('Y-m-d H:i:s');
}
}
$v[$j++] = $valore;
}
return $v;
}
} // end Table class
class Anagrafica extends Tabella {
// elenco dei campi nel database
const DB_ANAG_COD_ANAG = "cod_anag";
const DB_ANAG_COD_ORIGINALE = "cod_originale";
const DB_ANAG_COD_TIPOANAGRAFICA = "cod_tipoanagrafica";
const DB_ANAG_COD_FONTE = "cod_fonte";
const DB_ANAG_COD_TIPORAPPORTO = "cod_tiporapporto";
// more fields ....
protected $primarykey = array(
Anagrafica::DB_ANAG_COD_ANAG => Anagrafica::DB_ANAG_COD_ANAG,
Anagrafica::DB_ANAG_COD_ORIGINALE =>
Anagrafica::DB_ANAG_COD_ORIGINALE);
protected $nometabella = "anagrafica";
}
Thanks again,
Giuseppe
|
|
|
Re: Usage of class constants inside strings and heredocs [message #170514 is a reply to message #170513] |
Fri, 05 November 2010 12:11 |
Giuseppe Sacco
Messages: 5 Registered: November 2010
Karma: 0
|
Junior Member |
|
|
oops, I forgot to add the part about class constants in strings...
in all derived classes, I have special method for common operations on
specific tables. As an example, delete records:
class Comunicazioni extends Table {
// declare all field as class constants
// ...
public function CreaDeleteStatemnt() {
return "DELETE FROM {$this->nometabella}\nWHERE
".Comunicazioni::DB_COD_ANAG."=\$1 AND
".Comunicazioni::DB_COD_ORIGINALE."=\$2";
}
} // end class Comunicazioni
This is where I would like to use heredoc: I am in a derived class, so
I do not need reflection, and I need to create a prepared statement,
so I use placeholders instead of real values.
Bye,
Giuseppe
|
|
|
Re: Usage of class constants inside strings and heredocs [message #170515 is a reply to message #170514] |
Fri, 05 November 2010 13:01 |
Matthew Leonhardt
Messages: 9 Registered: November 2010
Karma: 0
|
Junior Member |
|
|
"Giuseppe Sacco" <eppesuig(at)gmail(dot)com> wrote in message
news:e35bdb56-6101-478c-891b-0facb4ebc0aa(at)g13g2000yqj(dot)googlegroups(dot)com...
> oops, I forgot to add the part about class constants in strings...
> in all derived classes, I have special method for common operations on
> specific tables. As an example, delete records:
>
> class Comunicazioni extends Table {
> // declare all field as class constants
> // ...
> public function CreaDeleteStatemnt() {
> return "DELETE FROM {$this->nometabella}\nWHERE
> ".Comunicazioni::DB_COD_ANAG."=\$1 AND
> ".Comunicazioni::DB_COD_ORIGINALE."=\$2";
> }
> } // end class Comunicazioni
>
> This is where I would like to use heredoc: I am in a derived class, so
> I do not need reflection, and I need to create a prepared statement,
> so I use placeholders instead of real values.
I don't see how any of this is relevant...
public function CreaDeleteStatemnt()
{
$delSql =<<<SQL
DELETE FROM %s
WHERE %s=\$1 AND %s=\$2
SQL;
return sprintf($delSql, $this->nometabella, Comunicazioni::DB_COD_ANAG,
Comunicazioni::DB_COD_ORIGINALE);
}
Does Alvero's (very elegant) suggestion of mixing heredoc with sprintf() not
fulfill your requirements for some reason?
|
|
|