I have an admin template which I builded with blade templates,including one another.The user request is extending the main blade and returning only the content.
However in the template I have stuff like - user messages(count),theme options etc.
These things must be saved in the user session.Cookies are not an option.
The question is how to do it in the best possible option.
I'm thinking of gettind the request in middleware and accessing the session there.After that I must pass the data to the blade templates (not the final extending one).
Whats your opinion ?! Thanks!
If I understand correctly, you have a main layout blade template that is later extended by the user view returned by the controller.
No additional code like you described is needed. Both user and layout templates are processed after controller action is executed and both have access to user session via session() helper and user object via Auth::user().
So the following sample code should work for you :
// SomeController
public function someAction() {
return return response()->view('user');
}
// main.blade.php
#if (Auth::check())
Show this text only to authenticated users
#endif
Value of session parameter is {{ session('parameter_name') }}
// user.blade.php
#extends('main')
Related
I'm making a presonification menu on my navbar so that i can access from any page i don't want to use the getRepository inside a controller and pass to the frontend.
Is there a way on symfony 4 that I can get all the users from my database and call it to front? like the app.session.user (to get info on the logged user) for example?
Thanks!
As Cerad mentioned, you can embed a Controller in your templates : https://symfony.com/doc/current/templates.html#embedding-controllers
Instead of doing {% include 'base/navbar.html.twig' %} you will do
In your template :
{{ render(controller('App\\Controller\\BaseController::renderNavbar')) }}
In BaseController
public function renderNavbar(UserRepository $userRepository) {
return $this->render('base/navbar.html.twig', [
'activeUsers' => $userRepository->findActiveUsers(),
]);
}
It's not a route, it's simply a function that renders html, so you don't need to add annotations.
I have a layout that is used when you are logged in. menu.blade.php.
Then I use it in blade files #extends('admin.layouts.menu')
I want to show some information in the layout, let's say the number of messages near the "message" link in the menu. I could easily do this by adding:
$message_count = Message::where("user_id", Auth::user()->id)->count();
and adding: <div>{{$message_count}}</div> to menu.blade.php
to every single controller and view where the layout is used, but this is clearly not a clean way to do it.
Is there a way to pass information to the view in a single step instead of having to do it in every single controller?
Use view composers.
View composers are callbacks or class methods that are called when a view is rendered. If you have data that you want to be bound to a view each time that view is rendered, a view composer can help you organize that logic into a single location
Register the view composer within a service provider:
public function boot()
{
View::composer('menu', function ($view) {
$view->with('messagesCount', auth()->user()->messages->count())
});
}
Then each time when the menu view will be rendered, it will have $messagesCount variable with counted messages for an authenticated user.
In the past I've used a proprietary framework that kinda followed an Objective-C like View Controller scheme.
Basically I was able to in one controller instantiate another and pass it some values like an array of products and then inject the reference to the controller to my view and render it whenever I wanted by issuing: $controllerReference->render();
This could be useful in many cases, eg. if I had a controller responsible for rendering a catalog, I would just pass it an array with all the items I would like to see and it would take take of pagination and displaying the items by itself...
Example:
At \UI\Homepage\Controller.php (the controller responsible for the homepage):
// Instantiate a ProductDisplay Controller
$controllRef = new \UI\ProductDisplay\Controller();
$controllRef->setProducts( ... ); // Inject the product array
// Load the current view for this controller and pass it a reference for the ProductDisplay controller
$this->loadSelfView(["controllRef" => $controllRef]);
At \UI\Homepage\View.php (the view loaded before):
// some html of the view
$controllRef->render(); // Render the ProductDisplay view here!
// some other html
How should this functionality be accomplished in Laravel? From what I've been reading Laravel tries to avoid this kind of actions, why? What are the workarounds?
Thank you.
Here is how I will do this, it only work if the called controller method return a View object like return view('home');):
// Get the controller class from the IOC container
$myController= \App::make(MyController::class);
// Execute the controller method (which return a View object)
$view = $myController->myControllerMethod($someParams);
// Return the View html content
$html = $view->render();
you can use the Controller.php class which is extended by all other controller to make a generic method in it to:
Get a controller instance
Call the right method with x parameters
Return the rendered content if it's a view class OR throw an exception (for exemple)
In recent versions of Laravel, it's possible to use Blade's #inject directive. It seems its main purpose is to inject services but I successfully injected controller actions.
Here is a snippet on what you have to do:
#inject('productController', 'App\Http\Controllers\ProductController')
{!! $productController->index() !!}
Just remember: since you're calling the controller method directly, and not through the router, you'll have to pass all required params. If that action requires a request instance, you may call it this way:
{!! $productController->index(request()) !!}
Probably the view returned by the called action contains HTML code. It's important to wrap the method call within {!! and !!}. Using regular {{ }} tags will cause the HTML code be escaped by the template engine.
Im creating a MySQL database driven PHP (W)CMS application which follows the MVC pattern. First take a look at the framework:
The MVC framework handles the request and decides what to load/call based on the URL, like: http://domain.com/user/details/121 will load and instantiate a User controller object, and calls its details(121) method with the userid passed as a parameter, and then instantiate a User_Model and "ask" it for the detailed data of the user with the 121 userid, and at last display the result with a View. This is the basic concept of an MVC architecture. Nothing particular, everything is clear at this point.
Whereas this will be a CMS, I want to handle a Page model. A user with the nesessary permissions (mostly admin and/or root) can perform basic CRUD operations and other stuff on a page, for example:
I can create a page with the:
tile = 'About us' (this will be displayed as a headline of the page or the title of the browser tab like eg.: HTML title and h1 tags)
URL denomination = '*about_us*' (this will be the URI endpoint, like: http://domain.com/about_us)
reference name = 'Who we are' (This is the text displayed in the menubar)
page content = 'lorem ipsum...' (The actual content of the page...by a WYSIWYG html text editor)
and much more options like structuring the pages, to assign sub pages under a parent page, or making a page startpage (which means if I set 'About us' as a start page, then http://domain.com will automaticall load that page content)...
Or I can modify these properties, even I can delete a page...etc.
The MVC framework makes no difference between handling a frontend and a backend call.
For example we have some requests:
http://domain.com/user/details/121
http://domain.com/about_us
http://domain.com/our_products/1255
The first will load a backend controller as I detailed before,
but the others will load a frontend content.
When the Bootstrap loads the appropriate controller/action we look for the actual controller file, in the example above :
/controllers/Users.php
/controllers/About_us.php
/controllers/Our_products.php
The first can be loaded because that is a 'static' controller written before, but the About_us and Our_products are not existing controllers so If it is impossible to load the controller, the bootstrap searches the database if is there a page with the same URL denimination (like: about_us, our_products). If there is, we load a common FrontEndController and display the requested page data, if there isn't, display a 404 error.
I do this because I want the bootstrap to handle all requests the same way, but I dont want to every frontend URL compulsorily contain the FrontEndController (e.g.:http://domain.com/FrontEndController/our_products/1255). So this is how I hide it from the user, so the URL can remain more user friendly. My question is: Is this a good practice? Or are there any other proper ways to do this?
The MVC framework handles the request and decides what to load/call based on the URL
What you would normally is have is some sort of Router and Dispatcher class. The router would accept the the user/details/121, parse it and return a Route.
$route = $router->route( $request->getUri() );
The router could hold config values like the allowed space character in URI's, default allowed characters etc.
You can also add custom routes to the router
$router->addRoutes($routes);
The custom routes can be a simple associative array
$routes['requested-uri'] = 'custom-route'
In the example above you said when they visit the root of the website you want them to actually see the About Us page so that could be done like this:
$router->addRoutes([
'' => 'about-us
]);
Meaning when the URI is ''(blank) then go to the 'about-us' route. It shouldn't do a redirect, just transparently load up a different route while keeping the URI in the clients web browser the same.
Routing can obviously be more complex, using route objects added to a route collection for more advanced custom routing with more control. Some frameworks use annotations and all sort of different ways to achieve flexible routing.
The dispatcher could then accept the route returned from the router and dispatch it. That means verifying if the requested route actually exists i.e does the controller file exist and the requested method in the controller exist.
$view = $dispatcher->dispatch($route);
Inside the Dispatcher::Dispatch() method:
// Check if the controller file exists.
// Instantiate the controller file, preferably using a controller factory.
// Check if the controller method exists.
// Call the controller method
call_user_func_array([$controller, $route->getMethod()], $route->getParams());
$view = $controller->getView();
$action = $route->getAction();
// Call the view method.
if( method_exists($view, $action) ) {
$view->$action();
}
return $view;
I find the following a very easy to understand way of dealing with controller methods/actions. Let's say you have a login controller, the user sends a GET request to it first and a POST request to it when sending the login details in the form.
public function getIndex() { }
public function postIndex() {
$username = $this->request->post('username');
$password = $this->request->post('password');
}
The get and post in front of the method name is the request type, this prevents you having to do something like this
public function index() {
if( $this->request->getType() === 'POST' ) {
$username = $this->request->post('username');
$password = $this->request->post('password');
}
}
It also gives you more control over authorisation(if you do it at the routing layer) because you can easily allow a user to send a GET request to the controller but deny them access to sending a POST request.
Each controller has a one to one relationship with a view. The view get's injected into the controller on construction, preferably using a controller factory.
What would happen when you send a GET request http://domain.com/user/details/121 is the router would break up the URI and turn it into a route targeting the User controller, the getDetails() method with the parameter 121, the dispatcher checks if the controller and method exist, it then calls the method supplying the user ID as an argument, the controller sets the user ID in the view. Below is the User controller.
public function getDetails($userId) {
$this->getView()->setUserId( (int)$userId );
}
The view then has a method called details(). The same name as the method called in the controller, just without the request type in front of it.
The dispatcher then calls the details() method of the view which then fetches the required data.
Setting the title of the page is done in the view, as it is for presentation purposes only.
Part of the view that is related to the User controller
public function details() {
// Fetch the user by using the previously set user ID from the controller.
// If he doesn't exist set an error template, set the response code to 404,
// or redirect. Do whatever you want really.
$this->setTitle('User Details');
// Build template objects, bind the fetched user data to main template.
}
How you implement the setTitle method and all over view related stuff is up to you.
The view sends the response back to the client, whether it is HTML content, JSON, XML, or any other content type.
For example your application lets you search for users and export them to a Microsoft Excel Workbook file(.xlsx) and prompt the user to download it.
The view would:
Fetch the users
Generate the file
Set the HTTP response headers like Content-Type
Send the response
I've just discovered HMVC Modular Extension for CodeIgniter https://bitbucket.org/wiredesignz/codeigniter-modular-extensions-hmvc/wiki/Home and it seems perfect for my needs but I have some question.
Let's say I have two controllers:
Site which is the main controller and is used to show site's pages and may call methods of Users controller for example to show a form
User controller is used to authenticate users, to show login/sign up forms...
Now I have these questions:
If the user access the User controller directly (mysite.com/user/method) I want to show a full page while if i load a method of User from within the Site controller I want to show only a form (for example), is this possible?
What happens to view of a module loaded from another module: is the view shown automatically or i need to show it manually and how does the view behave?
If you method is being called via Modules::run()
There is a third optional parameter lets you change the behavior of
the function so that it returns data as a string rather than sending
it to your browser.
Eg:
//put underscore in front to prevent uri access to this method.
public function _module1()
{
$this->load->view('partial_view', array('some data'=>'some data'), TRUE)
}
call it inside your SITE view easily
Modules::run('User/_module1')
// should show whatever is in partial_view ie: a form
//an alternative is to pass in any params if the method requires them
Modules::run('User/_module1', $param)