I wish to store PDO results in redis cache so from online resources I gathered i do this.
$domain = 'www.example.com';
function getStat($domain) {
global $pdo;
global $redis;
$statement = "SELECT * FROM mc_visitor_session WHERE website = \'$domain\'";
$hash = md5($statement);
if (!$redis->get($hash . '-cache')) {
$query = $pdo->query($domain);
if ($result = $query->execute()) {
$record = $query->fetchAll(\PDO::FETCH_ASSOC);
$redis->set($hash . '-cache', serialize($record));
$redis->expire($hash . '-cache', 86400);
echo 'RESULT FROM MYSQL';
pretty_print($record);
}
}
$results = unserialize($redis->get($hash . '-cache'));
//will show this if it's already in cache.
echo 'RESULT FROM REDIS';
pretty_print($results);
}
getStat($domain);
As you can see the above code works well. However I wish to work it with pdo prepared statements instead of using pdo query without preparing and safely executing the queries. But I need to get the hash from the query statement as well to be use as the key in redis.
This is just one of the query i want to cache with redis and other queries contains more than 1 WHERE statement which requires multiple PDO Bind Parameter.
This may not be the best way to do it so may I ask for suggestions on how I can improve this to make it safer.
I saw this "Smart" Caching System using PDO and Memcache elsewhere on SO.
Wrap your PDO call inside a function that will hash the statement and an array of parameters.
$name = 'querycache-'.md5(serialize(array($sql, $params)));
You also need to ask yourself if fine-tuning your database, using proper indexes and letting it use its own caching system won't be faster than caching to Redis.
Write $query = $pdo->query($statement); instead of $query = $pdo->query($domain);
Related
For this query, is necessary to use mysql_real_escape_string?
Any improvement or the query is fine ?
$consulta = $_REQUEST["term"]."%";
($sql = $db->prepare('select location from location_job where location like ?'));
$sql->bind_param('s', $consulta);
$sql->execute();
$sql->bind_result($location);
$data = array();
while ($sql->fetch()) {
$data[] = array('label' => $location);
}
The query speed is important in this case.
No, prepared queries (when used properly) will ensure data cannot change your SQL query and provide safe querying. You are using them properly, but you could make just one little change. Because you are using the '?' placeholder, it is easier to pass params through the execute method.
$sql->execute([$consulta]);
Just be careful if you're outputting that to your page, SQL parameter binding does not mean it will be safe for display within HTML, so run htmlspecialchars() on it as well when outputting.
I am experiencing a strange phenomenon while mixing $this->db->where() and $this->db->query().
if (!empty($args) && is_array($args)) {
foreach ($args as $key => $value) {
$this->db->where_in($field, $value);
}
}
$result = $this->db->query('SELECT * FROM ...')->result_array();
While I can understand it is probably better to not mix ActiveRecord and regular queries, I am experiencing that the WHERE clause I am building up with $this->db->where_in() is affecting subsequent queries (i.e., the clause executes on next query).
Should all my queries be rewritten to either not use ActiveRecord, or to use ONLY ActiveRecord? Or is there a way to prevent this "clash"? I thought about $ths->db->flush_cache() but I am not using database caching, and using it does not seem to have any effect.
I would suggest not calling db->where_in in a loop. Consider instead
if (!empty($args) && is_array($args))
{
foreach ($args as $key => $value)
{
$values[] = $value;
}
$this->db->where_in($field, $values);
}
In truth the loop in not needed if $args is an indexed (as opposed to associative) array. You could simply remove the foreach and use
$this->db->where_in($field, $args);
You probably shouldn't mix Query Builder (previously known as Active Record) and db->query(). The Query Builder (QB) methods essentially assemble a statement that you would provide to db->query() and then, pretty much literally calls query("The statement that QB built").
IMO, it is almost always easier to type the query statement and use it in $this->db->query("Select * from ...");. Query Builder is great but is often more work that it is worth.
In your example you should probably stick to Query Builder. That can still be very concise. If you're looking for all fields from a single table then db->get will do the job.
$result = $this->db->get('table_name')->result_array();
Typically QB clears all the various elements created that go into the statement when the statement is executed with a get, insert, or update call. You can start fresh at any point with this call.
$this->db->reset_query();
I have a query which I use all over my routes.php under almost every get request and also use the results in many of my views. It makes more sense at this point for me to call the query once and be able to use it globally without ever having to call it again.
Here's the query:
$followers = Follower::where('user_id', '1')
->get();
How can I do this?
Why not just execute the query once in an init function and store the result into a global variable?
global $followers = Follower::where('user_id', '1')
->get();
you can store it to the session every time the user logs in
Like this exemple
$followers = Follower::where('user_id', '1')
->first();
Session::put('followers', 'value');
whenever you want that you can access it like this
$value = Session::get('followers');
The another answer with session is a simple solution but
I would suggest you to use Laravel Cache for this purpose (because this is the standard practice).
The Laravel Cache::remember accepts three parameters.
key: make an md5 key of 'followers' and 'user id'
time: time in minutes you want to cache the values (depending how frequently your values will be changed)
A closure function which runs when no value is found corresponding to the key. (this method will query once, in this case, and store the value in your cache)
Just do the following in your BaseController's constructor:
$id = 1; //User id
$key = md5('followers'.$id);
$minutes = 60; //cache for 1 hour, change it accordingly
$followers = Cache::remember($key, $minutes, function() use ($id) {
return Follower::where('user_id', $id)->get();
});
Now of course to use Cache you need to use some Cache driver like Redis.
If you don't have how to setup it Read my other answer.
Though it may be little longer solution for your problem, and may take you 15-20 min to set up and run everything, but believe me once you start using cache you will love it.
In my Symfony/Doctrine app, I have a query that orders by RANDOM(). I call this same method several times, but it looks like the query's result is being cached.
Here's my relevant code:
$query = $table->createQuery('p')
->select('p.*, RANDOM() as rnd')
->orderBy('rnd')
->limit(1)
->useQueryCache(null)
->useResultCache(null);
$result = $query->fetchOne();
Unfortunately, the same record is returned every time, regardless of me passing null to both useQueryCache and useResultCache. I tried using false instead of null, but that didn't work either. Lastly, I also tried calling both setResultCacheLifeSpan(0) and setResultCacheLifeSpan(-1), but neither call made a difference.
Any insight on how to prevent caching since I want a different random row to be selected each time I call this method?
Edit: I also tried calling clearResultCache(), but that just ended up causing an error stating: "Result Cache driver not initialized".
Edit 2: As requested, here's the SQL generated by calling $query->getSqlQuery():
SELECT c.id AS c__id, c.name AS c__name, c.image_url AS c__image_url,
c.level AS c__level, c.created_at AS c__created_at, c.updated_at
AS c__updated_at, RANDOM() AS c__0 FROM cards c ORDER BY c__0 LIMIT 1
It turns out I'm a moron. I tried to simplify my query for this question, and in doing so, I didn't capture the true cause. I had a where() and andWhere() call, and the combination of conditions resulted in only one possible record being matched. Thanks for taking the time to respond, everyone, sorry to have wasted your time!
Doctrine also caches entities you created in the same request/script run.
For instance:
$order = new Order();
$order->save();
sleep(10); // Edit this record in de DB in another procces.
$q = new Doctrine_Query();
$result = $q->select()
->from('Order o')
->where('o.id = '.$order->id);
$order = $result->getFirst();
print_r($order->toArray());
The print_r will not contain the changes you made during the sleep.
The following code will remove that kind of memory cache:
$manager = Doctrine_Manager::getInstance();
$connection = $manager->getCurrentConnection();
$tables = $connection->getTables();
foreach ( $tables as $table ) {
$table->clear();
}
PS: Added this answer because I found this topic trying to resolve above issue.
i created a Doctrine_Query and executes it but i wanna know what params i can pass to it.
$q = Doctrine_Query::create()
->select('cl.id, cl.name')
->from('ContactList cl');
$contactLists = $q->execute($params, $hydrationMode);
from the api documentation:
execute($params = array(), $hydrationMode = null)
where do they tell me about the params? and also hydration mode.
seems like i cannot find anything in the documentations. would be great if they had a reference for everything.
thanks
I beleive the params are an array of values to bind to the query - similar to a prepeared statement - for example:
$q = Doctrine_Query::create()
->select('cl.id, cl.name')
->from('ContactList cl')
->where('cl.name = ?');
$q->execute(array('fayer'));
The hydration mode is one of the hydrator constants from Doctrine_Core and determines how the result set is hydrated (Array, object, etc..) You can also write custom hydrators if you need to.