Anybody wish to help me with a pattern for the PHP language bundle? I have embedded SQL under a variable such as below. I'm having trouble excluding the addslashes part from the scope.
$sql = "WHERE category = '" . addslashes($category) . "'";
...or...
$qid = DB::query(" WHERE category = '" . addslashes($category) . "' ");
The pattern I've come up with so far:
{ name = 'meta.scope.sql'; begin = '(dbQuery|DB::query)("|$\w*(sql|where)\w*\s*=\s*"'; end = '")|";'; patterns = ( { include = 'source.sql'; }, ); contentName = 'source.sql.embedded'; },
I'm new at this so any help would be appreciated.
Thanks, Quinn
Some time ago I introduced a SQL heredoc in PHP. Why not use this:
… $query = <<<SQL SELECT * FROM `users` WHERE `foo` = {$bar}; SQL; …
It will color the SQL according to the SQL syntax and let PHP substitute the variables as specified here: http://www.php.net/manual/ en/language.types.string.php#language.types.string.syntax.heredoc
I'd also advise using a function like this to quote/escape your SQL data:
function quote_smart($value) { // Stripslashes if (get_magic_quotes_gpc()) { $value = stripslashes($value); } // Quote if not numeric if (!is_numeric($value)) { $value = "'" . mysql_real_escape_string($value) . "'"; } return $value; }
Soryu
On 06.03.2006, at 08:55, Quinn Comendant wrote:
Anybody wish to help me with a pattern for the PHP language bundle? I have embedded SQL under a variable such as below. I'm having trouble excluding the addslashes part from the scope.
On Mon, 6 Mar 2006 12:12:40 +0100, Soryu wrote:
Some time ago I introduced a SQL heredoc in PHP. Why not use this:
... $query = <<<SQL SELECT * FROM `users` WHERE `foo` = {$bar}; SQL; ...
It will color the SQL according to the SQL syntax and let PHP substitute the variables as specified ...
Thanks Soryu, I saw that HEREDOC code. But I have my own reasons for doing the code the way I did (one reason being supporting 100000 lines of legacy code). Any ideas?
Q
On 6/3/2006, at 8:55, Quinn Comendant wrote:
[...]
$sql = "WHERE category = '" . addslashes($category) . "'";
...or...
$qid = DB::query(" WHERE category = '" . addslashes($category) . "' ");
To match the SQL part I think you will need two different rules (one for each construct).
I have written an example of matching the first construct below, let me know if you have further questions.
{ begin = '($sql) = '; end = ';';
# assign a scope name to the “$sql” part captures = { 1 = { name = 'variable.other.php'; } };
patterns = ( # start a new context for … in “$sql = …;”
# match strings in this context { name = 'string.quoted.double.php'; begin = '"'; end = '"'; patterns = ( { match = '\.'; }. # escaped characters { include = 'source.sql'; } # treat content of string as SQL ); }.
# for that which is not matched as a string in this # context use the normal (root level) PHP rules { include = '$self'; } ); }
On Tue, 7 Mar 2006 16:47:55 +0100, Allan Odgaard wrote:
[...]
I have written an example of matching the first construct below, let me know if you have further questions.
{ begin = '($sql) = '; end = ';';
[...]
Thanks Allan
But it doesn't work correctly yet. It _does_ apply source.sql to the contents of the double-quoted string, but most everything else breaks. Here is a more specific example to describe what is wrong...
$sql = "SELECT * FROM some_tbl WHERE foo = '$foo' AND bar = '" . $this-
bar() . "'";
Problem 1: The SQL is treated as a double quoted string, which it is, but I want source.sql.embedded to override string.quoted.double.php. I added contentName = 'source.sql.embedded'; and now it works.
Problem 2: $foo should be variable.other.php. Ok, I think I know how to do this, using captures, right? Or maybe even better would be to use { include = '#var_basic'; }? Nope, none of those work.
Problem 3: '" . $this->bar() . "' should be source.php but instead it considers it a string.quoted.single.php
I solved the last two problems by adding { match = "'"; }, but I have no more than an intuitive sense why this works. What does it mean to use a pattern with only a "match" statement? What is "\."? But there is a problem with this solution: it doesn't allow for single-quoted strings here, for example if '$foo' needs to be 'foo'.
In the end here is what I came up with:
{ begin = '($\w*(?:sql|where)\w*)\s*=\s*'; end = ';'; beginCaptures = { 1 = { name = 'variable.other.php'; }; }; patterns = ( { name = 'string.quoted.double.php'; begin = '"'; end = '"'; patterns = ( { match = '\.'; }, { match = "'"; }, { include = 'source.sql'; }, { include = '#var_global'; }, ); contentName = 'source.sql.embedded'; }, { include = '$self'; }, ); },
Unrelated question: what is "swallow"? It seems to be undocumented.
And how far is it to the moon? In miles - how far? And what is the principle element in the composition of moon rock? And what is the electric bill of the white house? And how do you make vegan bread pudding?
Q
On 8/3/2006, at 9:10, Quinn Comendant wrote:
Problem 1: The SQL is treated as a double quoted string, which it is, but I want source.sql.embedded to override string.quoted.double.php. I added contentName = 'source.sql.embedded'; and now it works.
So no problem, I presume?
Problem 2: $foo should be variable.other.php. Ok, I think I know how to do this, using captures, right? Or maybe even better would be to use { include = '#var_basic'; }? Nope, none of those work.
Yes, I believe my example did use a capture to name it.
Problem 3: '" . $this->bar() . "' should be source.php but instead it considers it a string.quoted.single.php
I would think it is: string.quoted.single.sql
This is because the ' starts a single quoted string in SQL. You will need a rule to override that, likely only when next character is a ".
What does it mean to use a pattern with only a "match" statement?
That this pattern is matched against the text, and if it does match, the name of the rule is assigned to that portion of the text (and the text is not matched by other rules afterwards).
What is "\."?
That’s the regular expression to match a backslash followed by any character.
This is for things like: "this "is" a string"
Here \. will match the two ", so that the " there won’t end the string.
But there is a problem with this solution: it doesn't allow for single-quoted strings here, for example if '$foo' needs to be 'foo'.
Not sure what this refers to, but if it lack a match, add it ;)
[...] Unrelated question: what is "swallow"? It seems to be undocumented.
http://lists.macromates.com/pipermail/textmate/2006-February/008692.html