Where to put universal functionality in a CakePHP project - php

I currently have a Helper (FieldFormatterHelper) I created to assist with consistent formatting of certain types of data (dates, booleans, enumerated types, etc) across various views.
In particular I store certain enumerated types in MySQL using an integer and then display a corresponding string value in my views. The problem I'm running into now is that while this Helper works well for my views for things like "view" and "index" Views that administrative users access from the site's backend, I also have afterSave() methods in several models that create JSON outputs for Mustache rendering on the frontend.
I understand, more or less, the core ideas of MVC and the basic arguments for, say, not trying to access a View Helper from within a Model, but I need some sort of universal access to the functionality my Helper provides. Certainly I could define my enumerated type mappings in my frontend JavaScript and other places I might need it, but that violates the DRY principle and would ultimately be a pain to maintain.
So, the question is: If it's not appropriate to access/load my Helper from within my Model, where, and how, should I encapsulate this functionality so both my Models and various Views can utilize it?
Ideally, I would be able to continue using my existing FieldFormatterHelper--perhaps modifying to be a wrapper for this new container.
Any guidance on the ways of CakePHP and MVC in general would be appreciated. Thanks.

You can implement it as a static method on a class and use it anywhere
class Utils {
static public function formatField($args) {
// your implementation
}
}
then just have your helper defer to the static method call using
Utils::formatField($args);

You can create a static function and put it in app\view\helper\AppHelper.php. Then when you want to call it you put
App::uses('AppHelper','View/Helper');
at the top of the file and call it like this:
AppHelper::staticFunction()

Related

PHP MVC - Calling view functions from model, or controller?

After reading a fair few posts on Stack, and also some material recommended to me on line, the MVC pattern is quite open to interpretation, so please don't answer with another explanation. Thanks!
I'm reaching the end of designing my own PHP MVC now, and have two possible ways to move forward with the views.
But first, my controllers are currently quite dumb, not containing any classes and simply call public methods from the suitable models, and render the appropriate view.
Views are included as necessary, so naturally the objects are available to them via the constructors, along with all the methods (inc delete/update etc).
My first option is to get data using something like this in the view
foreach($object->fetchData() as $data)
and then looping through the results. However some people do not agree with this, and have suggested that such methods should be excluded from the view. Instead it has been recommended that I assign this to a variable in the constructor, and then use this variable in the view
//constructor
$fetched_data = $object->fetchData()
// view
foreach($featched_data as $data)
I don't like this very much, as it seams messy and unnecessary.
With all my critical methods being made available to the view, could this be considered a problem?
So here's the question. Do I keep it how it is, and create new methods in the MODEL for rendering data (as above) OR can I create a class in the constructor, extend the model into it, protect the critical functions in the model, and then create my read only public methods in the CONSTRCUTOR?
Thanks!
I would create a class in the constructor. Not only would extending the model be a much safer approach, but it'd also minimize the calling of functions in the views. Am assuming you'll have several views, it's much easier to get access the constructor data than calling method functions each time in each view.
You can add classes to your controllers that will call the method functions and pass the data directly into the views, instead of clustering your constructor or bootstrap.

CodeIgniter CRUD view abstraction

