Currently in my CI project I have a single controller that handles all things account. Such-as register, login, activation, etc.
My routes work as such...
domain.com/account/login/ or domain.com/account/register/
How can I remove account from the route while also being about to remove the controller from other pages.
I basically want the controller to always be removed. One of my reasons for this is SEO, search engine rank the importunateness of a page based on how deep it is in a website.
The only way I have seem to achieve this is to do some thing like route['activate'] = 'account/activate'; for every single page, which would be a huge hassle.
$route['^(?!other|controllers).*'] = “account/$0″;
Try this :
$route['(:any)'] = "account/$1";
The answer to your question is that you DO have to explicitly set the routes.
How is it going to know which controller a given function is in????
You have to tell it.
use mod_rewrite (if the controller is always the same name)
Ok, I can think of one way to do this, but it is probably gonna be more of a pain than just writing out routes for each function.
You need to extend the Router.php with application/core/MY_Router.php and overide the _validate_request() method. Which basically decides if this this is a valid route or not.
it does a check to see if the controller class exists then fails if it doesn't exist.
You need to replace this with some code which assumes no controller segment, then scans thru each of your controllers and checks if it contains the method called (it will be segment 1, since theres no controller).
Now the tricky part, at this point in the CI lifecycle your controller obviously isnt loaded, so you cant examine it using method_exists() yet.
You need to load your controllers one at a time, and then for each one run
method_exists($loaded_class, $method_name)
and if its true, then set then go ahead and call:
$this->set_class('the_name_of_the_scanned_class_which_had_the_method');
Then CI can keep going on as normal and it will load your methods without the user ever know what controller it loaded from.
.. probably not worth the hassle imho. A much easier solution would be to just have one controller and one route to that controller.
Related
Coming from a straight PHP and Drupal background, I am recently learning the Symfony2 framework. Currently I am in the routing chapter of the book. This is probably a simple question.
What are some real world use cases for why one would want to generate URLs in a Symfony app? I understand the code but I'm having a bit of trouble determining its practical applications.
I'm referring to this section should you need a refresher.
As always, thank you!
P.S. Symfony is amazing. :)
Basically, you need to generate a URL whenever you need to link to anywhere in your application.
Let's say that you have an application that needs to manage some users. This means that you will probably have URLs like /user/create, /user/edit/(user id) and /user/remove/(user id).
Whenever you display a link to edit a user you need to know on what URL you can find the page that allows you to edit a user. So you need to link to /user/edit/(user id). One solution would be to have this as a fixed link so that in your code you could just write
edit this user
But what if you want to change this URL scheme? Let's say someone is unhappy with the term "user", after all the humans managed by this system are not only users, they are actually "person"s! So now you need to change all the URLs containing "user". Probably there are quite a few places in your app where you have had to hardcode these URLs and now you will need to find and change all of them. Eugh.
But fear not, for Symfony routing comes to the rescue!
Instead of hardcoding these URLs, we can simply let the Symfony router generate them for us. This means that we first need to tell Symfony which routes we have, e.g. by adding the following YAML code to our routes config file:
user_edit:
path: /user/edit/{userId}
defaults: { _controller: AppBundle:User:edit }
requirements:
userId: \d+
This tells our application "Okay, whenever somebody requests a page that looks like /user/edit/{userId}, then you need to call the editAction method in our UserController class in the AppBundle namespace and you need to pass the userId as a parameter. Oh, and also you should only call the controller if userId is a valid integer with at least one number."
So this is how Symfony knows how to map URLs to controllers. But the goodness that comes along with it is that we can use this information for the reverse way as well.
Usually, in our application we do not really care about what the URL looks like for a certain action we want to perform. All we know is that when clicking a certain link, then the browser should jump to a page that allows me to edit a user. And since we just defined a route that takes us right there, we can have Symfony generate the correct URL to achieve just that.
So in your view you can now discard the hardcoded URL from earlier and instead replace it with a route generated by the Symfony router:
edit this user
Now whenever you need to change what the URL actually looks like all you need to do is edit your routing config and not a lot of separate views.
Because, imagine you want to change a given page URL and you've hardcoded it in 10 Twig templates. You will have to modify all these files. On the opposite, when using the routing component:
You would only have to change the URL where the route is defined.
The routing component "takes" care of the current environment you are using (dev, prod...)
Also note that is a bad practice to "switch environment", a typical issue is to hardcode an URL in a Javascript. In this case you can expose your Symfony2 routes in the Javascript by using a bundle like FOSJsRoutingBundle.
I almost immediately realized their use and now I feel silly. :) For those who stop by this question in the future:
Notes about Generating URLs:
Similar to the Drupal l() function, sometimes you need to generate links inside your application based on a variety of parameters.
You don't always want to hardcode your links in case you decide to change paths sometime down the line.
In summary: Think of this as an alternative to using straight anchor tags with href elements all over the app and, instead, keeping things dynamic.
Use case
In the project I'm working I use generateUrl to redirect the user
after creating, editing an entity.
For example after creating a Service entity, I redirect the user to the view
of the just created Service.
Controller
return $this->redirect($this->generateUrl('myentity_view', array('id'=> $id)));
Additional note
In twig files, you can use the path function which call the routing component and generate url with given route name and parameters.
I've had a quick search on Stackoverflow but not really found an answer to a question that I have. Sorry if it's already been answered and I've missed it!
I'm working on an application, and similarly to Facebook, there will be 'notifications' but in my case it'll be items that require actions from the user. It would just be a 'count' of the actions that are required and nothing else.
I've followed a fat model, skinny controller approach through my application and so far so good. I have a good idea of what goes where, and when to use a plugin, app model, app controller, etc.
However, I'm a little confused about where to put this notification/action 'count'. I'm guessing either afterFilter() in the app_controller.php file, but that's just a guess. I'm just looking for the most efficient place to put it.
So, where's the best/fastest/most efficient place to put this count call?
Thanks!
Kingsley
EDIT: I just realised it's worth pointing out that this particular call is on a model. So, at the moment I have to load that model, and then call it.
The ideal place is in an Element. You can then use requestAction() to tell it where to retrieve it's data from.
The Element is placed into a view (or used to display a Flash message). Within it, it pulls it's data (requestAction) from a Controller's Action. That action get's it's data from the Model of your choice just like you would in any other action. This allows complete separation of concerns (ie MVC).
If you're like me, you think CodeIgniter is pretty nice. You also probably hate typing _model every time you load or call a method or property from your models, because it's ugly and time-consuming.
I've been searching for a solution to this for a couple hours with no luck - so I put together a quick fix.
Take a look at the loader class documentation.
Say you've got a class called page_model, you would typically load and use it like this:
$this->load->model('page_model');
$this->page_model->function();`
If you want to avoid typing _model every time you can do this:
$this->load->model('page_model', 'page');
$this->page->function();
When I first started using CodeIgniter I always did this. Now after using CI for several years and a number of websites, I regret that decision.
It's harder to tell what's going on when looking at the code. Having the _model as part of the code that calls the model function removes any ambiguity. For example, in the above function call is page a library or a model?
This is because CodeIgniter does not support namespaces. While there have been discussions of namespace support in CI for some time, support in the stock codebase is still forthcoming.
The solution? Prefix your controllers instead! In typical usage, you're unlikely to need to type the name of the controller more than once per file.
First edit application/config/routes and add the following line after all the other routes:
$route['(:any)'] = "c_$1";
With this rule, you route the first segment of the URI to the matching controller with your prefix. So that:
http://www.domain.com/fishsticks
maps to the following controller:
c_fishsticks
Next, rename your controller files with this prefix, as well as altering the class names inside to match.
That's it! Now you can name your models with relative freedom. You can rename your models at your leisure, but don't forget that you need to change each model's filename, each model's class name, as well as all references to each model. This is easily the most time-consuming step, but on the plus side you don't have to do it all at once.
I created a page using the MVC structure called 'sections' ( view is located in the app/views/sections folder, model in the model folder and the controller in the controller folder) when i request the variable $test, it works fine without any errors..
When i want to request this variable in my home.ctp, it provides me with an error, saying that the variable is undefined..
Is there any way in cakePHP to request this variable on any page you want it to?
Thnx in advance!
In the MVC stack, you need to set variables with data in your controller, and then pass them out to your view.
So in your example, you'll want to $this->set('myvar',$item); in your SectionsController, then in your view, you will be able to echo $myvar.
Be sure to set this in the home() method of your Sections controller, otherwise it won't be available in your home view.
Standing on the shoulders of deceze's comment and DavidYell's answer, I think they've managed to scratch out a decent view of what you're trying to get to. Maybe. So with that loose understanding of what you're seeing and what you have...
By default, the PagesController::display() method generates the homepage view (home.ctp). I suspect that this is what you're talking about. That said, the variable you're setting in a method of your SectionsController won't be available to your homepage which is created by a different method in a different controller. If you want a variable available to all views there are several things you can do:
You can set the variable in your config/core.php file (not generally recommended)
You can set it in config/bootstrap.php if it's a constant. By that, I mean that it's a value you're going to hard code, not something dynamically generated. Whether you create the variable as a constant doesn't matter.
You can set in in your AppController in a beforeFilter() or beforeRender() method. All of your custom controllers (assuming you've followed protocol) inherit from the AppController. If you choose this path, make a copy of cake/libs/controller/app_controller.php and place it in your app/ directory.
Those are the ways that I think will best meet your needs as I understand them.
I'm working on a web application, using the CAKEPHP framework. Herefor i need to request one variable on multiple pages (all pages have different controllers). it is oubvious that i get a error on several pages, since the variable isn't declared in all the different controllers.
Is there a workaround for this? i've already tried the app:: import to import a controller in another controller, but this doens't seem to work (still get a undefined variable error).
Thnx for your cooperation!
Regards,
Simon
Duplicate question, but I think it's phrased a bit better so I'll paste my answer here:
Standing on the shoulders of deceze's comment and DavidYell's answer, I think they've managed to scratch out a decent view of what you're trying to get to. Maybe. So with that loose understanding of what you're seeing and what you have...
By default, the PagesController::display() method generates the homepage view (home.ctp). I suspect that this is what you're talking about. That said, the variable you're setting in a method of your SectionsController won't be available to your homepage which is created by a different method in a different controller. If you want a variable available to all views there are several things you can do:
You can set the variable in your config/core.php file (not generally recommended)
You can set it in config/bootstrap.php if it's a constant. By that, I mean that it's a value you're going to hard code, not something dynamically generated. Whether you create the variable as a constant doesn't matter.
You can set in in your AppController in a beforeFilter() or beforeRender() method. All of your custom controllers (assuming you've followed protocol) inherit from the AppController. If you choose this path, make a copy of cake/libs/controller/app_controller.php and place it in your app/ directory.
Those are the ways that I think will best meet your needs as I understand them.
You can use the Configure.write... more info here
More on configure class
One way to make sure that the variable is available on all pages is to define it on the front controller (normally index.php) or any other always included file (such as global configs), another option might be to use the $_SESSION super global.
You can youse the beforeRender() or beforeFilter() callback methods from your AppController. :)
These'll be called on every page request. :)
If you to access a value from different controllers, you will need to save that value into a database record so it can be accessed by the different controller methods. Each controller call exists in its own context and can only share data that is stored external to the scripts.
In situations like this, I've created a preferences table (with fields like, id, name and value). Then add a $uses value to the app_controller to make it available to all controllers. Finally, just grab it with a find call. (ie. $foo = $this->Preferences->find( 'first', array('conditions'=>array('name'='foo')));