How to access data some specific Controllers in Laravel? - php

For sharing data with all views I read in documentation we can create
View::share('key', 'value');
I found that also we can make View Composer to share data with only some specific views.
But how to actually share data with only some specific controllers?
Few controllers we list to have injected some variables, objects arrays etc ready to use.
One Idea that comes to my mind is to create for them middleware... But I don't think it should be done something this way
Looking for this in documentation and web but cannot found, so how actually share data only with some specific controllers that we want to?

Maybe this will help for you:
Some snippets from conetix.com.au/blog/simple-guide-using-traits-laravel-5
You can use use ExampleCode; in the controller you wish
<?php
namespace App\Traits;
trait ExampleCode
{
public function asd()
{
return [1,2,3];
}
}
namespace App\Something;
use App\Traits\ExampleCode;
class Someclass
{
use ExampleCode;
public $yourarray;
public function __construct()
{
$this->yourarray = $this->asd();
}
public function hi(){
dd($this->yourarray);
}
}

If multiple controllers need to have access to the same data, then you may want to consider creating a base controller that they inherit from and setting that data in the constructor of the controller.
Alternatively you can store it in the session and retrieve it from there in the controllers that need it.

Maybe it's better to use decomposition for this purpose. Write some service class for your data, bind it to your service container and then inject it into controllers constructor or action methods.

Related

Why are Laravel Models static and should I use static functions in my own Models?

In Laravel Models use functions that are static and the documentation uses static functions to show how Models work. If I create a new Model for my application, it extends the base Model class but why is Laravel using static functions? I thought the idea is static anything is bad? For example, it makes testing harder?
I'm just confused as most things can be retrieved from the DI container? For example, a Model called Flight, why is it not used like this inside a controller:
namespace App\Http\Controllers;
use App\Flight;
class FlightController
{
public __construct(Flight $flight)
{
$this->flight = $flight; // etc.
}
}
And Models are not even using a Facade either? When I create my own models am I suppose to always use static functions as well?
I'm not sure I understand your question correctly, but I think you are mistaking Facades for static methods. Read this https://laravel.com/docs/7.x/facades#how-facades-work, Laravel uses the magic method _callStatic() to resolve to actual instances. So it looks static, but it isn't.

Laravel , how to call a function from another controller