I'm building a CMS using CodeIgniter and I'm stumped on the best way to go about handling the various CRUD views. Given that my URL is similar to...
mydomain.com/admin/app/content/pages/edit
...where 'admin' is my controller and 'app' is my action method, I currently map segments 3, 4, and 5 to actual directories/files, like so:
/views
/admin
/content
/pages
list_view.php
edit_view.php
add_view.php
/banners
list_view.php
edit_view.php
add_view.php
One caveat is that I need to call different non-CRUD model methods depending on which page is being called, so my app() action method is starting to have have a nasty if..else block. Also, each section's views are going to look different, because of different table data, so I don't see how I can avoid having a bunch of view pages. Obviously the downside of all this is that 1) I'm repeating a lot of code, and 2) if I add a new admin section I have to physically make a slew of new directories and add a new portion to the if...else block.
So my questions are:
How can I reduce the number of directories and view pages I'm creating?
Can list_fields() or field_data() methods lend itself to any automation?
One idea I had was to profile the table I'm interacting with, create a dynamic associative array that defines which fields I want to expose as well as the type of form element it should be, and then pass that off to a common view. Thoughts? Flaws?
While this may not directly answer to your question, it may provide you with a basis on which to design your CRUD. I've used GroceryCRUD for quite a while now and pretty much swear by it for basic and advanced CRUD operations. It's pretty well designed and built and apart from the bespoke file structure, would appear to offer all that you're looking for.
The CRUD could easily be modified to incorporate the file/url structure you're looking for too.
See http://www.grocerycrud.com/
You can extend the CI_Model and use some reflection functions like getProperties() to help with your generic CRUDs. In conjunction with CI's list_fields() like you mentioned, you could definitely create some generic pages to do so.
An example that can process form data for any object might be
function processForm() {
$props = $this->self->getProperties(ReflectionProperty::IS_PUBLIC);
foreach ($props as $prop) :
$prop->setValue($this,$this->input->post($prop->getName()));
endforeach;
}
where
$this->self = new ReflectionClass($this);

Django development - how to lay out and use code properly

Hi i'm a PHP developer trying to convert to Django and im having a bit of a hard time understanding where to put things and how to use the new language. Basically what i want to know is for example in codeigniter i would make classes and functions in my controllers. Where do i do that in django?
I believe the 'view' in django is more like the controller in an MVC framework but all the examples i can find of the view are very simple and just call a template and pass it some data.
I currently have an index view and a 'rates' view in my current project. The index page will call rates via JS and pass it some GET variables. In my php version i used these to instantiate my rates class which when had all the needed functions in it. I want to do this in Django.
The reason that it is called, "MVT" instead of "MVC" is that "View" to Django means, "presentation of data (according to given logic)" and "Template" means, "display of data presented." In a traditional MVC paradigm, "Controller" means "executer of logic" and "View" is "presentation of the result of the executed logic". (They are almost the same idea, but not quite).
So, what does this mean? Basically, if I were building something in Symfony, I would put all of the logic in the sfAction components. In CodeIgniter, it would be in the CI_Controller. In Django, I will place all of the logic in the "Views".
Just like CI (and Zend and others) will then call a "View" from the Controller descendant, the Django view will also call a "Template" from its "View". (Symfony's views are often called in a different syntax, so I will leave that to the reader to research if so desired).
Looking at your example, it looks like you want to call a method in the "View" (which view is configured in urls.py) which simply instantiates another object which has "all of your logic in it". Something like:
def ratesHandler(request):
rate = MyRatesClass(request.GET)
return HttpResponse("Insert something here. ") #or render_to_response
The logic always belongs in the view. You can put whatever logic you like there - no need to put it into a class, unless you want to. If the logic is related to a specific model, though, it is best to make it a method of the model or the model's Manager.
In django: "models" go in models.py, "controllers" go in views.py and "views" go in templates.
Models tend to be classes that subclass django.db.models.Model
Controllers (in views.py) are often functions but you can use classes if you like.
Note that if you're just displaying data from the database you can often use generic views so you hardly have to do any coding at all.
I can't tell whether there is a question in the last 2 paragraphs of your post. If there is a question there, please edit your post so it's clear.

How to merge few ACLs in Zend Framework?

I have few instances of Zend_Acl objects, like this one (one for each module):
class My_Acl_Module1 extends My_Base_Acl
{
public function __construct()
{
parent::__construct();
$this->addResource('News_Model_Entry');
$this->deny('guest', 'News_Model_Entry', 'index', new News_Model_Acl_Assert_CategoryPrivate());
}
}
class My_Base_Acl extends Zend_Acl
{
public function __construct()
{
$this->addRole('guest');
}
}
How to merge them into one ACL object to use in navigation container?
Edit
Some more info:
I don't use controller resources in favor of model based resources (models, forms implement Zend_Acl_Resource_Interface). All of them have method isAllowed()
I use modular directory and reusable modules (separate models, configs, routes etc.)
My application knows all installed modules, controllers, action (structure already parsed, not in real time)
So I'm looking the way to follow this scheme, and separate the ACL for each module. I don't want to use application resource, because it is a waste - acl is not needed always.
I have an action helper which instantiates module specific ACL only when it is really needed. But sometimes I'd like to have global application ACL available too (eg. when I'd like to pass it to the navigation view helper or controller plugin).
My module ACL classes have all just one method: init().
Dirty solution I see, is to parse the source classes and merge the files into one method for new class.
Any suggestions?
I think this is almost impossible without the application knowing a bit more about itself. I had a similiar problem a while ago too and didn't find any satisfying solution. When merging you'll loose some information (the module) which you need later on in your navigation.
The first solution I had back there, was to iterate over all acl-files in each module and create a custom ACL-merge function to merge them all. This actually did work but I didn't like the idea of a file-scan over my complete application (even if the results were cached).
My last approach was to add more data to my application: For every linkable action I defined the corresponding acl-file. This wasn't as much work as it may sound. Mainly because my controllers/models do match almost exactly. So I have a model 'News' and a controller 'News' which handles the access to it and maps every action of the model to the frontend. So I only had to specify the acl/controller relations. (I used a custom element in each navigation container to save this).

