I don't want to use drupal db_ rules.. I'd rather use my own pdo techniques for database queries and updates etc.. But I've managed to be able to get pdo to work, the only issue is that I have to use a connect on every custom page, some users in my community can edit the pages and will be able to see the connection information.. require & require_once do not seem to work.
Has anyone else had this issue and knows how to avoid it?
You could create your own module and use the init hook:
https://api.drupal.org/api/drupal/modules%21system%21system.api.php/function/hook_init/7
function yourmodulename_init() {
// This code will be executed on every page
}
However you should try to use the drupal database mechanics as it comes with a lot of best practices and powerful tools. E.g. views integration:
https://api.drupal.org/api/views/views.api.php/function/hook_views_data/7
In Drupal 7, Database::getConnection allows you to retrieve DatabaseConnection objects for all configured databases. And DatabaseConnection extends PDO so if your really want to bypass Drupal's Database API (which is itself based on PDO and either re-use or extends PDO classes all over the place), you can use it as you would use your own PDO object.
But if user of your community are able to edit your custom page, I'm guessing that your are actually embedding PHP code inside Drupal nodes using the PHP filter. Which is itself a very bad idea (worse than ignoring Drupal's Database API). You should instead consider writing custom modules tailored for your needs.
Related
I am working on a project that use MongoDB to house transactional data with MySQL housing all other data. For various reasons, we are looking at the possibility of moving from MongoDB to the MySQL xDevApi with the 8.0 version. In preparation for this possibility as well as to ease the learning curve as well as other database considerations, I am looking at creating a wrapper that will allow us to switch the database backend without having to update all the places in the code that interfaces with MongoDB.
I have an outline of one already, but am not sure it is the best way to do it. I think it is a decent start, I am just not certain of the file/folder structure.
The current file/folder structure is as follows:
\DocumentStore
abstract class DocumentStoreQueryBuilder
interface IDocumentStore
interface IDocumentStoreConnection
\DocumentStore\Mongo
class Connection implements IDocumentStoreConnection
class Query implements IDocumentStore
class QueryBuilder extends BuilderAlias
My thought is to use language similar to a relational database in order to help with the initial learning curve of those coming from a RDB background (the majority of those that will be coming onto the project).
I am sure that there is a better way to organize things, but to be honest, I am not too terribly familiar with Document Storage generally.
This is code that works with what I have so far.
In the connection file that is called from all files that need the connection.
$mgdbdoc = new DocumentStore\Mongo\Connection();
$connectionString = $mgdbdoc->buildConnectionString($settings);
$mgdbdoc->connect($connectionString);
$collection = new DocumentStore\Mongo\Query($mgdbdoc);
Defines the collection for action on. This could, theretically, be saved to a unique class name for each collection if necessary.
$collection->setCollection('transactions');
To be called whenever necessary.
$result = $collection->insert($document);
$result = $collection->filter($filter)->limit(2)->descending('_id')->select();
I haven't put in the update and remove functionality yet, and the and/or functionality is proving difficult, but I can get that.
My question is for any advice regarding this project. Any thoughts on proceeding forward? I haven't been able to locate a wrapper for multiple NoSQL databases like there is for PDO. I would appreciate any thoughts or advice.
I'm starting to write some PHP classes that are reusable across projects but had a quick question about handling dependencies.
I'm writing a pagination class that I want to grab results from a mysql database. Now obviously this will rely on a Database object/class. I have a custom written database class that I want to use but then I hit a problem. I was planning to pass the db object in as a paramter but of course, because it is my own db class - it will have custom methods that not everyone else will have.
So my pagination class might run:
$db->run_query($sql);
Obviously, someone else might have a db class that instead uses:
$db->query($sql);
What's the best way to deal with this? I could run my query before but then I'm making more work than I want to for the user. Is the lesser re-usability just something I'll have to live with if I want to make it a one-line command?
It's similar with other examples, so I may want a Page object to use an HTMLHelper but then the page class hits a wall in terms of it being easily reusable.
This is more for personal projects at the moment but releasing these classes is something that is likely to happen in the future.
Perhaps the response is :
What does it mean to "program to an interface"?
You may have to reconsider your conception.
Summary:
Do pre-controller hooks execute during caching? Is there any hook-point which will execute? (pre-system?)
I should probably highlight the fact that the hook doesn't affect the content that is sent to the browser. That isn't an issue.
Detailed version:
I plan on implementing some statistics-type functionality in a project I've built using PHP and CodeIgniter.
The project in question is a custom built CMS - due to the extended intervals between updates I've used caching to help speed up load times; this isn't essential but it's preferential. It seems to be a good solution to a largely static site; especially where dynamic content is primarily served client-side - i.e AJAX requests.
The proposed functionality primarily involves a pre-controller hook which accesses methods through libraries such as the User Agent library, before dumping them to a database. From here it can be polled, outputted via JSON and manipulated before being displayed by something like the jQuery flot plugin.
I've read through the documentation on the Web Page Caching as well as the documentation regarding hooks. Unfortunately, it's still not clear whether using caching will completely bypass the hooks.
I'm aware of the cache_override however this means implementing your own caching mechanism; not what I want to do!
The alternative would be gathering statistics client side and submitting it to the server via AJAX; but this isn't ideal either as I'm trying to have a clear separation of logic - for maintenance and testing reasons.
In short:
Do pre-controller hooks execute during caching? No.
Is there any hook-point which will execute? Yes pre_system does execute.
If caching kicks at system/core/CodeIgniter.php:189, the only hook that gets a chance to run is pre_system (system/core/CodeIgniter:124).
Unfortunately you don't get much functionality of codeigniter at that point, no get_instance() and without that most core libraries are not loaded as well. If you are inclined you can look into what functions are defined inside system/core/Common.php thats pretty much all you got.
If you are really want to make this work with the built in classes you can sort of fight your way to a database object and other core stuff like this:
You will have to manually get the BASEPATH.'database/DB.php' file included in. Fortunately in the loader class, it loaded with require_once so it won't break the page on cache miss.
Once you got the Database library loaded instantiate the usual $this->db object with calling DB(). Without parameters it will load the default database from the config files as usual.
At this point you can write your queries from your pre_system hook, and since hooks can be objects, you can move every logging code inside the hook's object. If you need other libraries you can get an instance of them with the load_class() function (don't forget to set the third prefix parameter to empty string if you are not loading a built in class).
At the end you should end up like this (imaginary code):
class MyLoggingHook {
// called from the hook config
public function run($params = array()) {
require_once(BASEPATH.'database/DB.php');
$db = DB(); // getting hold of a DAO instance
// routing information is always useful to have for pageview logs
$RTR = load_class('Router', 'core');
$RTR->_set_routing();
// Router also load Uri and Config classes inside so the following two instances could be interesting too:
// $RTR->uri
// $RTR->config
// load some useful library not related to CodeIgniter
$user_agent_detector = load_class('UserAgentDetector', 'libraries', '');
// do some logging
$db->insert('page_view_log', array('class' => $RTR->fetch_class(), 'method' => $RTR->fetch_method(), /*...*/);
}
}
I should probably mention that i've never used something like this in production and there's the risk of relaying on funcionality that could change from version to version. If you can do without touching the Codeigniter classes inside your hook go with that.
Using PDO for database access, loading the database config with get_config(), you can get by without touching any codeigniter related classes.
I am building a plugin for WordPress 3.3.1. In the code I define several shortcodes, class to support them, and a couple of admin pages. I am at a beginners level with php although I have 20+ years experience with programming, OOA&D, etc..
In the class methods, I make calls to a custom database not housed in the wp database. That is, the custom database is a separate schema, independent of the wp database.
Right now, I make the declaration in the methods that need the object. Works fine for dev but won't cut it in production. I am tempted to raise it to the class instance level. Here is where my question becomes clear. There are several classes that will need the connection. The plugin needs only one connection.
Where is the best place to put the database connection object declaration and initialization?
Given the answer to that, where is the proper place to destroy the db connection object instance?
I would make the database connection a static field. Which class to put it in depends on how you've structured your classes/code. Making it static will ensure that the same connection is shared throughout your script.
I recommend using PDO (connecting PDO to MySQL, etc) to connect to your database. PHP will automatically close the connection when the script ends.
I'm new to PHP (used to Python) and I've been instructed to create something that will allow users to CRUD entries. I was originally going to use a textarea field and sort by which numbered row they were, but I realized that if a user deleted a row, that it would screw up all the UIDs for the whole system.
So now here I am, several hours into the project and trying to figure out what's the best way to create something which A) allows multiple rows of data B) allows this information to be deleted or updated C) allows additional rows to be added D) shows all the rows available (this can be scrollable, so that it all doesn't display at once)
Database is MySQL
Are any of these easy to integrate? I don't know quite how much access I have to the server that this is running on.
It's a bit overkill, but you can very quickly get a basic and flexible CRUD up and running by installing CodeIgniter and then GroceryCRUD.
Some PHP frameworks come with built-in CRUD, but since OP didn't ask for any specific framework, then my answer recommends a framework-agnostic CRUD.
Agile UI is an open-source PHP UI component library containing CRUD, Grid, Form, Menu and many other visual elements you can use out-of-the box.
15 lines of PHP, (no HTML and no boilerplate code) is enough to build this UI:
Here is full code:
require 'vendor/autoload.php';
$app = new \atk4\ui\App('My App');
$app->initLayout(new \atk4\ui\Layout\Admin());
$db = \atk4\data\Persistence::connect($DSN);
class User extends \atk4\data\Model {
public $table = 'user';
function init() {
parent::init();
$this->addField('name');
$this->addField('email', ['required'=>true]);
$this->addField('password', ['type'=>'password']);
}
}
$app->layout->add(new \atk4\ui\CRUD())
->setModel(new User($db));
You'll need to also run: composer require atk4/ui but that's it.
Consider looking at a framework that comes with prototyping or scaffolding support like CakePHP. Besides PHPMyAdmin, that's probably the fastest way of getting CRUD functionality to work with an existing datastore.
I recommend using the yiiframework. It design is pythonesque like. The Gii generator that comes with Yii will read you DB tables and create all the necessary CRUD code for some simple editing.
http://www.yiiframework.com/
I'm looking for a drop-in admin like this too, here's one I found so far:
http://ajaxcrud.com/