I have a controller with the "getUsers" function in a controller called "UserController" , and inside it I want to call a function of the "CarController" controller called "getCars", the two options I have are:
a) Make the second call as "static" , then I can call it without instantiating the class
b) Do not do that function of the static class and I call it in this way
$ car_id = 100;
$ userController = new UserController ();
$ userController-> getCars ($ car_id);
I do not know which is the best practice, or what pros or cons has one or another.
I'm using laravel.
Thanxs.
It is a bad practice to call a controller from another controller, this usually signals that you have badly designed your code and you should think of a different way to achieve what you want.
None the less, you can do it like this:
app()->call('App\Http\Controllers\CarController#getCars');
If your controller method has parameters you can pass them as the second argument:
app()->call('App\Http\Controllers\CarController#getCars', [$param1, $param2]);
To answer your question, you should not call one controller method from another. As #elfu mentioned, this is not the intended functionality of a controller anyway. His post is correct and in your case you should probably use the User model as the location of this method, but I thought I'd at to it a little.
If you do want to share methods between multiple controllers, a good place to do this is through a Trait. In some cases, you are not referencing a model that is shared between controllers, and a Trait would be your best option.
To include a trait, you can reference it by including it at the top of your controller and then with a 'use' statement after the class declaration for the controller. Here is an example:
use App\Traits\ExampleTrait;
class CarController extends Controller
{
use ExampleTrait;
...
You would do the same in the UserController. Then, any method that you place in the ExampleTrait will be directly accessible from the CarController and the UserController by referencing it as $this->methodName(), just like referencing any other method in the same controller.
In your particular case, I would say that your logic should probably be stored in the User model, since the cars for a user are really an ATTRIBUTE of the User model, but the above gives you another option to work with.
In my humble opinion you should not call another controller in a controller.
It looks like you have some business logic in that controller. So you should move your logic to the entity (User.php) and call it in both controllers methods.
A regular controller returns a view (at least that is what is expected), so if you want to call another controller you should just send that route to that method (in web.php file) instead of calling it in another controller.
Hope that helps you.
You can call one controller function from another but the best way is to create a trait and use it both the controllers like:
trait Common
{
public function method(){}
}
class FirstController extends Controller
{
use Common;
}
class SecondController extends Controller
{
use Common;
}
If you want to bind parameters to the call, you can use:
$videos = app()->call('App\Http\Controllers\StorageController#returnViewVideo',[
'course'=>$course,
'lesson'=>$lesson,
]);
The following code worked for me well. and also it also can be used in routes.php
public function mobileImageUpload(Request $request){
$this->validate($request,[
'data'=>'required',
'filetype'=>'required',
'userid'=>'required',
]);
$namespace = 'App\Http\Controllers';
$controller = app()->make($namespace.'\ImageController');
return $controller->callAction('mobileImageUpload',[$request]);
}

Asset for multiple views in Yii2

So i am into the challenge of in passing the asset for a number of different views.
As far as I am concerned, there are some ways, apart from adding
use app\assets\SomeAsset;
SomeAsset::register($this);
to the layout page or calling out this method.
Although, I am interested, are there any more flexible ways of passing an asset or a group of assets to the whole crud model at once, for example.
Wiggling around me and my colleague found out that this way works as I wanted to:
use app\assets\SomeAsset;
//...Some other dependencies
class DefaultController
{
// add this at the beginning of class in the controller
public function beforeAction($action)
{
SomeAsset::register($this->view);
return parent::beforeAction($action);
}
}
So this might help if you want to pass asset to all files that are under DefaultController control.
Hope this will be useful to somebody.

Laravel Structure - dependency injecting a controller

I have a laravel app and have created a SocialMediaController to get the latest posts from twitter and instagram and store them in the database.
I need them to be universally accessible and know I can access it via the IOC.
public function doSomething(App\Http\Controllers\SocialMediaController
$SocialMedia) {
}
However if feels wrong to inject a controller like this. What is be best way to wrap up these methods for global use?
It seems like you want to share some logic you have in the SocialMediaController with another controller, right?
Instead of trying to pass a controller instance to the controller action using the service container, you may move the current logic to a service. Refer to Service Container and Service Providers in the Laravel docs on how to create your own services.
Another way to achieve that is using a trait. Check this answer on how you can do that https://stackoverflow.com/a/30365349/1128918. You would end up with something like this:
trait SocialFeeder {
public function getLatestFromTwitter() {
...
}
}
And, then, you can use that new trait with your controllers:
class SocialMediaController extends Controller {
use SocialFeeder;
public function doSomething() {
...
$tweets = $this->getLatestFromTwitter();
...
}
}

Laravel Service as Controller - working with multiples controllers

I'am a Brazilian developer, so... sorry for my limited English right away.
Well, in fact my problem is more a convention problem because until now I hadn't use services with Laravel (my apps were that simple so far).
I read about it before ask this question, but nothing helped with this specific situation. I'll try to describe in a objective way.
before that, just a comment: I know about the mistake using just controllers in these example. The ask is really about that mistake.
Well, the actual structure is:
abstract class CRUDController extends Controller {
protected function __construct($data, $validatorData) {
// store the data in a attribute
// create with Validator facade the validation and store too
}
abstract protected function createRecord();
protected function create() {
try {
// do the validation and return an Response instance with error messages
// if the data is ok, store in the database with models
// (here's where the magic takes place) in that store!
// to do that, calls the method createRecord (which is abstract)
$this->createRecord();
// return a success message in an Response instance
}
catch(\Exception $e) {
// return an Response instance with error messages
}
}
}
class UserController extends CRUDController {
public function __construct($data) {
parent::__construct($data, [
'rules' => [
// specific user code here
],
'messages' => [
// specific user code here
],
'customAttributes' => [
// specific user code here
]
]);
}
protected function createRecord() {
$user = new UserModel();
// store values here...
$user->save();
return $user;
}
}
// here's the route to consider in that example
Route::post('/user', 'WebsiteController#register');
class WebsiteController extends Controller {
private $request;
public function __construct(Request $request) {
$this->request = $request;
}
public function register() {
$user = new UserController();
$user->create($this->request);
// here's the problem: controller working with another controller
}
}
class UserAPIController extends Controller {
// use here the UserController too
}
and many other classes that extends CRUDController in the same way...
What I want
I want to create a controller (called here as CRUDController) to reuse methods like the pattern says (create, read, update and delete).
To be really objective here I'll use the create method as an example.
With the code above it seems clear the purpose? I think so... all my controllers have that code of validation equal and reusable. That's the thing.
Besides that, I want to my route of website call another controller (UserController) to store new users... but in the same way, I'll create an API that uses the same controller in the same way (with validations etc). That's the purpose of Responses in the CRUDController (I'll read them in the WebSiteController to resolve what to do, like show a view and in the other hand with the API I'll basically return the Response.
My real problem
Convention and pattern. The MVC pattern is broken here. Controller calling another controller is wrong and I know that.
I want to know what thing I should use! Services? Is that right? I see a lot (really) of examples of services but nothing like that, working with models and reusing code, etc. I never use Services but I know how to use, but I don't know if it's right to these cases.
I really hope that someone can help here and sorry once again for the mistakes with the English. Thanks a lot.
You're calling the CRUD controller a controller but it does not behave as an MVC controller. At best it's just a helper class. You could always do this:
abstract class CRUDManager {
//As you had the CRUDController
}
class UserManager extends CRUDManager {
//As you had the UserController
}
In your AppServiceProvider:
public function boot() {
$app->bind(UserManager::class, function ($app) {
return new UserManager(request()->all()); //I guess that's what you need.
});
}
Whenever you need to use it you can do:
public function register(UserManager $user) {
$user->create();
}
Now one thing to point out. It's not a good idea to initialise the request in the constructor. You should use dependency injection in controller methods. I don't even know if the request is available when the controller is being constructed (I know the session is not). The reason why I say this is that the middleware runs after the controller is constructed and therefore the request may be modified when the controller method is called.
Another note: If you did the original solution because you needed to use certain controller methods, then you can just use the corresponding traits (because the controller itself does not really have many method). I'm guessing a trait like ValidatesRequests would be one you'd need to use.
I'll answer my own question. I use a pattern called Repository Pattern to resolve the problem (or I try to use, because it's the first time using this pattern: maybe I don't use in the right way in every steps).
Files structure
Controllers
UserController.php
Models
UserModel.php
Providers
UserRepositoryServiceProvider.php
Repositories
RepositoryInterface.php
Repository.php
User
UserRepositoryInterface.php
UserRepository.php
Traits
InternalResponse.php
With that structure I did what I wanted in my question without working just with controllers.
I create a trait called InternalResponse. That trait contains a few methods that receive a transaction, validate if it's the case and then return a Response (called "internal" in my logic because the controller will read and maybe change the Response before return it in the end).
The Repository class, which is abstract (because another class must extend it to make sense to use. In this case the class UserRepository will extend...), uses the Trait mentioned.
Well, with it in mind, it's possible to know that the UserController uses the UserRepositoryInterface, that provides an object UserRepository: because the UserRepositoryServiceProvider register this with that interface.
I think there's no need to write code here to explain, because the problem is about an pattern, and these words explain well the problem (in the question) and the resolution with this answer here.
I'll write here a conclusion, I mean, the files structure with comments to explain a little bit more, to end the answer.
Conclusion: Files structure with comments
Controllers
UserController.php
// the controller uses dependency injection and call methods of
// UserRepository, read and changes the Response receveid to finally
// create the final Response, like returning a view or the response
// itself (in the case it's an API controller)
Models
UserModel.php
// an normal model
Providers
UserRepositoryServiceProvider.php
// register the UserRepositoryInterface to
// return a UserRepository object
Repositories
RepositoryInterface.php
// the main interface for the Repository
Repository.php
// the main repository. It's an abstract class.
// All the others repositories must extend that class, because
// there's no reason to use a class Repository without an Model
// to access the database... That class share methods like create,
// read, update and delete, and the methods validate and transaction
// too because uses the trait InternalResponse.
User
UserRepositoryInterface.php
// the interface for UserRepository class
UserRepository.php
// that class extend Repository and uses the UserModel
Traits
InternalResponse.php
// trait with methods like validate and transaction. the method
// validate, read and validate the data receveid for the methods
// create and update. and all the CRUD methods uses the method
// transaction to perform the data to the database and return a
// response of that action.
That's what I do and like I said before, I don't know if it's a hundred percent correct in reference to Repository Pattern.
I hope this can help someone else too.
Thanks for all.

Categories