Laravel: Get access to class-variable from public static function (basic oop issues)

28,586

Solution 1

Static methods do not have access to $this. $this refers to an instantiated class (an object created with a new statement, e.g. $obj = new ContentController()), and static methods are not executed within an object.

What you need to do is change all the $this to self, e.g. self::$text to access a static variable defined in your class. Then you need to change public $text = ''; to public static $text = '';

This is why static methods/variables are bad practices most of the time...

Not an expert at Laravel, but I'm sure you don't need to use static methods to pass variables into templates... If that is the case, I'm staying the hell away from Laravel...

Solution 2

You may try something like this (In the case of static):

class ContentController extends BaseController {

    public static $text = null;

    public static function getContent($description)
    {
        $content = Content::where('description', $description)->first();
        return static::$text = $content->text;
    }
}

Read the other answer to understand the difference; also read about Late Static Bindings but instead...

You may try something like this in Laravel to avoid static:

class ContentController extends BaseController {

    public $text = null;

    public function getContent($description)
    {
        $content = Content::where('description', $description)->first();
        return $this->text = $content->text;
    }
}

Use it like this:

{{ App::make('ContentController')->getContent('starttext') }}

Also this:

{{ with(new ContentController)->getContent('starttext') }}

Or this (Even without Laravel):

{{ (new ContentController)->getContent('starttext') }}

Solution 3

In Laravel 5.7 the or operator has been removed so {{ $text or 'Default' }} doesn't work anymore. New operator is ??. Beginning with Laravel 5.7 it should be {{ $text ?? 'Default' }}

Share:
28,586
Kristo
Author by

Kristo

I´m a Designer, Web-Developer, Illustrator and Filmmaker based in Mannheim, Germany

Updated on February 04, 2020

Comments

  • Kristo
    Kristo over 4 years

    EDIT

    In the meantime this question is been visited a few times. Just to share what I´ve learned with the help of stackoverflow and other resources I´d not recommend using the technique I was asking for. A cleaner way is to attach a variable containing the database-text within the controller:

    $txt = Model::find(1);
    return view('name', array('text' => $txt->content);
    

    Now you can access text in your view like so

    {{ $text ?? 'Default' }}
    

    But if you´re currently also hustling with basic oop and/or mvc architecture read on. Maybe it helps :-)


    ORIGINAL QUESTION

    I´m trying to output some text loaded from db. This is my setup:

    View:

    {{ ContentController::getContent('starttext') }}
    

    Controller:

    class ContentController extends BaseController {
    
        public $text = '';
    
        public static function getContent($description)
        {
            $content = Content::where('description', $description)->get();
            $this->text = $content[0]->text;
    
            return $this->text;
        }
    
    }
    

    I was trying various ways to declare a class variable and access it in my function but I always end up with:

    Using $this when not in object context

    tbh I think I lack some basic oop knowledge :-D

    • Sergiu Paraschiv
      Sergiu Paraschiv almost 10 years
      A view does not have explicit access to the controller class ($this does not exist in that context). It's a basic MVC principle, separation of logic (controller) from presentation (view). The docs pretty clearly show this example: View::make('greeting', array(...stuff here...)) where "stuff" is whatever you need to pass to the view, from the controller. Let me put it this way: read the docs (laravel.com/docs/responses).
    • Sergiu Paraschiv
      Sergiu Paraschiv almost 10 years
      Also, you should first start with the docs on PHP OOP (php.net/manual/en/language.oop5.php). The code you wrote makes no sense whatsoever.
    • Kristo
      Kristo almost 10 years
      When sticking to MVC principles you´re definitely right. But why not using the mighty routing-system of Laravel for render some simple Views where no user input is given?
    • Sergiu Paraschiv
      Sergiu Paraschiv almost 10 years
      If it's Route::get '/' return View::make('homepage') then yes, don't over-engineer. It's not only about the user input. You have Eloquent DB access in a controller with a method that responds with a Blade view. Please don't do Eloquent queries in routes.php. Please do separate logic, presentation and data storage.