I have a simple code that displays to the user all of his notifications received from the Database:
$user_notifications = DB::table('notifications')->where('user_id', $this->user->id)->orderBy('id', 'desc')->get();
the problem is that I have too many controllers and functions in them and I don’t want to duplicate this code everywhere, in each function and controller. How can I make the $user_notifications variable global and use it everywhere?
u need to create a NotificationRepository
class NotificationsRepository
{
private Notifications $model;
public function __construct(Notification $model)
{
$this->model = $model;
}
public function findByUserId(int $userId): Collection
{
return $this->model->where('user_id', $userId)->orderBy('id', 'desc')->get();
}
}
Then in Controller action add this repository by autowiring
class SomeController extends Controller
{
public function someAction(NotificationRepository $repository, int $id)
{
$notifications = $repository->findByUserId($id);
}
}
or this way, i dont know how did u use your actions
class SomeController extends Controller
{
public function someAction(NotificationRepository $repository, Illuminate\Http\Request $request)
{
$notifications = $repository->findByUserId($request->user()->id);
}
}
Related
I'm trying to concatenate two class spesific variables in controller and pass it to all views without repeating the same variable in every controller methods.
Example code:
class ProductsController extends Controller
{
private $global_path; //Comes from .env
private $sub_folder = '/products_folder';
public function __construct()
{
//Frontend Image Path - to pass into all views
$frontend_path = $this->global_path.$this->sub_folder;
}
}
I want to pass '$frontend_path' to all blade views created in the controller without repeating it in every single method like
return view('example_view', compact('frontend_path');
I tried View::share... but couldn't do it.
The '$sub_folder' variable doesn't have the same value in all controllers.
Is there a way to make it possible?
For your code, I think you can change it to
class ProductsController extends Controller
{
public $frontend_path;
public function __construct() {
$this->frontend_path = env('GLOBAL_PATH') . '/products_folder';
}
public function index()
{
$x = $this->frontend_path;
return view('index', compact('x'));
}
}
and directly use it like $this->frontend_path or like below SELF::$frontend_path
class ProductsController extends Controller
{
public static $frontend_path;
public function __construct() {
SELF::$frontend_path = env('GLOBAL_PATH') . '/products_folder';
}
public function index()
{
$x = SELF::$frontend_path;
return view('index', compact('x'));
}
}
or
class ProductsController extends Controller
{
public static $frontend_path;
public function __construct() {
SELF::$frontend_path = env('GLOBAL_PATH') . '/products_folder';
view()->share('frontend_path', SELF::$frontend_path);
}
public function index()
{
return view('index');
}
}
in view
{{ $frontend_path }}
I stumbled upon different articles about implementing Repository pattern in Laravel and all of them making me confused. Everyone of them is putting their weight on "keeping it ORM independent" but no one is actually showing the example code.
I am here with my repository sample structure which I believe is not ORM independent in a way. But I need it with REAL REPOSITORY PATTERN solution where I can change the ORM from Eloquent model to something else like Doctrine. And keep the Business logic separate some way so i no need to change it. currently my Business logic lies in Repository (not recommended i think.)
Basic Questions:
My repository, uses Eloquent method name inside it which will not be there if i change the ORM. $this->model = $shops;
In Controllers and Blade templates what we are playing with is Collections of Eloquent Model. How should we handle them if we change the ORM?
Where to put create/delete methods if not in repository.
Please don't just use Domain Object word because I am tired of
understanding it without an coded example. It will be highly
appreciated if you try to explain [Domain object] using a real code
example by modifying this. [How to return it in controller and use it
in Blade]
Interface:
<?php
namespace Modules\ShopOwner\Entities\Repository\Contract;
interface ShopsRepository {
public function getall();
public function create($data);
public function update($id, $data);
public function delete($id);
}
Eloquent:
<?php
namespace Modules\ShopOwner\Entities\Repository\Eloquent;
use Illuminate\Database\Eloquent\Model;
use Modules\ShopOwner\Entities\Repository\Contract\ShopsRepository;
use Modules\ShopOwner\Entities\Shops;
class ShopsEloquent implements ShopsRepository
{
protected $model;
public function __construct(Shops $shops)
{
$this->model = $shops;
}
public function getall()
{
return $this->model::with('shopadmin')->get();
}
public function create($data)
{
$this->model::create($data);
}
public function update($id, $data)
{
$this->model::findOrFail($id)->update($data);
}
public function delete($id)
{
$this->model::findOrFail($id)->delete();
}
}
Controller:
<?php
namespace Modules\ShopOwner\Http\Controllers;
use App\Http\Controllers\Controller;
use Auth;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Modules\ShopOwner\Entities\Repository\Contract\ShopsRepository;
use Modules\ShopOwner\Entities\Shops;
use Validator;
class ShopsController extends Controller
{
protected $shops;
public function __construct(ShopsRepository $shops)
{
$this->shops = $shops;
}
public function index()
{
$shops = $this->shops->getall();
return view('shopowner::shops.list', compact('shops'));
}
public function store(Request $request)
{
$data = $request->all();
$this->shops->create($data);
return redirect()->route('SO.shops.index')->with('success', __('shopowner::shops.create_success'));
}
public function update(Request $request, $id)
{
$data = $request->all();
$this->shops->update($id, $data);
return redirect()->route('SO.shops.index')->with('success', __('shopowner::shops.update_success'));
}
public function delete($id)
{
$this->shops->delete($id);
return redirect()->route('SO.shops.index')->with('success', __('shopowner::shops.remove_success'));
}
}
Create a base repository first. then extend this repository. Try this way. It may help you
interface BaseRepository{
public function getall();
public function create($data);
public function update($id, $data);
public function delete($id);
}
class BaseEloquent implements BaseRepository{
protected $model;
public function getall(){
return $this->model->get();
}
....
....
}
interface ShopsRepository extends BaseRepository{
}
class ShopsEloquent extends BaseEloquent implements ShopsRepository{
public function __construct(Shops $shops){
$this->model = $shops;
}
public function getall(){
return $this->model::with('shopadmin')->get();
}
}
I am following this link to implement it
I did below steps to implement the Contract in my existing class.
Below is the class where I will write some logic also before sending it to controller
namespace App\Classes\BusinessLogic\Role;
use App\Classes\DatabaseLayer\Role\RoleDb;
use App\Classes\Contract\Role\IRole;
class RoleBL implements IRole {
public function All() {
return (new RoleDb())->All();
}
}
Database Function
namespace App\Classes\DatabaseLayer\Role;
class RoleDb {
public function All() {
$Roles = \App\Models\Role\RoleModel
::all();
return $Roles;
}
}
Interface
namespace App\Classes\Contract\Role;
interface IRole {
public function All();
}
Service Provider class
namespace App\Providers\Role;
class RoleServiceProvider extends \Illuminate\Support\ServiceProvider {
public function register()
{
$this->app->bind('App\Classes\Contract\Role\IRole', function($app){
return new \App\Classes\BusinessLogic\Role\RoleBL($app['HttpClient']);
});
}
}
Finally in config/app.php in provider wrote below line.
App\Providers\Role\RoleServiceProvider::class
Controller - Constructor
protected $roles;
public function __construct(\App\Classes\Contract\Role\IRole $_roles) {
parent::__construct();
$roles = $_roles;
}
Controller Action method
public function index(IRole $roles) {
$RoleTypes = $roles->All();
}
So far everything works fine if I keep Interface as parameter in method.
if I try to use the variable $roles in index method and remove the variable, it is always null.
Please guide me if I missed anything?
You incorrectly assign the $roles property in your __construct() method.
Replace
$roles = $_roles;
with
$this->roles = $_roles;
and then in your index method do:
$RoleTypes = $this->roles->All();
I have a class in Laravel with a class variable that holds and object
class RegisterController extends Controller {
public $company;
When i set the variable in my index method all goes well
public function index($id = null) {
$this->company = new Teamleader\Company;
When I try to access $this->company from another method it returns
null
This is my full code
class RegisterController extends Controller {
public $company;
public function index($id = null)
{
$this->company = new Teamleader\Company;
// returns ok!
dd($this->company);
return view('register.index');
}
public function register()
{
// returns null
dd($this->company);
}
}
Am I missing something?
Thank you!
You are not __constructing() the class, you are just assigning variable inside a function inside a class, which means it is encapsulated into that function inside that class.
So if you would like to make $this->company global in class, you could use
public function __construct() {
$this->company = new Teamleader\Company;
}
In Laravel 5 you can inject a new instance of Teamleader\Company into the methods you need it available in.
use Teamleader\Company;
class RegisterController extends Controller {
public function index($id = null, Company $company)
{
dd($company);
}
public function register(Company $company)
{
dd($company);
}
}
For Laravel <5 dependency inject into the constructor.
use Teamleader\Company;
class RegisterController extends Controller {
protected $company;
public function __construct(Company $company)
{
$this->company = $company;
}
public function index($id = null)
{
dd($this->company);
}
public function register()
{
dd($this->company);
}
}
Dependency injection is better than manual invocation as you can easily pass a mock object to this controller during testing. If you're not testing, maybe someone else will be in the future, be kind. :-)
I'm developing an API and in the controller the index, store, show, update and destroy methods are all the same except for the Model that is being used.
How would you implement this?
I was thinking about a ActionRepository where I create those methods and will resolve the model somehow. I am not sure how I can reach the model though..
Really would appreciate some feedback on this ;)!
You can do this:
abstract class BaseController extends LaravelController {
protected $repository; // or $model or whatever you need
public function index() { // your logic }
public function show($id) {
// your logic here, for example
return $this->repository->find($id);
// or
return $this->model->find($id);
}
public function create() { // your logic }
public function store() { // your logic }
public function edit($id) { // your logic }
public function update($id) { // your logic }
public function destroy($id) { // your logic }
}
class SomeSolidController extends BaseController {
public function __construct(SomeRepositoryInterface $repository)
{
$this->repository = $repository;
}
}