Im trying to get the layered navigation of a category links from a php that is outside magento.
I can create all of the category html, but the problem is that the layered links are created with the params of frontcontroller (at the same way of the toolbar links).
If i have a filter selected the creation of layered links doesnt take account of it, and also the layered links havent the category url...
I try to recreate the frontcontroller of the category page inside magento on my php ouside that, but i haven success... Even i recreate the $_SERVER, but the controller seems to not find a router...
In the php if i use mage::run, it do the operation of calcule correctly but mage::run makes the response and isnt i want because i need an xml output only of layered navigation.
If i use mage::app i can get the category html, but the controler isnt calculated correctly although is the same $_SERVER[request_uri] and havent correct links. The front controller havent action...
In the frontcontroller request i see two differences: in magento dispathed is true, but in the php no, and in magento de request_uri are rewrited to catalog/category/view/id/7?color=99 while in the php not hombre.html?color=99
Im missing anything, i need to initialize the front controller? o reinitialize???
Or there a different way to get the layered navigation from outside magento??
I found the problem and the solution...
On start magento it calls to rewrite the URL with the aim to get converted friendly url on a route url...
hombre.html?color=99 is converted on catalog/category/view/id/7?color=99
So the first is to call Mage::getModel('core/url_rewrite')->rewrite(); and now our frontcontroller request have the URL converted correctly.
Before that the frontendcontroller is inited executing the function match in all of its routers to try to find a controller and an action...
$frCont = Mage::app()->getFrontController();
foreach ($frCont->getRouters() as $router) {
if ($router->match($frCont->getRequest())) {
break;
}
}
With that two steps i have the frontcontroller initialized like if i access to the url "hombre.html?color=99" but in fact im on another php in my services folder.
But the match function after initialize the frontcontroller and get the router, action, and route, dispatch the action by default, so it generate all the html output and cannot work with layouts... So i create a local copy of the class Mage_Core_Controller_Varien_Router_Standard and i have updated the function match:
public function match(Zend_Controller_Request_Http $request){
.
.
.
$controllerInstance->dispatch($action);
return true;
}
for this one
public function match(Zend_Controller_Request_Http $request, $dispatchAction = true){
.
.
.
if($dispatchAction==true){
$controllerInstance->dispatch($action);
}
return true;
}
So in my service php i have that code:
Mage::getModel('core/url_rewrite')->rewrite();
$frCont = Mage::app()->getFrontController();
foreach ($frCont->getRouters() as $router) {
if ($router->match($frCont->getRequest(),false)) {
break;
}
}
And i have the frontcontroller initialized and the action,router,params, etc assigned like if i access from the catalog URL but withouth dispatching the action, and then i can write the objects i want with the layout object.
Hope it helps anyone.
Related
I'm building a simple CMS using Code Igniter version 3.0.0
The site's URLs are all customizable by the user and so do not follow the standard MVC structure of /controller/method/parameter-1/parameter-2/. Instead, all frontend traffic gets directed to PublicController's index method. This method searches the database for the current URL to return the correct page, and also the page type. Each page type corresponds to a controller.
How do I call that controller from the PublicController without doing a redirect?
I can't use the redirect() method because that would change the URL in the browser window and cause an un-need additional page request.
if you look at the url /about/who-we-are/
about is the controller and who-we-are is a function in the controller that loads one or more views.
The same for /locations/stores/
the functions stores in the controller locations.
read the documentation and it will be easy to understand.
http://www.codeigniter.com/user_guide/overview/mvc.html
I am pretty sure that configuring a route is your answer:
// routes.php
$route['(:any)'] = "PublicController/index/$1";
// PublicController.php
public function index()
{
var_dump(func_get_args());
}
I am building a cms in codeigniter and i want to remove controller name and function name form the url and just print the alias.
I will be having two controllers one for static pages and other for blog posts with categories.
Please help, Suggestions reagrding modification of two controllers are also welcome.
You will need to override the default 404 controller in application/config/routes.php.
$route['404_override'] = 'content';
Any request that can't be mapped to a controller will be passed to the application/controllers/content.php controller
Your Content controller, or whatever you decide to call it, will parse the uri [$this->uri->segment(1)] and check for a matching reference in your CMS database.
If there is no match in the database, then you can look for a static view in the views folder and load it.
if(is_file(FCPATH.'views/'.$this->uri->segment(1).'.php')) {
$this->load->view($controller,$this->data);
}
If no static view is found, and there is no matching content in the db, call the show_404() function.
Using this method, you will keep the default CI functionality of uri mapping, so at any time, you can add controllers as you normally would and the app will perform like a vanilla CI install.
There will be several high profile links for customers to focus on, for example:
Contact Us # domain.com/home/contact
About the Service # domain.com/home/service
Pricing # domain.com/home/pricing
How It Works # domain.com/home/how_it_works
Stuff like that. I would like to hide the home controller from the URL so the customer only sees /contact/, not /home/contact/. Same with /pricing/ not /home/pricing/
I know I can setup a controller or a route for each special page, but they will look the same except for content I want to pull from the database, and I would rather keep my code DRY.
I setup the following routes:
Route::get('/about_us', 'home#about_us');
Route::get('/featured_locations', 'home#featured_locations');
Which work well, but I am afraid of SEO trouble if I have duplicate content on the link with the controller in the URL. ( I don't plan on using both, but I have been known to do dumber things.)
So then made routes like these:
Route::get('/about_us', 'home#about_us');
Route::get('/home/about_us', function()
{
return Redirect::to('/about_us', 301);
});
Route::get('/featured_locations', 'home#featured_locations');
Route::get('/home/featured_locations', function()
{
return Redirect::to('/featured_locations', 301);
});
And now I have a redirect. It feels dumb, but it appears to be working the way I want. If I load the page at my shorter URL, it loads my content. If I try to visit the longer URL I get redirected.
It is only for about 8 or 9 special links, so I can easily manage the routes, but I feel there must be a smart way to do it.
Is this even an PHP problem, or is this an .htaccess / web.config problem?
What hell have I created with this redirection scheme. How do smart people do it? I have been searching for two hours but I cannot find a term to describe what I am doing.
Is there something built into laravel 4 that handles this?
UPDATE:
Here is my attempt to implement one of the answers. This is NOT working and I don't know what I am doing wrong.
application/routes.php
Route::controller('home');
Route::controller('Home_Controller', '/');
(you can see the edit history if you really want to look at some broken code)
And now domain.com/AboutYou and domain.com/aboutUs are returning 404. But the domain.com/home/AboutYou and domain.com/home/aboutUs are still returning as they should.
FINAL EDIT
I copied an idea from the PongoCMS routes.php (which is based on Laravel 3) and I see they used filters to get any URI segment and try to create a CMS page.
See my answer below using route filters. This new way doesn't require that I register every special route (good) but does give up redirects to the canonical (bad)
Put this in routes.php:
Route::controller('HomeController', '/');
This is telling you HomeController to route to the root of the website. Then, from your HomeController you can access any of the functions from there. Just make sure you prefix it with the correct verb. And keep in mind that laravel follows PSR-0 and PSR-1 standards, so methods are camelCased. So you'll have something like:
domain.com/aboutUs
In the HomeController:
<?php
class HomeController extends BaseController
{
public function getAboutUs()
{
return View::make('home.aboutus');
}
}
I used routes.php and filters to do it. I copied the idea from the nice looking PongoCMS
https://github.com/redbaron76/PongoCMS-Laravel-cms-bundle/blob/master/routes.php
application/routes.php
// automatically route all the items in the home controller
Route::controller('home');
// this is my last route, so it is a catch all. filter it
Route::get('(.*)', array('as' => 'layouts.locations', 'before' => 'checkWithHome', function() {}));
Route::filter('checkWithHome', function()
{
// if the view isn't a route already, then see if it is a view on the
// home controller. If not, then 404
$response = Controller::call('home#' . URI::segment(1));
if ( ! $response )
{
//didn't find it
return Response::error('404');
}
else
{
return $response;
}
});
They main problem I see is that the filter basically loads all the successful pages twice. I didn't see a method in the documentation that would detect if a page exists. I could probably write a library to do it.
Of course, with this final version, if I did find something I can just dump it on the page and stop processing the route. This way I only load all the resources once.
applicaiton/controllers/home.php
public function get_aboutUs()
{
$this->view_data['page_title'] = 'About Us';
$this->view_data['page_content'] = 'About Us';
$this->layout->nest('content', 'home.simplepage', $this->view_data);
}
public function get_featured_locations()
{
$this->view_data['page_title'] = 'Featured Locations';
$this->view_data['page_content'] = 'Featured properties shown here in a pretty row';
$this->layout->nest('content', 'home.simplepage', $this->view_data);
}
public function get_AboutYou()
{
//works when I return a view as use a layout
return View::make('home.index');
}
I think this is a route issue but I'm not sure. I have a page with this URL:
siteurl.com/kowmanger/titles/titles/edit/$id
I'm trying to find out that when I'm on this page I load the titles page it says page not found so I need to tell it that the $id is just a paramter so I can use it to get the data of the title.
UPDATE :
So I decided to change my titles controller so that there's a edit and add function inside of the titles controller that way they dont' have separate controllers when they are in fact methods.
So now I have:
kansasoutalwwrestling.com/kowmanager/titles/titles - list of titles
kansasoutalwwrestling.com/kowmanager/titles/titles/add - addnew form
kansasoutalwwrestling.com/kowmanager/titles/titles/edit/$id - edit form
I don't have any routes set up so far for this. For some reason though I"m getting the same page for both of these page.
kansasoutalwwrestling.com/kowmanager/titles/titles/add - addnew form
(right link url) kansasoutalwwrestling.com/kowmanager/titles/add -
addnew form
I need a route so that it'll show the correct url if the add method is accessed.
Also I need to set up a route so that if the correct edit link is accessed it sees the id attached to the end of the url and it'll accept it so that I can do a my database query to get the title data.
UPDATE: So to reiterate I have a module(subfolder) called titles. Inside of the module I have a controller called titles and inside of that controller I have 3 functions called index(), add(), edit().
I tried using Chris's suggestion on the routes but its not routing correctly. Also wanted to mention I'm using wiredesignz modular separation framework if that matters.
Any additional ideas?
Possible answer based on your post, not one hundred percent your entire structure but if i had to guess based off the post I would try this as my routes first..
$route['titles/titles/edit/(:any)'] = 'titles/titles/edit/$1';
$route['titles/titles/add'] = 'titles/titles/add';
$route['titles/titles'] = 'titles/titles';
$route['titles'] = 'titles/index';
Are you using custom routing in your configuration files ?
The general routing protocol used by codeigniter is like this:
domain.com/controller/methode/param1/param2/param3
This being said, your url
siteurl.com/kowmanger/titles/titles/edit/$id
corresponds to something like this :
class Kownmanger extends CI_Controller
{
public function titles($titles, $action, $id)
{
}
}
In case you are using sub-folders in your controllers folder, what I have just said will change, Could you please tell us what's your directory structure ?
I have a site that has a lot of pages that lye at the root (ex. /contact, /about, /home, /faq, /privacy, /tos, etc.). My question is should these all be separate controllers or one controller with many methods (ex. contact, about, index within a main.php controller )?
UPDATE:
I just realized that methods that are within the default controller don't show in the url without the default controller (ie. main/contact wont automatically route to /contact if main is the default controller ). So you would need to go into routes and override each page.
If all of these are just pages, I would recommend putting them into a single controller. I usually end up putting static pages like this into a 'pages' controller and putting in routes for each static page to bypass the '/pages' in my URLs.
If they are share the same functionality, so they should be in the same controller.
for example, if all of them are using the same model to take content from, so, one controller can easily handle it.
Why in one controller? because you always want to reuse your code.
class someController{
function cotact(){
print $this->getContentFromModel(1);
}
function about(){
print $this->getContentFromModel(2);
}
function home(){
print $this->getContentFromModel(3);
}
private function getContentFromModel($id){
return $this->someContentModel->getContentById($id);
}
}
(instead of print, you should use load a view)
See in my example how all of the function are using the same getContentFromModel function to share the same functionality.
but this is one case only, there could be ther cases that my example can be bad for...
in application/config/routes.php
$route['contact'] = "mainController/contact";
$route['about'] = "mainController/about";
$route['home'] = "mainController/home";
$route['faq'] = "mainController/faq";
$route['privacy'] = "mainController/privacy";
and you should add all of these methods within the mainController.php
You can also save the content of the pages in your database, and them query it. For instance, you can send the url as the keyword to identify the page content
$route['contact'] = "mainController/getContent/contact";
$route['about'] = "mainController/getContent/about";
$route['home'] = "mainController/getContent/home";
$route['faq'] = "mainController/getContent/faq";
$route['privacy'] = "mainController/getContent/privacy";
in this case you only have to create one method named "getContent" in the controller "mainController" and this method will look something like this:
class mainController extends CI_Controller
{
public function getContent($param)
{
$query = $this->db->get_where('mytable', array('pageName' => $param));
// then get the result and print it in a view
}
}
Hope this works for you
The page names you listed should probably be different methods inside your main controller. When you have other functionality that is related to another specific entity, like user, you can create another controller for the user entity and have different methods to display the user, update the user, register the user. But its all really a tool for you to organize your application in a way that makes sense for your domain and your domain model.
I've written a blog post about organizing CodeIgniter controller methods that might be helpful to you. Check it out here: http://caseyflynn.com/2011/10/26/codeigniter-php-framework-how-to-organize-controllers-to-achieve-dry-principles/