Laravel, Singleton - how to send data to all controllers? - laravel

I'm doing shopping site. I made Cart Model, which is Singleton. My shopping cart exists in session always ( no matter or User is login or not ). Now I have to invoke every time in every Controllers and actions getInstance to check or there's key "cart".
Is there a possibility to do this automaticly for all views?
Here is code of my Singleton:
class Cart
{
private $cartModel;
private static $instance;
private function __construct()
{
$this->cartModel = new CartModel();
$cart = Session::get('cart');
if ($cart == null) {
Session::put('cart', array());
}
}
private function __clone()
{
}
public static function getInstance()
{
if (self::$instance === null) {
self::$instance = new Cart();
}
return self::$instance;
}
public function get(){
return Session::get('cart');
}
}
And here for example how it looks in Controllers and actions:
class StoreController extends Controller
{
public function mainSite()
{
$cart=Cart::getInstance()->get();
return View('zoo');
}
public function showCategory($categoryName)
{
$cart=Cart::getInstance()->get();
$category = new Category();
$categoryId = (int)$category->getCategoryId($categoryName);
$subCategories = Subcategory::where('category_id', $categoryId)->get();
return View('zoo-category', ['subCategories' => $subCategories, 'categoryName' => $categoryName]);
}
public function showSubcategory()
{
$cart=Cart::getInstance()->get();
}
I have to do this all the time: $cart=Cart::getInstance()->get();
Is there a possibility to do this only one time?

You can take advantage of Laravel's dependency injection. Bind your class to the IoC container and you can either access it through the IoC container or you can have Laravel automatically inject this into your controllers in several different ways.
Read more here: https://laravel.com/docs/5.4/container

Add it to base controller's constructor so that it gets called on every controller method.
// app/Http/Controllers/Controller.php
protected $cart;
public function __construct()
{
$this-> cart = Cart::getInstance()->get();
}
But i honestly see no point in your singleton class. All it does is set the cart with an empty array when it's not defined. Also $this->cartModel = new CartModel(); is this ever used?

Related

call the another function within a function

In laravel I want to call a function within function to make recursive.I caught the route error.how to call the function 'recursive in tableFetch'
class queryTest extends Controller
{
public function tableFetch() {
recursive();
}
function recursive(){
//condition
}
}
I want to do it for check the manager of the given person and then get the manager of the fetched value in query so need to do it recursive
A controller is not a good place for this. Instead, manage it in your Person Model(or whatever you have).
Everyone has a manager. So, your model has HasOne relation to itself.
Person Model:
public function manager()
{
return $this->hasOne(Person::class, 'manager_id');
}
Now if you need to check the manager of given person untill you meet a certain condition you can do it inside the model and get the result in the controller.
public function checkManager()
{
$manager = $this->manager
if (check manager)
return $manager;
//check for the last manager
return $this->manager ? $this->checkManager() : null;
}
Inside controller
function index()
{
$person = Person::find($id);
$manager = $person->checkManager();// this will do the recursive you need
}
Do something like this
class queryTest extends Controller
{
public function tableFetch() {
$this->recursive();
}
function recursive(){
//condition
}
}
you need to ask more precise details about your needs, because Laravel has some complications.
try doing this :
class queryTest extends Controller
{
public function tableFetch() {
$this->recursive();
}
public function recursive() {
//condition
}
}

Laravel - Delete if no relationship exists

Below is the one of the model. I would like to delete a Telco entry only if no other model is referencing it? What is the best method?
namespace App;
use Illuminate\Database\Eloquent\Model;
class Telco extends Model
{
public function operators()
{
return $this->hasMany('App\Operator');
}
public function packages()
{
return $this->hasMany('App\Package');
}
public function topups()
{
return $this->hasMany('App\Topup');
}
public function users()
{
return $this->morphMany('App\User', 'owner');
}
public function subscribers()
{
return $this->hasManyThrough('App\Subscriber', 'App\Operator');
}
}
You can use deleting model event and check if there any related records before deletion and prevent deletion if any exists.
In your Telco model
protected static function boot()
{
parent::boot();
static::deleting(function($telco) {
$relationMethods = ['operators', 'packages', 'topups', 'users'];
foreach ($relationMethods as $relationMethod) {
if ($telco->$relationMethod()->count() > 0) {
return false;
}
}
});
}
$relationships = array('operators', 'packages', 'topups', 'users', 'subscribers');
$telco = Telco::find($id);
$should_delete = true;
foreach($relationships as $r) {
if ($telco->$r->isNotEmpty()) {
$should_delete = false;
break;
}
}
if ($should_delete == true) {
$telco->delete();
}
Well, I know this is ugly, but I think it should work. If you prefer to un-ugly this, just call every relationship attributes and check whether it returns an empty collection (meaning there is no relationship)
If all relationships are empty, then delete!
After seeing the answers here, I don't feel copy pasting the static function boot to every models that need it. So I make a trait called SecureDelete. I put #chanafdo's foreach, inside a public function in SecureDelete.
This way, I can reuse it to models that need it.
SecureDelete.php
trait SecureDelete
{
/**
* Delete only when there is no reference to other models.
*
* #param array $relations
* #return response
*/
public function secureDelete(String ...$relations)
{
$hasRelation = false;
foreach ($relations as $relation) {
if ($this->$relation()->withTrashed()->count()) {
$hasRelation = true;
break;
}
}
if ($hasRelation) {
$this->delete();
} else {
$this->forceDelete();
}
}
}
Add use SecureDelete to the model that needs it.
use Illuminate\Database\Eloquent\Model;
use App\Traits\SecureDelete;
class Telco extends Model
{
use SecureDelete;
public function operators()
{
return $this->hasMany('App\Operator');
}
// other eloquent relationships (packages, topups, etc)
}
TelcoController.php
public function destroy(Telco $telco)
{
return $telco->secureDelete('operators', 'packages', 'topups');
}
In addition, instead of Trait, you can also make a custom model e.g BaseModel.php that extends Illuminate\Database\Eloquent\Model, put the function secureDelete there, and change your models to extends BaseModel.

How to use multiple routes that link to same page in laravel?

I have 2 controllers. One manages category and other slider. They have no relation between them. They are on same homepage in different sections. So I want to show both category and slider value that is there in database.
I tried
Route::get('/', ['uses'=>'SliderController#homepage','as'=>'homepage']);
Route::get('/', ['uses'=>'CategoryController#homepage','as'=>'categoryHomepage']);
If I do that the second one is overwriting the first one.
Is there a way from which I can pass both routes so that I can use both values in my homepage.
Thanks!
Have you tried dependency injection.
1 Single route
Route::get('/home', ['uses'=>'SliderController#index','as'=>'homepage']);
2 Create a data passing controller
use View;
class SliderController extends Controller {
private $repository;
public function __construct(DataRepository $repository)
{
$this->repository = $repository;
}
public function index(DataRepository $repository)
{
return View::make('home.index')->with('data', $this-repository->getData());
}
}
3 DataRepository class fetch there records
class DataRepository {
public getData()
{
$data = array();
$data['category'] = Category::all();
$data['slider'] = Slider::all();
return $data;
}
}
After above three steps, DataRepository will automatically inject data to your controller. Reference taken from here.

Call method from (custom) controller class in Magento

I'm working with the M2e extension for Magento. Now I want to call a method of the class Ess_M2ePro_Adminhtml_ListingController in the file app/code/community/Ess/M2ePro/controllers/Adminhtml/ListingController.php.
But I don't know, how. I can't create an object or model to get access to the class to use the methods. Maybe it's not a good idea to call this controller methods directly, but in my case (remove a associated magento product to an ebay listing) it's required to call this methods.
In general these actions are called from the magento backend. I've also tried to create an admin_html session, but at the moment I don't have any further ideas.
Here's an example, how it looks like. I'm working with regular PHP-code, nothing special:
class Ess_M2ePro_Adminhtml_ListingController extends Ess_M2ePro_Controller_Adminhtml_MainController
{
//#############################################
protected function _initAction()
{
/** removed **/
}
protected function _isAllowed()
{
return Mage::getSingleton('admin/session')->isAllowed('m2epro/listings/listing');
}
//#############################################
public function indexAction()
{
/** removed **/
}
//#############################################
public function searchAction()
{
/** removed **/
}
public function searchGridAction()
{
/** removed **/
}
public function lockListingNowAction()
{
$listingId = (int)$this->getRequest()->getParam('id');
$component = $this->getRequest()->getParam('component');
$lockItemParams = array(
'id' => $listingId,
'component' => $component
);
$lockItem = Mage::getModel('M2ePro/Listing_LockItem',$lockItemParams);
if (!$lockItem->isExist()) {
$lockItem->create();
}
exit();
}
}
And I'm looking for something like this:
$test = Mage::getModel('M2ePro/Ess_M2ePro_Adminhtml_ListingController')->lockListingNowAction();
You shouldn't call methods from an other controller. Specially in your case, when you have exit at the end of the method.
You can use the _forward method if you are in a controller:
$this->_forward($action = 'lockListingNowAction', $controller = 'adminhtml_listing', $module = 'M2ePro', $params = array('id'=>$id)) //controller name may be different
But the cleanest way is to have the code you need in a helper and call the code from that helper in both controllers.

Laravel4 - Saving a model with multiple relationships/foreign keys

I've tried to understand a process of saving a model with multiple relationships but I still can't figure out how to do it "kosher" way.
To begin with - I have an Event model that belongs to a category (Eventcat) and a Location:
// Event.php
class Event extends Eloquent {
protected $table = 'events';
public function location()
{
return $this->belongsTo('Location');
}
public function eventcat()
{
return $this->belongsTo('Eventcat');
}
public function users()
{
return $this->belongsToMany('User');
}
}
// Location.php
class Location extends Eloquent
{
protected $table = 'locations';
public function events()
{
return $this->hasMany('Event');
}
}
// Eventcat.php
class Eventcat extends Eloquent
{
protected $table = 'eventcats';
public function events()
{
return $this->hasMany('Event');
}
}
I've seeded the database with a few categories and locations and now I trying to get events saving work. I thought that the $event->eventcat()->associate( $eventcat ) would work but I got a Call to undefined method eventcat() error.
public function postCreateEvent() {
$event = new Event();
$eventcat = Eventcat::find( Input::get('event-create-eventcat[]') );
$location = Location::find( Input::get('event-create-location[]') );
$event->title = Input::get('event-create-title');
$event->description = Input::get('event-create-description');
$event->price = Input::get('event-create-price');
$event->start_date = Input::get('event-create-start_date');
$event->end_date = Input::get('event-create-end_date');
$event->eventcat()->associate( $eventcat );
$event->location()->associate( $location );
$event->save();
}
I've read the documentation, API and a few threads here but I still can't figure out the best way to deal with this.
Thanks for replies!
I would actually bet that you have a conflict in your class name. Laravel contains an Event class and I wonder if that isn't what's being called in your code. As a quick test, you could rename your class FooEvent and see if it works.
The best solution is probably namespacing your model (see http://chrishayes.ca/blog/code/laravel-4-methods-staying-organized for a quick intro) so that your model can still be called Event without conflicting with the builtin class.

Resources