Laravel - How to pass cached value to multiple views without extra requests? - laravel

Have several data collections that are retrieved from cache and need to be passed to several different views.
For performance optimization need them to be retrieved only once, without extra requests to cache.
So using ViewComposer is not an option - it fires request to cache for each listed view.
Using following solution in AppServiceProvider :
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
view()->share('somedata', Cache::get('somekey'));
}
But in this case data passed to all views, which is not good from perspective of memory consumption.
Need ability to pass data only to certain views. (not pages, as those views are used on almost every page)
Something like following:
view(['viewname1', 'viewname2'])->share('somedata', Cache::get('somekey'));

You can use a View Composer. Example below taken from documentation.
Register the view composer in your AppServiceProvider and specify the routes it should be attached to;
View::composer(
['profile', 'dashboard'], // the routes you want to share it with
'App\Http\View\Composers\MyViewComposer' // your registered view composer
);
In your View Composer, get your cached variable and pass it to the views;
public function compose(View $view)
{
$someData = Cache::get('somekey');
$view->with($someData);
}

Related

Generic Model Based CRUD API Laravel

Is there a built in or library based way to implement generic Eloquent/Model based views in Laravel for simple CRUD endpoints?
At the moment I am writing the logic for index, store, destroy, update manually, but all the code is essentially the same.
e.g.
public function destroy($id)
{
$customer= CustomerInfo::find($id);
$customer->delete();
}
I'm more used to Django and the DRF which implements a ModelViewSet class which handles all (most) of the logic for simple CRUD applications.
Implement generic Eloquent/Model based views in Laravel for simple CRUD endpoints
I'm not sure about that but Laravel provides route to model binding, which shortens your code. There's also resource controller which is already pretty much declare all needed methods for you. What's left is quite minimal. So after using model binding and resource controller, your destroy() method may look like:
public function destroy(CustomerInfo $customerInfo)
{
$customerInfo->delete();
}
But the method name and its agrument is already declared like a placeholder, you just write delete() line. More about model binding and resource controller
Use single artisan command to have CRUD endpoints all in one.
php artisan make:controller PhotoController --resource
Because of this common use case, Laravel resource routing assigns the typical create, read, update, and delete ("CRUD") routes to a controller with a single line of code. To get started, we can use the make:controller Artisan command's --resource option to quickly create a controller to handle these actions:

Does Cache work in an API route and should we use it?

I am creating an API. In this API I am accessing a (permissions) table from a database multiple times, in middleware as well as in controllers. I was thinking, instead of accessing the database multiple times, why don't I call it once and use it multiple times. After calling it once, I could store it in the cache within a service provider. But I am not sure if it is a good way to go because API routes don't load all the services like session.
There are other ways like storing data into the config. Or create a class and make a facade for it and then call it when ever it is needed. But I am curious if the cache would work in API routes and would it be a good idea?
Okay with the advice of #lagbox I created a dead simple class.
namespace App\Helpers;
use App\Permission;
class Provide
{
public $permissions = [];
function __construct() {
$this->permissions = Permission::whereNotNull('route_name')->get();
}
}
This may vary, it's just a class that will keep some collection data in it. I named it provide to keep it generic, just in case that I could need other data than permission in the future. Of course this class could be more detailed but just for storing and returning permissions it is enough.
Then I bound it as a singleton in my AppServiceProvider to run it only once.
public function register()
{
$this->app->singleton('App\Helpers\Provide', function ($app) {
return new \App\Helpers\Provide();
});
}
and when I need it I call it like
$provide->permissions->toArray()
All the features of the collection are available everywhere from the beginning to the end. Yes that may look like an overkill or an abuse of IoC but this über simple approach is in my case a superb solution.

How to use $this in another file on Codeigniter?

