I have some extremely complex queries that I need to use to generate a report in my application. I'm using symfony as my framework and doctrine as my ORM.
My question is this:
What is the best way to pass in highly-complex sql queries directly to Doctrine without converting them to the Doctrine Query Language? I've been reading about the Raw_SQL extension but it appears that you still need to pass the query in sections (like from()). Is there anything for just dumping in a bunch of raw sql commands?
$q = Doctrine_Manager::getInstance()->getCurrentConnection();
$result = $q->execute(" -- RAW SQL HERE -- ");
See the Doctrine API documentation for different execution methods.
Yes. You can get a database handle from Doctrine using the following code:
$pdo = Doctrine_Manager::getInstance()->getCurrentConnection()->getDbh();
and then execute your SQL as follows:
$query = "SELECT * FROM table WHERE param1 = :param1 AND param2 = :param2";
$stmt = $pdo->prepare($query);
$params = array(
"param1" => "value1",
"param2" => "value2"
);
$stmt->execute($params);
$results = $stmt->fetchAll();
You can use bound variables as in the above example.
Note that Doctrine won't automatically hydrate your results nicely into record objects etc, so you'll need to deal with the results being returned as an array, consisting of one array per row returned (key-value as column-value).
I'm not sure what do you mean saying raw SQL, but you coud execute traditional SQL queries this way:
...
// $this->_displayPortabilityWarning();
$conn = Doctrine_Manager::connection();
$pdo = $conn->execute($sql);
$pdo->setFetchMode(Doctrine_Core::FETCH_ASSOC);
$result = $pdo->fetchAll();
...
The following method is not necsessary, but it shows a good practice.
protected function _displayPortabilityWarning($engine = 'pgsql')
{
$conn = Doctrine_Manager::connection();
$driver = $conn->getDriverName();
if (strtolower($engine) != strtolower($driver)) {
trigger_error('Here we have possible database portability issue. This code was tested on ' . $engine . ' but you are trying to run it on ' . $driver, E_USER_NOTICE);
}
}
You can also use Doctrine_RawSql(); to create raw SQL queries which will hydrate to doctrine objects.
It should be noted, that Doctrine2 uses PDO as a base, thus I would recommend using prepared statements over plain old execute.
Example:
$db = Doctrine_Manager::getInstance()->getCurrentConnection();
$query = $db->prepare("SELECT `someField` FROM `someTable` WHERE `field` = :value");
$query->execute(array('value' => 'someValue'));
Symfony insert raw sql using doctrine.
This in version Symfoney 1.3
$q = Doctrine_Manager::getInstance()->getCurrentConnection();
$result = $q->execute($query);
Related
I was wondering if we could query already queried table. Like this:
$results = Table::where('name','like', '%'.$request['name'].'%')->get();
$results = $results::where('surname', 'like', '%'.$request['surname'.'%'])->get();
I try to do something like this, because I have many options to query from table, and some of them may be empty. So in order not to check all possibilities, and writing different queries, it would be easier in this way. Thanks in advance
The $result variable is in fact a Laravel Collection, so you have a lot of option to work with a Collection including its own where() function.
Imho I will go with this code:
$query = Table::where('name','like', '%'.$request['name'].'%');
$results = $query->get();
$results2 = $query->where('surname', 'like', '%'.$request['surname'.'%'])->get();
I am using prepared statements for a search functionality using PDO and I am using the like clause. Mysql is 5.5.32
function dblink(){
# hidden #
$conn = new PDO("mysql:host=localhost;dbname=$database",
$username, $password, array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ
));
return $conn;
}
$conn = dblink();
$query = "select * from tablename where attrib like ? ;";
$stmt = $conn->prepare($query);
$stmt->execute(array($_POST['field']."%"));
$results = $stmt->fetchAll(PDO::FETCH_OBJ);
This dumps all the table contents when user enters % for field in the html form. I thought prepared statement would handle it and there is % in execute so that it matches the substring entered.
How do I use the POST field as normal text only so that it doesn't cause such problem?
This dumps all the table contents when user enters % for field in the html form.
Yes. That's the exact purpose of LIKE operator.
No, it has nothing to do with prepared statement. The latter is used to format your data, not to interfere with query logic.
If you don't like the way your code works - change it. But at the moment it works exactly the way you coded, with no flaws.
I am using the following code to load a categorys record:
$res = JTable::getInstance('category');
$res->load(array('id' => $catid));
Now I would like to load the record based on its title which whould be matched against a SQL LIKE-pattern - is it possible to do this in a simple way with JTable, or do I need $dbo?
Far as I know JTable is made to be simple and carry only one element at a time, and through the primary key. If you really want something more advanced, I recomend that you use JDatabaseQuery way.
// Get a db connection.
$db = JFactory::getDbo();
// Create a new query object.
$query = $db->getQuery(true);
// Select all articles for users who have a username which starts with 'a'.
// Order it by the created date.
$query
->select(array('a.*', 'b.username', 'b.name'))
->from('#__content AS a')
->join('INNER', '#__users AS b ON (a.created_by = b.id)')
->where('b.username LIKE \'a%\'')
->order('a.created DESC');
// Reset the query using our newly populated query object.
$db->setQuery($query);
// Load the results as a list of stdClass objects.
$results = $db->loadObjectList();
In your case, instead of "$db->loadObjectList();" you can use "$db->loadObject();" for load just one item.
Source:
http://docs.joomla.org/Accessing_the_database_using_JDatabase/3.1
I'm working on an application using ZF2. In my application, I have to insert many rows in a database (about 900).
I've got a table model for this, so I first try to do :
$table->insert(array('x' => $x, 'y' => $y));
in my loop. This technically work, but this is so slow that I can hardly insert half of the datas before php's timeout (and I can't change the timeout).
Then, I've decide to use a prepared statment. So I've prepared it outside of the loop, then execute it in my loop... it was even slower.
So, I decide to stop using ZF2 tools, as they seems to be too slow to be used in my case, and i've created my own request. I'm using mysql, so i can do a single request with all my values. But I can't find any method in any of the interface to escape my values...
Is there any way to do this ?
Thank you for your help and sorry for my poor english.
If you want to perform raw queries you can do so using the Database Adapter:
$sql = 'SELECT * FROM '
. $adapter->platform->quoteIdentifier('users')
. ' WHERE ' . $adapter->platform->quoteIdentifier('id') . ' = ' . $adapter->driver->formatParameterName('id');
/* #var $statement \Zend\Db\Adapter\Driver\StatementInterface */
$statement = $adapter->query($sql);
$parameters = array('id' => 99);
/* #var $results Zend\Db\ResultSet\ResultSet */
$results = $statement->execute($parameters);
$row = $results->current();
use transactions: http://dev.mysql.com/doc/refman/5.0/en/commit.html
Than will help you to decrease the execution time
I create a custom import and export, at the moment as an external script (via bootstrap), i plan to create a module in a more generic fashion lateron.
I am building a frontend for nagios and for our host management and nagios configuration btw. Maybe it might become useful for other environments (networkmanagement)
Now i need to know how to get list of all nodes of type x?
I want to avoid direct SQL.
A suggestion i got was to make an rss and parse it
but i acess the drupal db a dozen times to extract various nodes, so it feels strange to do a web request for one thing
So what i am looking for as newbie drupal dev is just a pointer to basic search module api for this task
TIA
florian
Why do you want to avoid using SQL?
If you want to get info about what's in your db, like all the nodes of type x, the only way to get it, is through a SQL query, unless you have the data extracted already.
A query like
db_query("SELECT title, nid FROM {node} WHERE type = 'x';");
shouldn't be the thing that ruins your performance.
Edit:
The link you provided is a from Drupal 7, so you have to be be careful reading this. The reason is that in Drupal 7 it is not only possible to use db_query which basically is wrapper for the php functions mysql_query, pg_query. It's a bit different and using it, you wont have to use db_specific code. Anyways new in Drupal 7 is something that is a bit like an ORM. I haven't read about it in detail, but the idea is that you can build a query using commands on an object. This is probably what you are after. However, Drupal 7 is not ready at all for production sites. There are still a lot of critical issues and security issues. So this wont be a possibility for quite some time.
Edit 2:
If you want to get the node title and body, this is what you should do:
$type = 'x';
$query = db_query("SELECT r.nid, r.title, r.body FROM {node} AS n
LEFT JOIN {node_revisions} AS r ON r.nid = n.nid
WHERE type = '%s';", array($type));
$nodes = array();
while ($node = db_fetch_object($query)) {
$nodes[$node->nid] = $node;
}
You can use db_fetch_array instead of db_fetch_object` if you want to extract arrays instead of objects from the db.
This is a pretty old question, but for anyone coming across this page now, in Drupal 7.x best practise is to use dynamic queries.
So if you wanted to select all the nodes of type x, you could do the following:
$articles = db_select('node')
->fields('node', array('nid', 'title'))
->condition('type', 'x', '=')
->execute()
->fetchAllKeyed();
The $articles variable should then be an array of all x type nodes, keyed by nid with the arrays corresponding value set to the node title. Hope that can help.
Views is generally how you create database queries without writing them in Drupal, but this query is so simple I'm not sure it's worth the overhead of learning views, barely 5 lines after you've bootstrapped Drupal:
$nodes = array();
$results = db_query("SELECT nid FROM {node} WHERE type = '%s'", $type);
while ($result = db_fetch_object($result)) {
$nodes[] = node_load($result->nid);
}
Gotta use SQL do to this.
http://api.drupal.org/api/function/node_get_types/6
Node counts =
$node_types = node_get_types();
$type_count = array();
foreach ($node_types as $type) {
$result = db_fetch_object(db_query('SELECT count(nid) AS node_count FROM {node} WHERE type = "%s"'), $type);
$type_count[$type] = $result['count(nid)'];
}
print_r($type_count);
Nodes and their type:
$node_types = node_get_types();
$nodes = array();
foreach ($node_types as $type) {
$result = db_query('SELECT nid, title FROM {node} WHERE type = "%s"'), $type);
while ($node = db_fetch_object($result)) {
$nodes[] = array('Type' => $type, 'Title' => $node->title);
}
}
print_r($nodes);
Something like that. I am eating lunch so I didn't test that but I have done this before so it should work. Drupal 6.
The migrate module may be of interest to you. It also supports drush so you can script things fairly easily.