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.
Related
edit: apparently it's too late to delete this question, which is a shame because I have no idea why storing pages in a JSON file seemed like a reasonable idea last May.
It'd be good to let a framework handle page routing instead of reinventing the wheel, but I'm trying to understand actual implementation of this design pattern better as much as anything else. I also recognize that a pure implementation of MVC may not always be possible for web applications, but all of this is server-side.
This is my current structure (minus irrelevant files):
app/
controllers/
PageController.php
models/
PageModel.php
views/
GlobalFooter.php
GlobalHeader.php
Pages.json
config/
db_connect.php
/docs
/lib
/web
/js
/img
/css
index.php
When a user loads a page, the page instantiates a controller which passes the $_GET parameter to the page model.
The model loads the Pages.JSON file as an associative array and retrieves specific page data:
title
controller
page-specific stylesheet names
page-specific script names
which membergroups can access it
etc.
Along with extracting a dynamic list of the pages this User is allowed to access, for navigation. The controller then calls the appropriate view with the appropriate content.
So far: Originally I was going to put the Pages.json in with the "views", because it's static data and the stylesheet/script specification is relevant to front-end management. After all, the goal is that repainting the house only needs webroot access, or views template access for more extensive remodeling.
But Pages.json is not a view. It's a data source.
Current "solution":
Leaving the file on the top level in app/...but I feel like this is an MVC faux pas.
Even if it isn't, I don't want my app folder to become a dumping ground for data sources.
Potential solutions I've been tossing around:
Storing the pages in a database table instead of JSON and having a PageModel method call a method from db_connect.php to fetch it. But I want pages to be able to load skeletons of themselves even if a connection to the database fails. Additionally, even with cacheing, I don't want to make that database request whenever a page loads.
Storing the pages in a multidimensional PHP array instead of JSON...but then I have the same design problem, albeit with a PHP file, something I want working on the front end of this to touch even less than JSON. Along with a teeny bit more overhead.
Adding data/ as a data-housing directory in app/...but this also feels too much like stepping outside the design pattern and creating a dumping ground.
Going back to separate parallel one-dimensional PHP arrays in the PageModel, which might theoretically be more efficient, but it was ugly and risky and hard-coded compared to sourcing page info dynamically. Nah.
Current planned solution:
Decoupling the front-end JSON data (stylesheet, etc.) from the
back-end (controller, etc.) into two JSON files.
Storing front-end data sources in views/ from now on.
Storing back-end ones in model/ from now on.
Does that sound like a good solution? Or is there a convention already for where data sources should be stored?
Or is this an X question for a Y problem and I shouldn't be storing the pages as JSON data at all? And if so, what would be a better alternative to either that, database tables, or hard-coded PHP arrays?
If anyone has advice or an answer, thank you in advance for your time.
You can avoid storing these values in a json file.
you can introduce a naming convention, which might not be a good
solution for some use cases.
I would tie CSS and JSS in the template file (HTML or PHP) file on
your view. this way you dont have to list all your assets files
manually in a json file. Thus your designer/frontend programmer can
just write a "normal" HTML/template/PHP file.
Having a model that loads page definition, might cause a problem when you have 2 or models in your page. And also your model will not be reusable, because it's tied to a page.
For your page definition, such as title, meta keywords and stuff, you can create 1 model specifically for this. Your controller then fetch these data by calling it for a specified action/page. e.g. in index action, you can call: pageDefModel->getMetaTags();. then you can pass these results to your view.
Overview: I am building a CMS using PHP, and I am trying to implement this using MVC. I am trying to extend my code using this structure, as it represents an accurate representation of MVC and it is quite straightforward. To communicate with my database I use Domain Objects and Data Mappers.
Questions:
Is it really necessary to have a 1:1:1 mapping between a model, a view, and a controller?
Example: For a blog system, when displaying a blog entry page I would create a controller called DisplayEntryController, and a View called DisplayEntryView. The view would get its information from the BlogMapper class (which communicates with the DB to retrieve the current blog entry) and a CommentMapper class (which communicates with the DB to retrieve the comments for the current blog entry). Is this good practice, considering that view works with 2 model objects? If not what is the alternative? If yes, how can this be implemented in a generic way?
Can multiple controllers handle one page? For the example above, would it be possible to have a DisplayEntryController and a CommentController handling the relevant parts of a page displaying the blog entry? If yes, how would the 2 controllers coordinate?
Thank you in advance. Examples will be greatly appreciated.
Most PHP MVC implementations I've seen on the web use the page approach to organise their MVC. E.g. for the Home page, you have one view, one controller and one model. Routing for 1:1:1 mapping in MVC is straightforward, as you can enforce the location and naming of your MVC components, and when a request for the Home page comes it automatically looks for the following classes: HomeView HomeController and HomeModel.
This obviously doesn't work well in larger projects. How should routing be handled to support routing to multiple models (DataMappers), multiple views, without creating an overcomplicated router or adding a complex dependency injection layer?
Example: As discussed above, when displaying a blog entry you display
the blog entry code and the comment section. To achieve this, it
communicates with two DataMappers, the one which gets the blog entry,
and the one which returns the comments for the blog. How can the view
be assigned to work with these two datamappers to get the data from
the DB?
There is no requirement to have a 1:1 mapping of the model, controller and view.
MVC works of a concept of a tiered approach to handling your application, with each tier being handled by 'agents' to implement the way they see fit. To explain this further, consider the following scenario.
Assume you process data, then hand them over to someone to store. You don't care where they store it and how they store the data, as long as the information is available again when you need it. You can happily go about processing your data, and then say to them for example 'This is project data for Client X, store it,' and later say 'Can you give me the project data for Client X.'
SO MVC works on this approach, whether the data storage guys dump all data together or pack them away is not important to you. However, what is important is the interface between the two parties when sending and retrieving. For example, you could decide to store the information as either Client data, or Project Data, or both.
Likewise, you could have agents collecting data and handling it to you to process. You don't care how many interfaces they use (for example, phone, web, email, mobile devices), but you care about what data they hand you. (Of course a rule might dictate that only web information must be handled). So the interfaces for collecting data might be different.
Therefore, each agent can use the most efficient method (and even combine or split them) to get the system working in their side, and therefore there is no mapping of the data.
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.
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 :)
I'm learning the OO and MVC paradigm (using Codeigniter and PHP). I continue to find warnings such as this: If you find yourself pasting the same code into multiple files, then you aren't using OO/MVC properly. So, here's a question for more experienced programmers.
I have a create-user form that I am using two very similar versions of:
Version 1 (at /volunteer/register) is created by an anonymous user. The form lives in the volunteers controller, and needs to be verified by an admin.
Version 2 (at /admin/create_volunteer) is created by a logged-in admin. The form and validation is nearly the same, but it is submitted with different parameters.
Another, similar example:
I want to build different user dashboards that share a template, but will be used by different user roles and have different functions and information based on role. As I see it my choices are:
Create a Dashboard controller with three functions defining the data loaded into the dashboard template.
Add the a dashboard function to each role's controller (Volunteer, Admin etc).
Create a controller for each case (Volunteer, Admin, etc.)
I apologize if this appears sophomoric but essentially I'm looking for rules-of-thumb to determine how to design architecture in MVC.
My questions:
In the first example, is my logical choice of controllers (Volunteer & Admin) less than ideal? Is code replication in this case an acceptable practice?
Can anyone recommend architecting tools to establish logical consistency and good workflow for MVC?
Especially since the two forms are not the same (different rules, different interface) there's absolutely nothing wrong having two separate view files if you need it. Loading the same view file in two different controllers or methods is perfectly acceptable, indeed it's appropriate. If there are only a few tweaks that need to be made, try to reuse the view file by passing different data to it.
If you want to simply load the form view file in different instances, that would save you some code duplication. Just set different rules and if needed, pass different data to the view. It's similar to using the same form to create and edit something in two different methods. If the output is going to be totally different, just write separate view files. If it's the same output but with different data - definitely reuse it.
Don't get obsessed with trying to not duplicate view fragment code - if you are writing even more code to force the reuse of a view file by modifying it for different instances, it kind of defeats the purpose. Try to just make it a general practice to make your code as reusable as possible.
So, without seeing your actual code - I'd say don't worry about it. In my experience, view files for front-end and back-end are almost always unique (completely different UI). In general, if you find you are duplicating the same very similar code a lot, it's time to write a function, class, or template for it.
It seems you would like to use some ACL for distinction between roles (Volunteer and Admin) that will check whether requested module or action can be accessed.
Creating different controllers for the roles doesn't seem to be a good choice since this architecture could not be reused - you don't want to reuse specific Admin or Volunteer functions in other applications but rather a module that lets you create and control such roles.
You would like to reuse a code offering particular functionality, this might be one controller, one model and some view files.
Most programmers consider duplicated code as a sign that the solution to a problem still can be improved.
If the problem in your case is that the from is defined in one controller but you need to use it in another controller as well, then you need a better place to define the form so that both controllers have access to it independently from each other.
Make the form configurable so it's possible to reuse it.