I have a file named fn.php in my view, then I create a function to post data, like this
function post($input_name){
return $this->input->post($input_name);
}
In my controller I call it like this,
public function myFunc(){
$this->input->load('fn.php');
// then I use the function that I have created like this
post('myinputname');
}
But... I got error, how I can solve this problem? thank you so much
You should take some time to try and understand the MVC architecture. It is, after all, one of the main points of using a framework.
You can't put functions in a view and expect to load them somehow and access them. You can put functions in a model, controller, library or helper. In you case I would suggest a helper:
application/helpers/some_file_helper.php
function post($input_name){
$CI = &get_instance();
return $CI->input->post($input_name);
}
The get_instance() part is only used when $this (CI context) isn't available. This only happens in helpers and libraries. In views, controllers, and models $this is always available.
Model or controller:
$this->load->helper('some_file');
print_r(post('somevar'));
However if all you want to do is access the post variable use $this->input->post('somevar') directly and don't introduce an extra layer.

Laravel RESTful Controller - Params Before Action Name

I have UsersController which is RESTful controller, there are some functions within it.
inside UsersController.php:
function postOutletVisit($id){
// some code
}
inside routes.php :
Route::controller('users', 'UsersController');
with this route I can access postOutletVisit action like this:
[POST] mydomain.com/users/outlet-visit/{id}
But I'm wondering if it's possible to convert that link to:
[POST] mydomain.com/users/{id}/outlet-visit
I know that I can do this by defining routes for every action like:
Route::post('users/{id}/outlet-visit', 'UsersController#outletVisit')
But this is not suitable for me because there are plenty of actions inside UsersConroller and I will loose the greate naming convenient for actions (first part of action name determines the method used in it, instead of defining the methods separately in routes.php file)
Outlet Visit is a specific resource, so it doesn't belong in your UserController and should have its own controller.
class OutletController extends BaseController
{
public function postStore($userId) // Controller for storing Outlet Visits
{
...
}
}
Then you define your routes for OutletController, specifying that you need to attach it to a specific user :
Route::controller('users/{id}/outlet', 'OutletController');
If needed you can add more actions for this Controller, such as listing, forms for adding / editing, etc.
First off, I think you mean to use Route::resource('users', 'UsersController').
Secondly, of course you can. Just overload the other route method underneath:
// This defines the predefined Laravel routing
Route::resource('users', 'UsersController')
Route::post('users/{id}/outlet-visit', 'UsersController#outletVisit');
There are no ways to change the urls created by the method Route::controller unless you extend it.

CodeIgniter Model / Controller and UserID

My Models in CodeIgniter need to check that a user is authorised to perform the given action. Inside the Models I have been referencing using $this->session->userdata['user_id'].
My question is - should I be setting a variable to $this->session->userdata['user_id'] in the Controller and passing this to the Model, or simply checking it inside the Model ?
Does it even matter ? I suppose passing $user_id into the function would make it (slightly) more readable. What are the arguements and recommendations for / against ?
You can choose between data that is fundamental to your application and data that is incidental to a given model member function. Things that you use everywhere should be guaranteed (base members, globals, etc.), and things used only in the current function should be parameters. You'll find that using implied variables (like $this->session->userdata) in many places in your models and views will become spaghetti quickly, and will be unpredictable if you don't bootstrap them properly.
In my CodeIgniter projects, I add a custom base model and controller that inherit from the CI framework, adding their own member data that is used everywhere in the app. I use these base classes to provide data and functions that all of my models and controllers use (including things like userID). In the constructor of my_base_controller, I call the CI base constructor, and set up data that all of my controllers and views need. This guarantees predictable defaults for class data.
Strictly speaking $this->session->userdata['user_id'] belongs to the controller.
Models deal with data only... controllers, by definition control the flow of the data...
and authentication is a form of data control... (IMHO)
Codewise, I follow this procedure
class MyControllerName extends Controller{
function MyMyControllerName(){
parent::Controller();
$this->_user_id=$this->session->userdata['user_id']; //<-- define userid as a property of class
}
}
And then, say one of my functions foo() requires authentication.. I would do this
function foo(){
$this->_checkAuthentication(); //should short out if not authenticated
//rest of the function logic goes here
}
the _checkAuthentication() can be simplistic like:
function _checkAuthentication(){
if(!isset($this->_user_id) && $this->_user_id<=0){ /or any other checks
header("Location: ".base_url()."location_of/user_not_authorised_page");
exit;
}
}

Resources