I am using CodeIgniter 2.0 for the first time to create a multilingual site where the home page contains a slide show. I am developing it on my laptop - localhost/website/.
I am using the routes.php file to specify which language function to call to set variables depending on the url with format http://localhost/website/language/page_id/some-page-title. Thus http://localhost/website/en/1/Home-Page gives the english page of page_id 1.
Routes file therefore has:
$route['default_controller'] = "content";
$route['en/(:num)/(:any)'] = "content/en/$1";
$route['de/(:num)/(:any)'] = "content/de/$1";
$route['es/(:num)/(:any)'] = "content/es/$1";
etc
An example of a language function (the en function) in the content controller is:
public function en ($page_id) {
$language="en";
$lang_array['css']="base.css";
$this->get_content($page_id, $lang_array);
}
The get_content function then does everything.
The index function of the content controller however looks like this:
public function index() {
//setting defaults for when arrive straight at home page or with no language in url
$page_id=1;
$lang_array['language']="en";
$lang_array['css']="base.css";
$this->get_content($page_id, $language);
}
My problem is that when I go to http;//localhost/website/ everything works fine including the slideshow. However, when i go to the url http://localhost/website/en/1/Home-Page everything works except the pictures in the slideshow dont appear (even though they are both executing the same code and the html output is the same when i look at view source on the page).
The only thing i could think of is the fact that if i just put http;//localhost/website/ then the index function will be called which activates the constructor, but if i put http://localhost/website/en/1/Home-Page then the index and thus constructor are bypassed. However dont know why therefore other things still work but pic slideshow doesn't. Is this the reason do you think? any solutions?
Thanks
TOm
What I could think is some sort of JavaScript error on an undefined variable, possible related to the $lang_array['language'] not being set.
In the index, you set the key to default to 'en',
public function index() {
//setting defaults for when arrive straight at home page or with no language in url
$page_id=1;
$lang_array['language']="en";
$lang_array['css']="base.css";
$this->get_content($page_id, $language);
}
but in the en method, you did not
public function en ($page_id) {
$language="en";
$lang_array['css']="base.css";
$this->get_content($page_id, $lang_array);
}
Since they look pretty much the same, you should abstract the identical behavior into a private function, or perhaps modify the route to send the language as a param to a single function.
Related
I'm posting this after my hair has been ripped out, ran out of rum, and tried everything I can find on google. I've been developing a site using codeigniter which makes use of templates. I've built the backend first and all is working properly there. So now i've started on getting the front end working which is where I'm hitting the issue.
I've created a controller called pages.php which is going to parse the uri string of the current page, use my library to get the page data from the database, then display it. My pages are all created through an editor on the back end and stored in the database.
So here's the pages controller
class Pages extends CI_Controller {
public function __construct()
{
parent::__construct();
$this->load->library("pages");
}
public function display_page()
{
$page_slug = $this->uri->segment(1);
$data["joes"] = "Here's joes first variable";
$this->pages->get_page($page_slug);
}
}
and here's the error message i get when i hit my url like this demo.mydomain.com/joes-test
and here is how my routes are set up. $route['(:any)'] = 'pages/display_page';
My Pages.php library works perfect on the back end but it's a large file. I've only posted the get_page function below. If you need to see everything let me know. But i dont believe the issue has anything to do with the library itself.
public function get_page($slug){
$objPages = new pages();
$objPages->get_object('slug="'.$slug.'"');
return $objPages;
}
[EDIT] If i place the following inside my homepage controller it works. But the calling function needs to be inside the library.
$this->load->library('pages');
$the_page = $this->pages->get_page("joes-test");
I want to call $this->get_object("joes-test") but this doesn't work. get_object() is an inherited function inside the library.
Now oddly enough. The code i put above will NOT work if i do the exact same thing inside the pages controller
any help leading to a solution would be awesome. I'm under a time crunch and pay to get some assistance. Thanks in advance.
No you can't use the same name with controller and library. please choose another name. for example Mypages for you controller name.
change your routes
$route['(:any)'] = 'mypages/display_page';
then call your controller.
http://demo.mydomain.com/joes-test
I think there nothing wrong with library uri, because as codeigniter official website say: This class is initialized automatically by the system so there is no need to do it manually.
I don't know about lib pages, but how about use
$this->load->view(<file-html>);
and if you want to passing data in variable, you can add variable like this
$this->load->view(<file-html>, $data);
Hope this help, Cheers
Hello.
In Yii1.1 i could make an action in siteController and then using: Yii::app()->controller->createUrl('actionname', array('language'=>'new language to toggle'));
It was possible to me to create hiperlinks with CHTML in index file and when clicked those hiperlinks changed the entire tranlations of the website from Portuguese to other language and all way around.
Now i'm beginning with Yii2 and controller does not have createUrl() anymore. Also the other methods dont work that way. I tried run, runAction, tried with the Url:: class and nothing.
Also, in Yii2 making <?php echo Html::a('Portuguese', Yii::$app->language = "pt"); ?>
Doesn't do anything !!! When clicked the hyperlink does not change the language of the site.
Does anyone know how to create an hiperlink or some other way in Yii 2 that toggles completely the entire website language. I need to have two versions of this website -> English and Portuguese.
I need to perform like this -> when click in the english word it will translate to English, and when click the portuguese word it will change the site to Portuguese language.
Any Ideas ??
Many thanks in advance.
NEW EDIT TO THE QUESTION
I wrote this code in my siteController, and now the sites toggles languages, but only on second mouse click the toggle happens and the content is refreshed. Anybody knows why?
Here are my actions
public function beforeAction($action) {
if (Yii::$app->session->has('lang')) {
Yii::$app->language = Yii::$app->session->get('lang');
} else {
Yii::$app->language = 'us';
}
return parent::beforeAction($action);
}
public function actionLangus(){
Yii::$app->session->set('lang', 'us'); //or $_GET['lang']
return $this->render('index');
}
public function actionLangpt(){
Yii::$app->session->set('lang', 'pt'); //or $_GET['lang']
return $this->render('index');
}
I opted for render('index'), because redirect was not finding the view to display.
Many thanks for a solution...
You can do like below in Yii2:
\yii\helpers\Html::a('Change Language',\yii\helpers\Url::toRoute(['controller/action',['language'=>'NEW_LANGUAGE']]));
\yii\helpers\Html::a('Change Language',['controller/action',['language'=>'NEW_LANGUAGE']]);
Or:
use yii\helpers\Html;
use yii\helpers\Url;
Html::a('Change Language',Url::toRoute(['controller/action',['language'=>'NEW_LANGUAGE']]));
Html::a('Change Language',['controller/action',['language'=>'NEW_LANGUAGE']]);
Then, in your action, you need to do:
//validation
Yii::$app->language= "NEW_LANGIAGE";
// store current language using state or cookie or database
UPDATE
action code:
//please put some validation on $_GET['lang']
Yii::$app->session->set('lang', 'us'); //or $_GET['lang']
$this->redirect('controller/action'); // redirecting user to somewhere
Then in your controller's beforeAction:
public function beforeAction($action) {
if (Yii::$app->session->has('lang')) {
Yii::$app->language = Yii::$app->session->get('lang');
} else {
//or you may want to set lang session, this is just a sample
Yii::$app->language = 'us';
}
return parent::beforeAction($action);
}
By above code, in every action, it checks whether the language is set in session or not. If yes, it changes the language. If not, it sets language to us as default. In your change language action, it just sets the new language, which, is given from $_GET request, into the session. Then it redirects user to another page.
Please note that, this is just a suggestion, others might use different ways, such as creating a bootstrap component, using controller init() method, storing lang into cookie or database and so on.
I'm assuming it's one of the app layout files - I want to write a hook in my mobile template to pull a different CMS homepage.
Edit: To clarify, I want to achieve having a different cms page pulled for the hompage of a mobile version of the store vs. the desktop version. Since you can only set one default CMS page in magento admin, seems like there needs to be some custom coding in the mobile template files.
One of the things I love about Magento is the ability to accomplish a lot of things, just by playing with layout files.
I'll refer to Alan Storm's image to illustrate how I accomplished this exact task without having to change code (I hope you don't mind Alan).
As you can see with the image above, the Full Action Name is cms_index_index. You can find this information with debugging tools, like Commerce Bug.
As we have the action name, we can change the layout files to point to a mobile-specific home page. In this method the mobile-specific home page is actually a static block.
Once you have set up your mobile-specific content, you can add the following to your mobile template local.xml file, to use this block for your home page:
<cms_index_index>
<block type="cms/block" name="cms_page"><action method="setBlockId"><block_id>mobile_home</block_id></action></block>
</cms_index_index>
In this case I have set up a mobile_home static block. It will use the same layout name as the desktop home page, but this has already been overridden in the mobile template.
This may not be the best way, but it doesn't involve code changes.
It's probably not as straight forward as you'd like, but here's how this works.
The request for the homepage is routed to the indexAction method of the Mage_Cms_IndexController class.
If you take a look at the indexAction method you can see Magento uses the renderPage method of the cms/page helper object to render the contents of the page
#File: app/code/core/Mage/Cms/controllers/IndexController.php
public function indexAction($coreRoute = null)
{
$pageId = Mage::getStoreConfig(Mage_Cms_Helper_Page::XML_PATH_HOME_PAGE);
if (!Mage::helper('cms/page')->renderPage($this, $pageId)) {
$this->_forward('defaultIndex');
}
}
The $pageId is pulled from Magento's system configuration, and is the URL identifier of the CMS page.
If you hop to the renderPage method
#File: app/code/core/Mage/Cms/Helper/Page.php
public function renderPage(Mage_Core_Controller_Front_Action $action, $pageId = null)
{
return $this->_renderPage($action, $pageId);
}
it wraps the call to the protected _renderPage method. If you hop to THAT method, the page loading code is the following portions.
#File: app/code/core/Mage/Cms/Helper/Page.php
protected function _renderPage(Mage_Core_Controller_Varien_Action $action, $pageId = null, $renderLayout = true)
{
$page = Mage::getSingleton('cms/page');
//...
if (!$page->load($pageId)) {
return false;
}
//...
}
This loads the CMS Page object for the homepage. Notice the model is a singleton, which means other code that instantes the singleton later will have the same page. After this, standard Magento page rendering happens. Possibly relevant to your interests, the content layout blocks end up looking like this
Meaning the block HTML for the CMS page is rendered by the following code in Mage_Cms_Block_Page
#File: app/code/core/Mage/Cms/Helper/Page.php
protected function _toHtml()
{
/* #var $helper Mage_Cms_Helper_Data */
$helper = Mage::helper('cms');
$processor = $helper->getPageTemplateProcessor();
$html = $processor->filter($this->getPage()->getContent());
$html = $this->getMessagesBlock()->toHtml() . $html;
return $html;
}
The getPage method instantiates the same singleton we mentioned above. The other code is what replaces CMS page {{...}} directives with their actual content.
If I was approaching this project, I'd consider a class rewrite for the Mage_Cms_Model_Page object that looks something like this.
public function load($id, $field=null)
{
if( ... is mobile site ... AND ... $id is for the home page ...)
{
$id = ... ID of the mobile site, hard coded or pulled from custom config ...;
}
return parent::load($id, $field);
}
There's also the cms_page_render event which fires after the page has loaded in the _renderPage method. You could try reloading the passed in page object with a different ID in the observer. You could also consider something in the model_load_after or model_load_before events — although that gets trickier to do since you can't directly change the ID.
For code that's not going to leave a single client's system, I usually opt for the rewrite these days, since it's quicker (less expensive for clients) and has less complications (i.e. getting at and changing the information you need) during development. The trade-off is a possible future conflict with someone else who's rewriting the class.
Your milage/philosophy may vary.
Good luck!
I have a page /discussion and I want to implement pagination in it. Now, I want that for the first time the page should load as /discussion, which means that this act as if it was /discussion/page/1. For the other page the url will be /discussion/page/$pagenumber.
Now, the problem is index(). Normally, I initialize all the page data in the index() and then load the view with the initialized data. But, here I’ll have to initialize default page stuff in index() and then the pagination stuff in page(). So, is there a way of sending another set of data from page() to the view? I don’t want to load the view since it will be loaded by the index().
However, I think it is not possible to do what I mentioned above. So, maybe I should keep my index() empty and do all the initialization in the page() and then load the view there. What do you say?
You don't need both the "page" and "index" methods, just use a route.
Using an index() method and dropping the page() method:
$route['discussion/page/(:num)'] = 'discussion/index/$1';
/discussion still gives you page 1, requesting discussion/page/32 will map to discussion/index/32
This assumes you're grabbing the page number as an argument (url segment), like so:
function index ($page = 1) {}
If you are doing something else, a route is still appropriate, maybe just not the one provided.
I suggest to have a look at PEAR's awesome Pager package. It automatically generates a pager and gives you the correct indexes depending on the (GET) input variables.
It sounds like you're trying to have your page method decorate your index method. Without knowing more about the overall structure of the controller, there really isn't terribly much to say, but it sounds like the below will help:
function page( $pos )
{
$this->index( $pos );
}
// a default parameter lets you ensure that this does not neet to have a page set.
function index( $pos = 0 )
{
// when calling the DB (I'm guessing that is where the pagination really happens)
// COUNT should be defined in the config if possible.
$this->db->where/*... add more here...*/->limit( COUNT, $pos );
}
Realistically, you should look into your URI routing class or using the _resolve method, but this should do what you need it to.
I'm not quite sure what your problem is.
If you have a index() method you can set all the pagination information there, remember you have to tell the pagination library which uri segment will be using to get the page number, and that doesn't have anything to do with the index().
There is no page() method in the controller, all of the pages are the same index() with a different set of paginated data, given by the uri_segment defined as the page number, that means all the stuff that is not related to the paginated queryset are intact through the pages.
I am currently working on CMS for a client, and I am going to be using Codeigniter to build on top of, it is only a quick project so I am not looking for a robust solution.
To create pages, I am getting to save the page details and the pull the correct page, based on the slug matching the slug in the mysql table.
My question is however, for this to work, I have to pass this slug from the URL the controller then to the model, this means that I also have too have the controller in the URL which I do not want is it possible to remove the controller from the URL with routes?
so
/page/our-story
becomes
/our-story
Is this possible
I would recommend to do it this way.
Let's say that you have : controller "page" / Method "show"
$route['page/show/:any'] = "$1";
or method is index which I don't recommend, and if you have something like news, add the following.
$route['news/show/:any'] = "news/$1";
That's it.
Yes, certainly. I just recently built a Codeigniter driven CMS myself. The whole purpose of routes is to change how your urls look and function. It helps you break away from the controller/function/argument/argument paradigm and lets you choose how you want your url's to look like.
Create a pages controller in your controllers directory
Place a _remap function inside of it to catch all requests to the controller
If you are using the latest version of CI 2.0 from Bitbucket, then in your routes.php file you can put this at the bottom of the file: $routes['404_override'] = "pages"; and then all calls to controllers that don't exist will be sent to your controller and you then can check for the presence of URL chunks. You should also make pages your default controller value as well.
See my answer for a similar question here from a few months back for example code and working code that I use in my Codeigniter CMS.
Here's the code I used in a recent project to achieve this. I borrowed it from somewhere; can't remember where.
function _remap($method)
{
$param_offset = 2;
// Default to index
if ( ! method_exists($this, $method))
{
// We need one more param
$param_offset = 1;
$method = 'index';
}
// Since all we get is $method, load up everything else in the URI
$params = array_slice($this->uri->rsegment_array(), $param_offset);
// Call the determined method with all params
call_user_func_array(array($this, $method), $params);
}
Then, my index function is where you would put your page function.