So I'm working on a small CMS in Laravel 5, and the one of the first things that I don't fully get is passing variables to a view.
I have seen things like
return View('view', array('name' => 'your name here'));
Or variables in a view composer
public function compose($view) {
$view->with(Config::get('configfile'));
}
but I'm still wondering if there is a better/more elegant way to do this. For example, with the first approach, I have to give it that array at every view, which just seems like a hassle, and with the view composers, it just feels like there should be a better solution.
Is there a recommended way to push these variables on the the view?
Also, I'm talking about a set of variables that are needed in every view. for example the name and the slogan of the website.
Thanks.
Have you considered view()->share see the docs Sharing Data with All Views
<?php
namespace App\Providers;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
view()->share('key', 'value');
}
}
it allows you to share a piece to data with all your views. I don't see any reason why you couldn't load all your config in this way if your needing to access it on the majority of views.
You can use Route Model Binding: https://laravel.com/docs/5.2/routing#route-model-binding for model specific data binding. Other than that, there's no (practical) way to do it.
Related
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.
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.
I'm working on building a small CRUD app in Laravel 5. I have a few app wide settings such as "SiteTitle" and "BaseURL" I'd like to give my admins the ability to change from the UI. My whole app uses a base.blade.php template that gets extended to the different views+controllers, this is where these settings would most likely be used.
Something like:
<h1>{{ $setting->SiteName }}</h1>
I have the settings stored in a database table that are tied to a Setting.php model.
I'd rather not everyone of my controller methods query the database for these settings to just pass them up to the template base.blade.php.
What's the best way of creating some type of global setting variable I can reuse throughout the app?
Thanks in advance!
You could create a service provider, say SettingsServiceProvider, that loads all the settings from the database and then caches them. Then on subsequent page loads, it could return cached setting values rather than querying the database, which you should be rightfully concerned about.
Something as simple as:
class SettingsServiceProvider extends ServiceProvider
{
/**
* Register the application services.
*
* #return void
*/
public function register()
{
$this->app->singleton('settings', function ($app) {
return $app['cache']->remember('site.settings', 60, function () {
return Setting::pluck('value', 'key')->toArray();
});
});
}
}
Assuming your settings model is called Setting as per Laravel’s naming conventions. You can then access settings like so:
<h1>{{ array_get(app('settings'), 'site.name') }}</h1>
If you wanted a prettier way of accessing settings, you could create a helper function:
function setting($key)
{
return array_get(app('settings'), $key);
}
Which would make usage like this:
<h1>{{ setting('site.name') }}</h1>
Almost emulating the config() helper function’s usage.
If your app uses multiple controllers then you could define a parent controller that gets extended by all your other controllers. Within the parent controller's constructor you can retrieve the settings data and store it in a class property which will be available to all of the child controller classes. Your child controllers can simply pass this data to the view.
I have a model which is used by two modules. I don't want to duplicate the code for that model into each modules.
For example I have 2 modules. First takes the blog posts from model and print them for normal users, and the other one prints them for admin users but with a few more options (which are set in the view). I would have the same model in two places. And.. that's bad.
Just a piece of code:
<?php
namespace Blog\Model;
use Zend\Db\Adapter\Adapter;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\AbstractTableGateway;
class BlogTable extends AbstractTableGateway
{
protected $table = 'blog_posts';
public function __construct(Adapter $adapter)
{
$this->adapter = $adapter;
$this->initialize();
}
/**
* Gets the blog post list
*
* #return array
**/
public function fetchAll()
{
//..
}
}
So, how should I design this application?
The biggest question might be why you separate the administrative side outside of the 'Blog-Scope'. An administrative Module should only be the front-end to gather all backend-options (if that makes any sense)
However to get back into your question: you can simply include those classes from model A into model B, like use Blog\Model\BlogTable
Ultimately though i see management of a module as a responsible of the Blog-Module itself, as hinted within the first paragraph.
Edit: One thing i forgot to mention. Ideally if you decide to go the dependant approach, your module should make the BlogTable accessible through a service. That way your ModuleAdmin only has to do something like $serviceLocator->get('my-blog-table') which is a much more clean approach.
You could achieve this by having a base/shared module that provides various models, helpers etc.
But personally I would be looking to architect modules around functionality rather than user access levels.
I have a controller/model for projects. so this controls the projects model, etc, etc. I have a homepage which is being controlled by the pages_controller. I want to show a list of projects on the homepage. Is it as easy as doing:
function index() {
$this->set('projects', $this->Project->find('all'));
}
I'm guessing not as I'm getting:
Undefined property: PagesController::$Project
Can someone steer me in the right direction please,
Jonesy
You must load every model in the controller class by variable $uses, for example:
var $uses = array('Project');
or in action use method
$this->loadModel('Project');
In my opinion the proper way to do this is add a function to your current model which instantiates the other model and returns the needed data.
Here's an example which returns data from the Project model in a model called Example and calls the data in the Example controller:
Using Project Model inside Example Model:
<?php
/* Example Model */
App::uses('Project', 'Model');
class Example extends AppModel {
public function allProjects() {
$projectModel = new Project();
$projects = $projectModel->find('all');
return $projects;
}
}
Returning that data in Example Controller
// once inside your correct view function just do:
$projects = $this->Example->allProjects();
$this->set('projects', $projects);
In the Example view
<?php
// Now assuming you're in the .ctp template associated with
// your view function which used: $projects = $this->Example->allProjects();
// you should be able to access the var: $projects
// For example:
print_r($projects['Project']);
Why is this "better" practice than loading both models into your controller? Well, the Project model is inherited by the Example model, so Project data now becomes part of the Example model scope. (What this means on the database side of things is the 2 tables are joined using SQL JOIN clauses).
Or as the manual says:
One of the most powerful features of CakePHP is the ability to link relational mapping provided by the model. In CakePHP, the links between models are handled through associations.
Defining relations between different objects in your application should be a natural process. For example: in a recipe database, a recipe may have many reviews, reviews have a single author, and authors may have many recipes. Defining the way these relations work allows you to access your data in an intuitive and powerful way. (source)
For me it's more reasonable to use requestAction. This way the logic is wrapped in the controller.
In example:
//in your controller Projects:
class ProjectsController extends AppController {
function dashboard(){
$this->set('projects', $this->Project->find('all'));
}
$this->render('dashboard');
}
Bear in mind that you need to create dashboard.ctp in /app/views/projects of course.
In the Page's dashboard view (probably /app/views/pages/dashboard.ctp) add:
echo $this->requestAction(array('controller'=>'projects', 'action'=>'dashboard'));
This way the logic will remain in the project's controller. Of course you can request /projects/index, but the handling of the pagination will be more complicated.
more about requestAction(). but bear in mind that you need to use it carefully. It could slow down your application.