What could I do to improve my MVC?

I'm thinking of re-working my MVC before I get to far along with it. At the moment it uses a sinle controller which takes the user input and determines the model. The model has maby differ methods which I call actions, because one is called automatically. The model loads its view file, which again holds many different methods. The model can set properties which can be used in the view. Then the controller calls th template classwhich parses the output for display.
Is this the bst way to do it?
Or should each different part (news, contact, about) have its own controller, which loads a specific model and view. Essentially, instead of grouping methods into a single file, it uses multipe files.
I'm kind of lost as to how I should do it.
Cheers
Start using a MVC that works and is well-known like in Symfony or Cake. From that you will decide:
what do to in your own, knowing the best practices;
to drop your own if you feel like you can save time by using theses.
If you are thinking of advancing your own MVC model, like #e-satis have said, you will need to experience what is happening in already developed systems. However, as based on my experience in designing MVC model and determining what is there in opensource community, I stick back to my own MVC for two good reasons. One reason is the flexibility of customization and the other is own MVC privacy.
I used the following approach for MVC design pattern.
A Router.php file identifying user-request urls. This router will be able to fetch controllers and include the file and call the controller default method.
The loaded controller is also able to load other controllers if required to function. This is done using a global method, where all controller Class will extend to a MainController Class which is able to call to other controllers.
I do use a global registry to set and get variables from one controller to the other.
The Models are used to get the Data from Table, and most of my Models will represent Database functions which includes CRUD (Create Read Update Delete). So that a controller can easily manipulate database table data using a model.
Naming conventions in all controller, models, and views is also important, if you want to system to be more intelligent to identify the required action knowing the file name.
I use the Views separately for each type of controller. And these views will be sent to a Master Template View file.
Same as models, the controller will be able to set Views to Master View.
There are other customizations which you can do, like applying security methods before calling a class, or after calling a class/controller/model/view etc.
This is done by the MainController, which it will always look into a folder with autoload class which states what files should be loaded before and after of different actions during the process of building the content and delivering the output.
MVC is not a small scale idea, but it is a design idea which can always be developed. There are so many PHP MVC open source frameworks to be found if you know how to search the major search engines like google.com
But I do advice you that, MVC is not a good solution if you are simply developing a small dynamic website, as it will consume more time in developing compared to developing small websites. MVC is ideal, if you have business logic and needs system automation in order to avoid most routine tasks of developing, and like that I would say MVC is most ideal for larger applications.
The model loads its view file
The Controller should act as a Mediator between the Model and the View.
The Model shouldn't be aware of the way the view renders it, and also the View shouldn't be aware of any kind of logic of the Model.
In theory, if your MVC is well structured, you should be able to represent the same Model with different types of Views (HTML, XML, JSON for example).
Build FrontController which parses request uri and decides which controller to load and which method to run. With .htaccess rewrite all request to index.php
//index.php
class FrontController{
function run(){
//parse request uri here /comment/new
//load controller comment
//run controllers method new and pass some request attributes
}
}
// ../controllers/comment.php
class Controller_Comment extends Controller{
function new($request){
//do stuff here
}
}

Categories