I am trying to create dynamic menu using PHP Codeigniter.
There are some Main Menu
Each Main Menu have some Sub_Menu Like, Categories ->Hardware, Software etc.
I somehow made it but there is an issue, the Main menu is showing correctly but the sub menu under main menu is repeating in each Main menu.
This is the image of the issue:
My View Code
<ul class="slimmenu">
<?php foreach($menus as $menu): ?>
<li>
<?php echo $menu -> Menu_Name;?>
<ul>
<?php foreach($submenus as $submenu): ?>
<li>
<?php echo $submenu -> Sub_Menu_Name;?>
</li>
<?php endforeach;?>
</ul>
</li>
<?php endforeach;?>
</ul>
My Controller Code
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class MainSystem extends CI_Controller
{
function __construct() {
parent::__construct();
$this->load->model('menusys','ms');
}
function menu()
{
$this->data['menus'] = $this->ms->get_menu();
$this->data['submenus'] = $this->ms->get_submenu();
$this->load->view('index', $this->data);
}
function add_menu()
{
$data = array(
'Menu_Name' => $this->input->post('mname'),
'Menu_Link' => $this->input->post('mlink'),
);
$this->ms->adm($data);
}
function sub_menu()
{
$this->data['mmenu'] = $this->ms->get_menu();
$this->load->view('submenu', $this->data);
}
function add_submenu()
{
$data = array(
'Main_Menu_Name' => $this->input->post('mmname'),
'Sub_Menu_Name' => $this->input->post('mname'),
'Sub_Menu_Link' => $this->input->post('mlink'),
);
$this->ms->adsm($data);
}
}
?>
My Model Code
<?php
defined('BASEPATH') or exit('no direct script directy allowed');
/**
*
*/
class menusys extends CI_Model
{
public function __construct()
{
parent::__construct();
}
public function adm($data)
{
$this->db->set('Is_Active',0);
$this->db->insert('main_menu',$data);
$this->session->set_flashdata('msg', 'Meun has been added');
redirect('MainSystem/menu');
}
//sub-menu Section
public function get_menu()
{
//$this->db->where('Is_Active',1);
// $this->db->select('*');
// $this->db->from('main_menu');
// $this->db->join('sub_menu', 'main_menu.Menu_Name = sub_menu.Main_Menu_Name','inner');
// $query = $this->db->get();
// return $query->result();
//
$query=$this->db->get_where('main_menu',array('Is_Active'=>1));
return $query->result();
}
function get_submenu()
{
$this->db->where('main_menu.Menu_Name = sub_menu.Main_Menu_Name');
$this->db->select('*');
$this->db->from('sub_menu');
$this->db->join('main_menu', 'main_menu.Menu_Name = sub_menu.Main_Menu_Name','inner');
$query = $this->db->get();
return $query->result();
}
public function adsm($data)
{
$this->db->set('Is_Active',1);
$this->db->insert('sub_menu',$data);
$this->session->set_flashdata('msg', 'Meun has been added');
redirect('MainSystem/menu');
}
}
What I Want: I want that each Sub_Menu will show under his parent menu.
Any help will be appreciated.
UPDATE
This is sub-menu table image.
you need to format your menu array and loop it something like this
$menu = array(
'menu_name_1' => array(
'submenu1_1' => 'www.something.com',
'submenu1_2' => 'www.something.com',
),
'menu_name_2' => array(
'submenu2_1' => 'www.something.com',
'submenu2_2' => 'www.something.com',
)
);
foreach($menu as $menu_name => $submenu){
echo $menu_name.'<br>';
if (!empty($submenu)){
foreach($submenu as $submenu_name => $submenu_link){
echo ''.$submenu_name.'<br>';
}
}
}
You have array with menu names and submenu. First you loop menu name and check dose it has submenu, it if has, you loop submenu and make links.
Related
I am converting a static an html code to wordpress theme, i want to open another page to open when i click on the anchor tag, how do i go about it. Thanks.
<li>About Us</li>
In WordPress, links are permalinks:
Permalinks are the permanent URLs to your individual weblog posts, as
well as categories and other lists of weblog postings.
Original link: https://wordpress.org/support/article/using-permalinks
When creating a theme, you must display the links that are available in the admin panel: Admin panel -> Appearance -> Menus
The menu consists of locations, location is the place in the template where the user menu is displayed
I created a mini plugin for you that allows you to create custom menus and display them anywhere
Plugin structure:
wp-content\plugins\unbywyd-custom-menus
wp-content\plugins\unbywyd-custom-menus\unbywyd-custom-menus.php
wp-content\plugins\unbywyd-custom-menus\templates
wp-content\plugins\unbywyd-custom-menus\templates\navbar.hbs
wp-content\plugins\unbywyd-custom-menus\partials
wp-content\plugins\unbywyd-custom-menus\partials\menu_item.hbs
wp-content\plugins\unbywyd-custom-menus\partials\handlebars
wp-content\plugins\unbywyd-custom-menus\partials\handlebars\{library: https://github.com/zordius/lightncandy}
My example will be complete and working so that you can create any custom menus in WordPress. I will use the handlebars template engine to make things easier.
And so the contents of the unbywyd-custom-menus.php file:
<?php
/*
Plugin Name: Unbywyd custom menus
Version: 0.1
Author: Unbywyd
Author URI: unbywyd.com
*/
/*
* We will use the Handlebars template engine
*/
if(!class_exists('LightnCandy\LightnCandy')) {
require_once ("handlebars/autoload.php");
}
use LightnCandy\LightnCandy;
define('UCMS_DIR', plugin_dir_path(__FILE__));
class unbywydCustomMenus {
public $menus = [];
function __construct($menus=array()) {
$this->menus = $menus;
add_action('init', array($this, 'init'));
/*
* Create use_custom_menu shortcode
* You can use [use_custom_menu location="navbar"] in wordpress posts to display navbar menu
* And also for using from php <php print do_shortcode('[use_custom_menu location="navbar" customparam="test" class="test"]'); ?>
*/
add_shortcode( 'use_custom_menu', array($this, 'use_custom_menu'));
}
function use_custom_menu($attrs) { // Create shortcode handler
if(!isset($attrs['location'])) {
$attrs['location'] = '';
}
return $this->get_nav($attrs['location'], $attrs);
}
function get_template( $template_name ) { // Get a template by its name from templates/ directory
$path_to_file = wp_normalize_path(UCMS_DIR . 'templates/' . $template_name . '.hbs');
if(!file_exists($path_to_file)) {
return '';
}
return file_get_contents($path_to_file);
}
function get_handlebars_partials() { // Get all partials from partials/ directory
$path_to_partials = wp_normalize_path(UCMS_DIR . 'partials/');
if(!file_exists($path_to_partials)) {
return array();
}
$list_files = scandir($path_to_partials);
$partials = array();
foreach($list_files as $path) {
$path_to_file = wp_normalize_path($path_to_partials . '/'. $path);
if(is_file($path_to_file)) {
$ext = pathinfo($path_to_file, PATHINFO_EXTENSION);
if($ext == 'hbs') {
$partials[pathinfo($path, PATHINFO_FILENAME)] = function($name, $context) use($path_to_file) {
return $this->prepare_template(file_get_contents($path_to_file))($context, array('partials' => $this->get_handlebars_partials()));
};
}
}
}
return $partials;
}
function get_handlebars_helpers() {
return array(
/*
* You can use debug helper to display the incoming data into the template
* {{{debug}}}
*/
'debug' => function($context, $options=array()) {
if(!current_user_can('editor') && !current_user_can('administrator')) {
return '';
}
return '<pre class="debug" dir="ltr" style="text-align:left !important;">'.json_encode($context['data']['root'], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE).'</pre>';
}
);
}
// You can use this function to render any of your templates from /template directory
function template_render($template_name, $data) {
$prepared_template = $this->prepare_template($this->get_template( $template_name ));
$partials = $this->get_handlebars_partials();
return $prepared_template($data, array('partials' => $partials));
}
function prepare_template($template) {
$template = do_shortcode($template);
$prepared = LightnCandy::compile($template, array(
'flags' => LightnCandy::FLAG_HANDLEBARSJS | LightnCandy::FLAG_ADVARNAME | LightnCandy::FLAG_RUNTIMEPARTIAL | LightnCandy::FLAG_ERROR_SKIPPARTIAL,
'helpers' => $this->get_handlebars_helpers()
));
return LightnCandy::prepare($prepared);
}
function init() {
/*
* Registering custom menu locations
*/
foreach($this->menus as $menu) {
register_nav_menu($menu['id'], $menu['label']);
}
}
function build_tree(Array $data, $parent = 0) {
$tree = array();
foreach ($data as $d) {
if ($d['parent'] == $parent) {
$children = $this->build_tree($data, $d['id']);
if (!empty($children)) {
$d['children'] = $children;
}
$tree[] = $d;
}
}
return $tree;
}
// Get generated HTML of navigation
function get_nav( $location, $other_params=array() ) {
$menu_data = $this->get_nav_menu_items_by_location($location);
if(empty($menu_data)) {
return 'You can do nothing, or you can display a notification that there are no links in the menu';
} else {
return $this->template_render($location, array_merge($other_params, array('menu' => $menu_data)));
}
}
// Simple handler to build data of custom navigation
function get_nav_menu_items_by_location( $location, $args = [] ) {
$locations = get_nav_menu_locations();
if(!isset($locations[$location])) {
return array();
}
$object = wp_get_nav_menu_object( $locations[$location] );
if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
$link = "https";
} else {
$link = "http";
}
$link .= "://";
$link .= $_SERVER['HTTP_HOST'];
$link .= $_SERVER['REQUEST_URI'];
if(!$object) {
return array();
}
$menu_items = wp_get_nav_menu_items( $object->name, $args );
if(!$menu_items) {
return array();
} else {
$menu = array();
foreach( $menu_items as $i) {
$data = array(
'url' => $i->url,
'id' => $i->ID,
'parent' => $i->menu_item_parent,
'title' => $i->title,
'active' => $i->url == $link || $i->url . '/' == $link,
'attr_title' => $i->attr_title,
'description' => $i->description,
'class' => implode(' ', $i->classes)
);
if(!empty($i->target)) {
$data['target'] = $i->target;
}
$menu[] = $data;
}
return $this->build_tree($menu);
}
return $menu_items;
}
}
/*
* Сreate our custom menus
* Of course, you can add this complexity and bring it up to the plugin settings and display it in the wordpress admin panel as option page.
*/
new unbywydCustomMenus(
[
['id' => 'navbar', 'label' => 'Navbar menu'],
['id' => 'footer', 'label'=> 'Menu in footer']
]);
First you call the plugin class and pass your custom menus to register them:
new unbywydCustomMenus(
[
['id' => 'navbar', 'label' => 'Navbar menu'],
['id' => 'footer', 'label'=> 'Menu in footer']
]);
Then you can customize the menus in the admin panel and add them to your locations
Admin panel -> Appearance -> Menus | Manage Locations
and now you can display your menu anywhere in the post using a shortcode:
[use_custom_menu location="navbar" customparam="test" class="test"]
You will also be able to display it programmatically using php:
<php print do_shortcode('[use_custom_menu location="navbar" customparam="test" class="test"]'); ?>
Link to GutHub with working plugin
You could just put in the static URL https://www.website.com/about but that will change if you move the about page into another folder. To keep this dynamic, you can use the wordpress function get_page_link() (if you have the page id) or get_permalink and get_page_by_path if you have the slug. The about page will need to be created in the database first so you can get these parameters.
Using page ID: (ex: page ID is 40)
<li>About Us</li>
Using slug: (ex: slug is 'about-us')
<li>About Us</li>
You can also get it using the page title, though this might change over time so I don't recommend it:
<li>About Us</li>
More information about retrieving links dynamically here: https://code.tutsplus.com/tutorials/why-you-shouldnt-code-urls-in-wordpress-themes-or-plugins--cms-23262
I use basic mode on Yii2 framework. I create two controllers - SiteController and CategoryController. I have two folders with few views - site (index and about) and category (category and search).
When i render view by SiteController evething is ok, but when i render view by CategoryController actionSearch - do not call main.php and do not show any html in view, but if i call die - the results is there.
Here is a code:
model:
namespace app\models;
use yii\db\ActiveRecord;
class Categories extends ActiveRecord
{
public static function tableName()
{
return 'categories';
}
public function getProducts(){
return $this->hasMany(Products::className(), ['category_id' => 'id']);
}
}
and CategoryController:
public function actionSrch() {
$cat = Categories::findOne(1);
$q = Yii::$app->request->get('q');
if(isset($q) and $q!=''){
$query = Products::find()->where(['like', 'title', $q]);
// pagination
$pages = new Pagination([
'totalCount' => $query->count(),
'pageSize' => 4,
'forcePageParam' => false,
'pageSizeParam' => false ]);
$products = $query->offset($pages->offset)->limit($pages->limit)->all();
}else{
$products = Products::find()->where('title<>:title', [':title'=>''])->all();
}
$this->render('search', compact('products','pages', 'q', 'cat'));
}
and the Search form:
<div class="col-sm-3">
<div class="search_box pull-right">
<form action="<?= \yii\helpers\Url::to(['categories/search']) ?>" method="get">
<input type="text" placeholder="Search" name="aaa">
</form>
</div>
</div>
and the view in search.php
use yii\helpers\Html;
use yii\helpers\Url;
use yii\widgets\LinkPager;
<ul class="catalog category-products">
<?= \app\components\MenuWidget::Widget(['tpl' => 'menu']) ?>
</ul>
<div class="col-sm-9 padding-right">
<div class="features_items"><!--features_items-->
<?php if(!empty($products)): ?>
<?php $i = 0; foreach($products as $prd): ?>
<h2><?= $prd->price ?></h2>
<?php endif; ?>
<?php endforeach; ?>
<?php else :?>
<div class="alert alert-danger">Do not have products!!!</div>
<?php endif; ?>
First chack your action name actionSrch or actionSearch.
And add return before render file like below.
public function actionSrch() {
$cat = Categories::findOne(1);
$q = Yii::$app->request->get('q');
if(isset($q) and $q!=''){
$query = Products::find()->where(['like', 'title', $q]);
// pagination
$pages = new Pagination([
'totalCount' => $query->count(),
'pageSize' => 4,
'forcePageParam' => false,
'pageSizeParam' => false
]);
$products = $query->offset($pages->offset)->limit($pages->limit)->all();
}else{
$products = Products::find()->where('title<>:title', [':title'=>''])->all();
}
return $this->render('search', compact('products','pages', 'q', 'cat'));
}
Refere Yii2 Base Actions and Yii2 Render()
How to load a control inside a controller prestashop?
Opencart support load controller inside the controller
$data['efgh'] = $this->load->controller('abcd/efgh');
So prestashop that support it? If yes then how?
i have a controller Category render custom tpl
public function renderList(){
$tpl = $this->createTemplate('dashboard.tpl');
// Category
$categories = GenCategory::getCategories();
$public_categories = GenCategory::getPublicCategories();
$unpublic_categories = GenCategory::getUnpublicCategories();
$tpl->assign(array(
// Category
'categories' => $categories,
'public_categories' => $public_categories,
'unpublic_categories' => $unpublic_categories,
));
return $tpl->fetch();
}
and controller Menu render custom tpl
public function renderList(){
$tpl = $this->createTemplate('menu.tpl');
$menu = GenMenu::getMenu();
$tpl->assign(array(
'menu' => $menu,
));
return $tpl->fetch();
}
I need show Menu inside Category.
I'll suggest you to use the initContent() method, and not the renderList, in this way:
public function initContent(){
// Category
$categories = GenCategory::getCategories();
$public_categories = GenCategory::getPublicCategories();
$unpublic_categories = GenCategory::getUnpublicCategories();
// Menu
$menu = $this->genMenu();
$this->context->smarty->assign(array(
// Category
'categories' => $categories,
'public_categories' => $public_categories,
'unpublic_categories' => $unpublic_categories,
// Menu
'menu' => $menu
))
$this->setTemplate(`rightdirectoryofyourtpl`.'dashboard.tpl');
}
public function genMenu(){
$menu = GenMenu::getMenu();
$this->context->smarty->assign(array(
'menu' => $menu,
));
return $this->context->smarty->fetch(`directoryofyourtpl`/menu.tpl)
}
Then in your tpl simply 'print' the $menu var
Issue/Question: I'm using CodeIgniter to build an event calendar, and I have included a sharing option. This option works at a base level, but only displays the users' ID (primary key) in an <ul>. This isn't ideal, and I would like to show the users' first and last names in the <ul> instead. I thought creating an associative array would work, but I'm receiving funky results. The first and last name echo out as "Array Array" when the page loads, and the URL id comes up as "Array" when you select the "Array Array" link. I'm wondering what is wrong in my logic.
Funky link generated in view:
Array Array
Funky URL that is linked to "Array Array":
http://example.com/user/shared/view/Array
Modified Controller:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Shared extends Common_Auth_Controller {
private $end_user;
public function __construct()
{
parent::__construct();
$this->end_user = $this->ion_auth->user()->row();
$data['end_user'] = $this->end_user;
$this->load->vars($data);
$this->load->model('events_model', 'events');
}
public function index()
{
$title['title'] = 'Shared';
$this->load->model('shared_model','shared');
$data['sharers'][] = array(
'shared_owner_id' => $this->shared->get($this->end_user->id),
'owner_first_name' => $this->shared->get($this->end_user->first_name),
'owner_last_name' => $this->shared->get($this->end_user->last_name),
);
$this->load->view('public/head_view', $title);
$this->load->view('user/header_view');
$this->load->view('user/shared_view', $data);
$this->load->view('user/footer_view');
}
Modified View:
<div class="hide-on-phones">
<ul>
<?php foreach($sharers as $key => $value): ?>
<li><?php echo $value['owner_first_name']." ".$value['owner_last_name'] ?></li>
<?php endforeach; ?>
</ul>
</div>
Model:
class Shared_model extends crud_model {
public function __construct()
{
parent::__construct();
$this->pk = 'id';
$this->table_name = 'shared';
}
public function get($shared_to_user_id)
{
$this->db->where('shared_to_id', $shared_to_user_id);
$ids = parent::get_all();
$users = array();
foreach ($ids as $id)
{
$users[] = $id->owner_id;
}
return $users;
}
}
Thank you so much for your help, and let me know if there is any more information that may be required. Below are the original view and controllers that work, but are not preferable.
Original Controller:
public function index()
{
$title['title'] = 'Shared';
$this->load->model('shared_model','shared');
$data['sharers'] = $this->shared->get($this->end_user->id);
$this->load->view('user/head_view', $title);
$this->load->view('user/header_view');
$this->load->view('user/navigation_view');
$this->load->view('user/shared_view', $data);
$this->load->view('user/footer_view');
}
Original View:
<?php foreach($sharers as $s): ?>
<li><?php echo $s ?></li>
<?php endforeach; ?>
Disclaimer: I'm new to web development, and I suck at associative arrays (apparently).
Your $data['sharers'] array doesn't have arrays as $values. Therefore, the way you are calling the $value[]'s in your foreach aren't working. You have no reason for calling the foreach at this point.
<div class="hide-on-phones">
<ul>
<li><a href="<?=base_url('user/shared/view/'.$sharers['shared_pk_id'])?>">
<?=$sharers['first_name'] . ' ' . $sharers['last_name']?>
</a>
</li>
</ul>
</div>
I expect you will later on fill an array with the data, in which case you can fill it as
$data['sharers'][] = array(
'shared_pk' => $this->shared->get($this->end_user->id),
'first_name' => $this->events->get($this->end_user->first_name),
'last_name' => $this->events->get($this->end_user->last_name)
);
Which, in turn can be looped using
<div class="hide-on-phones">
<ul>
<? foreach($sharers as $sharer): ?>
<li>
<a href="<?=base_url('user/shared/view/' . $sharer['shared_pk'])?>">
<?=$sharer['first_name'] . ' ' . $sharer['last_name']?>
</a>
</li>
<? endforeach; ?>
</ul>
</div>
I've figured it out. I needed to create an associative array in my model; not my controller. Thanks to everyone for your help!
Model:
class Shares_model extends crud_model {
public function __construct()
{
parent::__construct();
$this->pk = 'id';
$this->table_name = 'shares';
}
public function get($shared_to_user_id)
{
$this->db->where('shared_to_id', $shared_to_user_id);
$ids = parent::get_all();
$users = array();
foreach ($ids as $id)
{
$users[$id->owner_id]['owner_id'] = $id->owner_id;
$users[$id->owner_id]['owner_first_name'] = $id->owner_first_name;
$users[$id->owner_id]['owner_last_name'] = $id->owner_last_name;
}
return $users;
}
}
View:
<ul>
<?php foreach($sharers as $s): ?>
<li><?php echo $s['owner_first_name']." ".$s['owner_last_name'] ?></li>
<?php endforeach; ?>
</ul>
Controller:
public function index()
{
$title['title'] = 'Shared';
$this->load->model('shares_model','shares');
$data['sharers'] = $this->shares->get($this->end_user->id);
$this->load->view('public/head_view', $title);
$this->load->view('user/header_view');
$this->load->view('user/shared_view', $data);
$this->load->view('user/footer_view');
}
If we take your $data['sharers'] array and put in values for the php, then we would get something like this:
$data['sharers'] = array(
0 => array(
'id' => 1234,
'first_name' => 'John',
'last_name' => 'Doe'
),
1 => array(
'id' => 1235,
'first_name' => 'Jane',
'last_name' => 'Doe'
)
);
So, when you loop through this in your view, you need to access these correctly:
foreach($sharers as $key => $value):
// at this point, in the first iteration of the loop
// $key is 'id', or 'first_name', or 'last_name'
// and $value is 1234, or 'John', or 'Doe'
endforeach;
So, to loop through the sharers a bit easier, you just need to update your foreach a bit. At this point, change your view to this:
<div class="hide-on-phones">
<ul>
<?php foreach($sharers as $sharer): ?>
<li>
<a href="<?php echo base_url('user/shared/view/'.$sharer['shared_pk_id']) ?>">
<?php echo $sharer['first_name']. " " .$sharer['last_name'] ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
I am having difficulties implementing the codeigniter pagination class. I have created my model, view and controller for getting my news articles and data is echoed in the view successfully.
My problem is that when I attempt to implement pagination it seems like I am unable to get the correct count of fields in my database. Can somebody show me what I have done wrong?
The pagination links display perfectly, but the content echoed does not appear to be limited. How can I count the rows of the query?
Required classes for the pagination are autoloaded
Model:
class News_model extends CI_model {
function get_allNews()
{
$query = $this->db->get('news');
foreach ($query->result() as $row) {
$data[] = array(
'category' => $row->category,
'title' => strip_tags($row->title),
'intro' => strip_tags($row->intro),
'content' => truncate(strip_tags( $row->content),200),
'tags' => $row->tags
);
}
return $data;
}
Controller
// load pagination class
$config['base_url'] = base_url().'/news/index/';
$config['total_rows'] = $this->db->get('news')->num_rows();
$config['per_page'] = '5';
$config['full_tag_open'] = '<div id="pagination">';
$config['full_tag_close'] = '</div>';
$this->pagination->initialize($config);
$viewdata['allnews'] = $this->News_model->get_allNews($config['per_page'],$this->uri->segment(3));
View
<?php if (isset($allnews)): foreach ($allnews as $an): ?>
<?php echo heading($an['title'], 2); ?>
<?php echo $an['content']; ?>
<?php endforeach;
else: ?>
<h2>Unable to load data.</h2>
<?php endif; ?>
<?php echo $this->pagination->create_links(); ?>
In your controller, you're passing parameters to your get_allNews method, but your method doesn't make use of those parameters:
$viewdata['allnews'] = $this->News_model->get_allNews($config['per_page'],$this->uri->segment(3));
So you are getting all records, and expecting the limited result set. You need to change the beginning of your get_allNews method like this:
class News_model extends CI_model {
// make use of the parameters (with defaults)
function get_allNews($limit = 10, $offset = 0)
{
// add the limit method in the chain with the given parameters
$query = $this->db->limit($limit, $offset)->get('news');
// ... rest of method below