CodeIgniter core changes - php

CI looks for Segment[1] for controller (in controller dir) and Segment[2] for Method. Now, I have specific requirement by business application which needs that I do not want CI to look or by force go to controller dir to load but I will have something like this "domainURL/module_identifier_id/controller/method/".
Here, every request will be coming along with its associated Module's Identifier ID which will have complete module's configuration and other data (controller files, module location where it was uploaded, all menus and their URLs which will have same URL mechanism which we want to design for developers to develop modules and upload) stored in DB.
We need to get this ID and play with it to fetch relevent records and point CI to load controller from where we want it and indeed rest for methods etc every thing needs to be working as it is.
I hope you understand what we are looking for that we have our own main controller type file where all of the requests will be coming with customizing protocol as described above and developers will be following it by all means, that there must be module identifier first and then controller, method etc...
Let me know if you have any query to be cleared on?

I think I would just use routes for this:
$route[(:any)/(:any)/(:any)] = '$2/$3/$1';
This should just rearrange your segments the way you want, without completely changing the way the native routing system works.

Related

How to implement region-specific app in Laravel Controllers

I am using Laravel 6.
I am building an app that has Files (not a file stored on your desktop or storage). I have a File model, FileController controller and Files in the DB with id, user_id (as it belongs to a user) and data (which is a JSON column).
For my app, a File can have different fields, based on jurisdiction, that need to be captured (via forms on the blade templates) and managed via the controller (primarily via show, edit, update).
It is likely that I have many jurisdictions (imagine country, state and maybe city) versions of Files, with their respective fields that need to be captured, displayed, modified, etc.
In many of these Files, especially if its in the same country, there are fields (columns/keys) that are repeated.
Currently, I have one Controller, and when it comes to editing a File, showing a File or updating a File, I am starting to have logic that detects the country or state and modifying the logic or view.
Initially I thought I would do something like this
File - model
FileController - root controller
- #edit calls FileControllers/country/state/FileController#edit.php
- #show calls FileControllers/country/state/FileController#show.php
- #update will reference FileControllers/country/state/FileController#update
Files.view.blade - root view for Show
Files.edit.blade - root view for Edit
but I have a feeling this is going to get out of hand really quickly, especially if certain File records have similar fields, views, data types that I will capture. There aren't any that are consist across the various different jurisdictions, which is why I opted for a JSON store in the mysql database.
What are some ways to dynamically manage this sort of setup with relative ease of maintainability, in the long run? I am a beginner-ish to novice-ish developer.
I’ve decided for the purposes of moving my project forward to setup region specific controllers and views and to use Web.php to handle the routes such as
So I’ll be running:
php artisan make:controller /us/ny/FileController
Route::get(‘file/edit,’$country.’/‘.$state.’/FileController#edit’);
With some code to detect that those exist.
I’m still open to feedback and advice as I’m happy to refactor with a better way to manage it, especially with any reusable parts.
I wanted to log another answer in the event another developer is going down this path and looking for an answer.
Not sure if this is the best way but I've decided to invoke the method from within a root controller.
So
Route::patch('/file','FileController#update');
Within FileController, the update() method has
app()->call('App\Http\Controllers\\'.$country.'\FileController#Update')
I've read this isn't the best way to do it, but have not found specific alternatives.

Use cases for generated URLs in Symfony2?

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.

Kohana 3.3 - dynamic menu creation with rights management possible?

I would like to use Kohana 3.3 as a replacement for my self written "framework" which I am currently using for my webapp. Could you please tell me if it is possible to fulfill the following requirements and how to achieve this?
My app consists of several controllers, which I want to access via menu. This menu should be dynamically created, so that a newly created controller will show up immediately. Additionally the menu should exclude controllers which are not accessible for the currently logged in user.
Each controller must be able to check the user's role before executing an action (e.g. global admin, controller-specific admin, regular user). Depending on this role each controller must be able to permit or prohibit access. (Thought about a group membership based method).
I want to use a separate template (as far as I know aka partial) for the menu and for each controller output. They all should be merged with a "frame" template (with header, footer,login info, etc.). I saw there is a special controller for templates (template_controller iirc) - is this the right one to use as my base controller? And should I create a base controller which manages my "template" and nest the other controllers in it somehow?!
Additionally it would be nice if each controller had the ability to recognize the current request as ajax or non-ajax and adjust the rendering accordingly (in most cases "rendering" the whole site again is not desired with ajax).
I would be grateful for every answer!
Thanks in advance.
Yes, but you'd have to search for the controller files yourself AFAIK.
Yes, see before(),
2.1 If you want to keep it in one place you would only have to write a little extra something to specifiy which action requires what privileges. Check out Kohana's Request class for some nice stuff you could use for this (I'd say take a look at the url, uri and request methods, I don't know by hard what exactly they do)
2.2 You could also do it on a per-controller basis; e.g. Controller_Admin could do the following ugly one-liner (check snippet for 2.2 below). I suggest splitting it up a little bit though, e.g. giving your base controller a protected $_user variable which it fills in it's before() method and then use $this->_user instead of Auth stuff.
It's Controller_Template but yes, you got that right ;)
Like this? Request::$current->is_ajax() (http://kohanaframework.org/3.3/guide-api/Request#is_ajax)
Snippet for 2.2:
if ( ! Auth::instance()->get_user()->has('role', ORM::factory('Role', array('name' => 'admin')))
throw new HTTP_Exception_403('Permission denied!');

Change templates/views location in Symfony2

I will be working on project that has different theme for each domain (same application will be serving multiple domains).
I need to change location of templates completely outside the application folder, possible on another volume
I need to make it work with multiple domains with multiple themes - i guess theres cache problem
S how to do this stuff with Symfony2 and twig?
EDIT: I will try to ask this: What or where do I need to rewrite to get custom logic on locating specific templates that symfony uses to render pages.
I can't say if first point of your question is a bad practice (and don't know even if it possible, but I would say yes).
However, what I would do is some kind of "manager" that will takes responsibility for choosing what kind of template render, based onto your own logic. Some kind of "intermediate level" between actions and views.
You could create it as a service and use everywhere, without have need to instantiate it every time.
It could read a file for configuration or, even (but less springy), use a class-internal configuration.
Algorithm could be something like this:
Take into account your request
"Eat" data and "spit out" the correct template (name)
Pass template (name) to your view
Extend (dinamically) the template given by your manager
Please, don't ask me some code because it could result in some hundred lines :)

Advice on creating codeigniter app to serve custom microsites

I'm building a codeigniter application that will serve custom microsites. Essentially each microsite will be a collection of seven different views all loaded by a single controller's methods. To 'Theme' each microsite there will be different folders containing different versions of these view files (and their associated css, js and image files) and the controller will know which folder of views to load based on information stored in the database for each microsite record.
The problem with this approach is when a single microsite needs to have a custom page that is unique from all the other microsites. Since they're all controlled by one controller, we run into the limitation that either all the microsites need to support this page.
To futher explain what I'm referring to imagine these urls:
http://www.fakewebsite.com/index.php/microsite/index/david_site
http://www.fakewebsite.com/index.php/microsite/index/frank_site
In both of these links the controller is 'microsite' and the method is 'index'
'index' knows what template to return based off it's first argument which is either 'david_site' or 'frank_site' in the above example.
I can't say if this is possible with Codeigniter, but I assume so:
So what's now your problem? That you have too much code in the controllers? Move code from the controllers into the models. Then the code is more re-useable and you can have small controllers on each microsite with fat models that are shared anyway.
Sounds not really good so far, right? Still there's one controller per each site. Well, make each microsite's controller extend from a base controller. So all code's still in one place but for some controller methods they can extend that base controller on a per-site basis.
So the front-end controller then will provide the right controller class per site as it does for the themes - if I understood your question right.
Can you have a default "theme" for that controller, which would accommodate most of your microsites, and then if you need to create custom themes on top you can change it?
So like this
http://www.fakewebsite.com/microsite/david_site/ <-- default theme
http://www.fakewebsite.com/microsite/frank_site/ <-- default theme
http://www.fakewebsite.com/microsite/john_site/customtheme/ <-- custom theme
As I understand the question, you're asking how to load a different view file for only specific "microsites", but you're using the same controller and codebase for all of them.
In your views directory, have 1 directory for default themes, and and then for each "microsite" you want to do something custom with, create another directory which will contain the unique files, then when loading files - check if the unique exists first.
Hasty example that assumes default files are in the root of views/:
// I assume we know which site we're loading
$theme = 'david_site';
// Whatever the current view's name should be
$view = 'page3';
// Path to our custom file if it exists
$custom = APPPATH.'views/'.$theme.'/'.$view;
// Does a custom view exist?
if (file_exists($custom))
{
$view_file = $theme.'/'.$view;
}
else
{
// Use the default
$view_file = $view;
}
$this->load->view($view_file);
As far as I know, there's nothing like view_file_exists() in CI, so we're just using plain old file_exists() with the full path.
It would be worth writing a function for this of course, but hopefully this helps. You could even apply it to loading libraries, models, etc. - or even extend the Loader class to do it automatically (probably overkill).
CI2 already has a version of this feature in the ENVIRONMENT constant, although this usage is not its intention - but that is basically what it does.

Categories