database driven codeigniter navbar - php

I am new with CodeIgniter and have been told that it is the way to go.
I have read the user manual a few times now but don't seem to understand one thing which is I wanted to do a navbar driven from the database. I found a few posts on here saying about a method that I have implemented but no matter what I do, it just doesn't seem to work for me. what I have done so far:
Created a table with :
CREATE TABLE IF NOT EXISTS `app_routes` (
`id` bigint(20) NOT NULL auto_increment,
`slug` varchar(192) collate utf8_unicode_ci NOT NULL,
`controller` varchar(64) collate utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
KEY `slug` (`slug`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1;
Added to route.php file
$route[ 'default_controller' ] = 'home';
$route[ '404_override' ] = 'error404';
require_once( BASEPATH .'database/DB'. EXT );
$db =& DB();
$query = $db->get( 'app_routes' );
$result = $query->result();
foreach( $result as $row )
{
$route[ $row->slug ] = $row->controller;
$route[ $row->slug.'/:any' ] = $row->controller;
$route[ $row->controller ] = 'error404';
$route[ $row->controller.'/:any' ] = 'error404';
}
Set up a controller with:
<?php
class Home extends CI_Controller {
public function index()
{
$this->load->view('smooth/header.php');
$this->load->view('smooth/navbar.php');
$this->load->view('smooth/index.php');
$this->load->view('smooth/footer.php');
}
}
?>
In the database I have under controller home and as page contact
When I visit my site via my domain name only I see the frontpage but if I add the index.php/home to it I get nothing or index.php/home/contact nothing either
The path to my index.php files as situated in my domain/application/views/themes/smooth/index.php
Can anyone help with what I am missing please or what the problem is?

You didn't pass the routes to the view.
Without seeing the view in question I can't tell if there's an issue there, but you need to pass the data through like this:
$this->load->model('yourmodel');
$routes = $this->yourmodel->getRoutes();
$data = array(
'routes' => $routes
);
$this->load->view('smooth/header.php');
The database query goes in a model, so you will need to define that, and a method to return the data - here I've represented that model as yourmodel and the method to call as getRoutes. You should not, under any circumstances, be placing your database query in routes.php.

Related

Cant create table on plugin activation

I am trying to create table on plugin activation, I tried making the same function inside the class and calling it from the constructor, and I tried calling it outside the class and finally i tried to make another php file for calling it using the register_activation_hook, but nothing worked
plugin-code:
<?php
/**
*#package pageauthors
**/
/**
* Plugin Name: Page Authors
* Plugin URI: https://www.localhost.com/plugin
* Description: Allows you to add multiple authors to your wordpress post.
* Version: 1.0.0
* Author: Raphael Eid.
* Author URI: https://www.localhost.com/
* License: GPL v2 or Later
* Text Domain: PageAuthors
*/
$db = mysqli_connect('localhost','x','x','x');
//We can use require_once('../../../wp-config.php');
//mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
defined('ABSPATH') or die('Error my friend');
class pageauthors{
function register(){
//Call the Scripts
add_action('admin_enqueue_scripts', array($this, 'enqueue'));
//Create in the admin function
add_action('admin_menu', array($this, 'add_admin_pages'));
}
public function add_admin_pages(){
//add_menu_page( string $page_title, string $menu_title, string $capability, string $menu_slug, callable $function = '', string $icon_url = '', int $position = null )
add_menu_page('Add Author', 'Add Author', 'manage_options', 'raphaelprefix_plugin', array($this, 'admin_index'), 'dashicons-insert', 110);
}
public function admin_index(){
define( 'MY_PLUGIN_PATH', plugin_dir_path( __FILE__ ) );
include( MY_PLUGIN_PATH . 'templates/index.php');
// include( MY_PLUGIN_PATH . 'index.php');
include( MY_PLUGIN_PATH . 'templates/showAuthors.php');
// require_once plugin_dir_path(__FILE__) . 'templates/index.php';
}
function deactivate(){
global $wpdb;
$table_name = $wpdb->prefix . 'postsauthors';
$sql = "DROP TABLE IF EXISTS $table_name";
$wpdb->query($sql);
delete_option("my_plugin_db_version");
}
function enqueue(){
//Here we can enqueue and we should create the assets (css and js)
wp_enqueue_style('mypluginstyle', plugins_url('/assets/mystyle.css', __FILE__) );
wp_enqueue_script('mypluginstyle', plugins_url('/assets/mystyle.js', __FILE__) );
}
}
if(class_exists('pageauthors')){
$raphplugin = new pageauthors();
$raphplugin->register();
// $raphplugin->activate();
$raphplugin->deactivate();
}
function installer(){
include('installer.php');
}
//Activate - Register Activation Hook(__FILE__, array($instance, function))
register_activation_hook(__FILE__, 'installer');
//Deactivate - Register Deactivation Hook(__FILE__, array($instance, function))
register_deactivation_hook(__FILE__, array($raphplugin, 'deactivate') );
?>
installer.php
<?php
$db = mysqli_connect('localhost','x','x','x');
global $wpdb;
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
if (count($wpdb->get_var('SHOW TABLES LIKE "wp_postsauthors"')) == 0){
$sql = "CREATE TABLE `wp_postsauthors`
( `ID` INT(200) NOT NULL AUTO_INCREMENT , `post_ID` INT(200) NOT NULL ,
`author_name` VARCHAR(200) NOT NULL , `title` VARCHAR(200) NOT NULL ,
`description` VARCHAR(200) NOT NULL , PRIMARY KEY (`ID`)) ENGINE = InnoDB;";
dbDelta($sql);
}
Nothing is working even tho I am typing everything correctly
I'm going to simplify things as much as possible. Activation hooks are always frustrating to debug because of their async-like behavior.
First, you actually don't need to if check on whether the table exists, that's what dbDelta does for you already. You can actually change your schema that's defined in $sql later and dbDelta will attempt to figure that out and handle things automatically for you, too. In the real world, however, I have found that semi-complex table logic doesn't always make it through to an ALTER TABLE. Instead, most people keep track of their schema version and run table upgrades on plugin update. But that's for later.
Second, never assume the WordPress table prefix, that is asking for trouble some day. Instead, always use $wpdb->prefix.
The code below is the smallest version of a plugin that does what you are looking for. Instead of a function in a file, I'm just using a local anonymous function. The bulk of the code is the same as yours, just with some formatting that my IDE does for me automatically. This code is a full plugin which I'd recommend testing first. Once you've confirmed it is working, you should be able to pull the activation logic out. It is not wrong to use another file, I just try to remove as much distraction when I debug things.
<?php
/**
* Plugin Name: Page Authors
*/
register_activation_hook(
__FILE__,
static function () {
global $wpdb;
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
// Never assume the prefix
$table_name = $wpdb->prefix . 'postsauthors';
$sql = "CREATE TABLE `${table_name}`
(
`ID` INT(200) NOT NULL AUTO_INCREMENT ,
`post_ID` INT(200) NOT NULL ,
`author_name` VARCHAR(200) NOT NULL ,
`title` VARCHAR(200) NOT NULL ,
`description` VARCHAR(200) NOT NULL ,
PRIMARY KEY (`ID`)) ENGINE = InnoDB;";
dbDelta($sql);
}
);

Typo3 custom Content Elements cache problem

In Typo3 I have my custom content elements (CEs) defined like so, for example:
CREATE TABLE tt_content
(
my_rich_text_relation int(11) unsigned DEFAULT '0',
);
# Custom CE for displaying rich text.
CREATE TABLE tx_mythemes_rich_text
(
uid int(11) NOT NULL auto_increment,
pid int(11) DEFAULT '0' NOT NULL,
text text,
....
);
And:
lib.myContentElement = FLUIDTEMPLATE
lib.myContentElement {
templateRootPaths.0 = EXT:my_themes/Resources/Private/Templates/ContentElements/
partialRootPaths.0 = EXT:my_themes/Resources/Private/Partials/ContentElements/
layoutRootPaths.0 = EXT:my_themes/Resources/Private/Layouts/ContentElements/
}
tt_content {
my_rich_text >
my_rich_text =< lib.myContentElement
my_rich_text {
templateName = RichText
dataProcessing {
330 = TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor
330 {
table = tx_mythemes_rich_text
pidInList = this
where = uid=
where.dataWrap = |{field:mythemes_rich_text_relation}
as = richText
}
}
}
This works in my local system (Docker image) but I don't know why in our beta platform (where the context is not "development" it doesn't. When I add a new custom CE and refresh the caches, it gets displayed, but as soon as something changes (e.g. I add a new CE to the page), the Template of the CE doesn't get rendered (funny thing: the Layout does get rendered).
What can be happening? This looks so much like a cache problem.
Thanks in advance!

Load url from routes for a controller

As CodeIgniter comes out of the box, it supportes one controller for each unique url.
So, let's say i have the following urls in my routes.php file:
$route['default_controller'] = "homepage";
$route['404_override'] = "homepage/not_found";
$route['^products$'] = "product/list";
$route['^product/(:any)$'] = "product/details";
My urls will look like this:
product list => http://www.mywebsite.com/products
product details => http://www.mywebsite.com/product/my-custom-product
In the controller where I build the products list, I create the url for each product like this:
$this->db->from('products');
$products_result = $this->db->get();
$data['products'] = array();
foreach ($products_result->result() as $row)
{
$data['products'][] = array(
'title' => $row->title,
'image' => $row->image,
'url' => site_url('product/' . $row->url)
);
}
$this->load->view('products/list_view', $data);
But there is too much redundancy for each url. I have to write the url every time I want to echo it somewhere. If I want to change the url, I have to open each php file and replace them all.
Question: Isn't there a "method" I can use to call the controller name and its method and that "method" returns the url for that one? Something like this:
build_site_url('product/details', array('my-product-url'));
where the first argument is the controller and its method (since only one controller exists for a url pattern), and the second argument is the array of url parts.
What you're looking for is a feature called reverse routing. There is no such feature built into CodeIgniter at this time, and any library I could find was done in like 2010, so probably not the most up-to-date.
However, there are articles and pull requests out there relating to reverse routing, so if you are experienced enough, you should be able to put something together for your application.
Otherwise, your best bet may be to create helpers for your most common URLs (like your products). So you could do something like echo product_url('my-product-name');, and you would only need to adjust the URL in the helper function.
I am not sure what exactly that you desired, but you can override controller behaviour using _remap() function;
look: http://ellislab.com/codeigniter/user-guide/general/controllers.html#remapping
e.g.
public function _remap($method){
if ($method == 'product/details') {
///do what you want to do
}
You could either use a default lookup function in the product controller (described in the CI Routing docs; look at the examples).
$route['product/(:any)'] = "catalog/product_lookup";
A URL with "product" as the first segment, and anything in the second
will be remapped to the "catalog" class and the "product_lookup"
method.
Or you could use database driven routes.
Add the table product_slugs to your MySQL database:
CREATE TABLE IF NOT EXISTS `product_slugs` (
`id` bigint(20) NOT NULL auto_increment,
`slug` varchar(192) collate utf8_unicode_ci NOT NULL
PRIMARY KEY (`id`),
KEY `slug` (`slug`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1;
Replace the code in application/config/routes.php with the one below:
$route[ 'default_controller' ] = 'main';
$route[ '404_override' ] = 'error404';
require_once( BASEPATH .'database/DB'. EXT );
$db =& DB();
$query = $db->get( 'product_slugs' );
$result = $query->result();
foreach( $result as $row )
{
$route[ $row->slug ] = 'product/detail/$1;
}
All you would have to do then is to create a record when you create a product entry and you're done:
INSERT INTO `product_slugs` (`slug`) VALUES ('name-of-the-product');

CakePHP data not saving/adding to database

Submitting the data only reloads the page, no errors or messages is given by CakePHP.
The code follows the same/similar structure as the blog tutorial.
The view code
<?php
echo $this->Form->create('Sm');
echo $this->Form->input('recievers', array('rows' => '1'));
echo $this->Form->input('subject');
echo $this->Form->input('message');
echo $this->Form->end('SEND');
?>
Controller code
public function send() {
if ($this->request->is('sm')) {
$this->Sm->create();
if ($this->Sm->save($this->request->data)) {
$this->Session->setFlash('Sms has been added to the database');
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash('Unable to send sms.');
}
}
}
Model code
class Sm extends AppModel {
public $validate = array(
'subject' => array(
'rule' => 'notEmpty'
),
'message' => array(
'rule' => 'notEmpty'
),
'recievers' => array(
'rule' => 'notEmpty'
)
); }
Exported SQL
CREATE TABLE IF NOT EXISTS `sms` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`subject` varchar(150) DEFAULT NULL,
`message` text,
`sender` varchar(50) DEFAULT NULL,
`recievers` text,
`sent` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;
You've specified an incorrect request 'method';
if ($this->request->is('sm')) {
Should be:
if ($this->request->is('post')) {
I suspect you got confused by the examples on CakePHP, which use a 'post' Model. However this line is to check the type of request used to access the page, e.g. post, get, put.
By checking for the right request method, CakePHP will only insert/update the data is the form is sent/submitted, otherwise the form is just shown without updating the database
You forget to define name property inside model.
var $name = 'Sm';
Just a few minutes ago, I was facing same type of problem. My problem was more weird. In my controller I used something like this:
if( $this->MyModel->save( $this->request->data ) ) {
//positive. proceed.....
}
else {
//negative. show error
pr( $this->MyModel->validationErrors );
}
As you can see I've handled the negative case but still I could see nothing. Even in my model, I used beforeSave and afterSave to check. In my beforeSave model, I could see a perfectly formatted array ready to be saved but I afterSave was not triggering which means the data was not saved. Hence I should see error from my controller. Still no solution.
Now this is how I figured out the problem. I checked the table the data is gonna be saved into. The table had lots of columns with NOT NULL attribute. The data I was saving had some fields with NULL values. So theoretically, I should see validationErrors in the controller as a reason but unfortunately it was not showing. Setting those fields nullable solved my problem. So my suggestion to you is to check which fields might have NULL value and set those nullable and make sure the NOT NULL fields have some values.
Hope this helps. Cheers!!!

WP Custom plugin: Create table and insert data once.

This is my complete Wordpress plugin file:
<?php
function wp_create_table_install()
{
global $wpdb;
$table_name = $wpdb->prefix.'createtable';
$sql = 'CREATE TABLE '.$table_name.'(
id INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(75)
);';
require_once(ABSPATH.'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
function wp_create_table_insert_data()
{
global $wpdb;
$table_name = $wpdb->prefix.'createtable';
$id = 1;
$name = 'WP Create Table!';
$wpdb->insert($table_name, array('id' => $id, 'name' => $name));
}
register_activation_hook(__FILE__, 'wp_create_table_install');
register_activation_hook(__FILE__, 'wp_create_table_insert_data');
?>
When I activate the plugin, it always tries to create a table and insert data. How could I do it once, just in the first plugin activation?
Thank you.
A quicker way would be to add [IF NOT EXISTS] in your CREATE statement so that you don't get an error if your table already exists.
Before running CREATE TABLE, you could query information_schema.tables to check to see whether or not the table already exists.
Unfortunately, there's no way to run something on "install" - surprisingly, WordPress doesn't provide any hooks for install as opposed to activation!
The way people cope with this is to set and test an option - if the option is not set, then create the tables, and if it is set do nothing or do a DB upgrade. Options are read in and cached so there is no performance penalty to doing this.
$opt = get_option(MYPLUGIN_OPTIONS);
$opt['dbversion'] = 100;
...
update_option(MYPLUGIN_OPTIONS, $opt);

Categories