I have a few vars in my app that I would like to share through multiple views and requests. Basically I have a custom Layout which I load like that:
#section('stylesheet')
{{ HTML::style(URL::to('custom_stylesheet/'.$slug)) }}
#stop
I somehow have to send the "slug" var to every request and action and/or controller I need and I need a few. It's a shop from a startpage to checkout, last step.
How can I achieve that? Is View::share() a solution or a cookie?
The URL structure is like that:
www.domain.tld/name/{client_slug}/{event_slug}/<all other variables>
like /overview or /checkout or /details/{event_id}
Thanks!
If you need to specify views, use a View Composer:
View::composer(['view-a', 'view-b'], function($view)
{
$client_slug = 'whatever you need to do to calculate the slug';
$view->with('client_slug', $client_slug);
$view->with('event_slug', $event_slug);
$view->with('variable1', $variable1);
});
Or, as you said, View Share to share with all of them:
View::share('client_slug', $client_slug);
You can create a file for this purpose, something like app/composers.php and load it in your app/start/global.php:
require app_path().'/composers.php';
And you can consider using Session vars too, which keeps data through multiple requests:
Session::put('client_slug', $client_slug);
And get it with
$client slug = Session::put('client_slug');
But if this is a View thing only, View Composers are the way to go.
Using Session and View Composer them togheter is simple, you can set in one request:
Session::put('client_slug', $client_slug);
And in the next request you can send it to your views:
View::composer(['view-a', 'view-b'], function($view)
{
if (Session::has('client_slug'))
{
$view->with('client_slug', Session::get('client_slug'));
}
else
{
$view->with('client_slug', 'default-slug-or-whatever-you-would-do');
}
});
I'm pretty sure you can do this:
if (Cache::has('slug'))
{
View::share('slug', Cache::get('slug'););
}
Then just place that in your route file, or perhaps your base controller constructor, where ever you want it.
Then when you first get given the slug:
Cache::put('slug', $slug, 60); //60 minutes
Related
So essentially all of my views are using the header.blade.php since I am including it in my master layout. I need to pass data to the header on every single view. Is there a way to pass data just to the include rather than passing the data for the header in each view?
You don't need to do that, but you can:
All variables that are available to the parent view will be made
available to the included view. Even though the included view will
inherit all data available in the parent view, you may also pass an
array of extra data to the included view:
#include('view.name', ['some' => 'data'])
One option if you're trying to send data only to the included view is to use a view composer. They will fire even in the case of trying to prepare a view for #include
view()->composer('header', function($view) {
$view->with('data', 'some data');
});
actually the very best and faster method of sharing data to all views could be just using the
AppServiceProvider
instead of Jeff's answer you can use the share method instead of the composer method and achieve your goal faster.
Just pass the data you want in the boot method of the AppServiceProvider like following
public function boot()
{
View::share('key', 'value');
}
for more check this
I'm trying to implement a very simple page tracking system with Laravel, just to know which pages are most accessed.
At first I thought of create a table with access date, request URL (from Request::path()) and user id, as simple as that.
But I'd have to show page titles on reports, and for that I need some way to translate the request URI to its page title. Any ideas for that? Is there a better way to accomplish this?
Currently I set page titles from Blade view files, through #section('title', ...).
Thank you in advance!
You can use Google Analytics to show pretty and very efficient reports. With the API, you can also customize the reports and (for example) show the pages titles.
If you want to develop it by yourself, I think that the best solution is to write an after filter that can be called after each page loading. One way of setting the title, in this case, is to use flash session variable (http://laravel.com/docs/session#flash-data) :
// routes.php
Route::group(array('after' => 'log'), function()
{
Route::get('users', 'UserController#index');
}
// filters.php
Route::filter('log', function() {
Log::create(array('title' => Session::get('title'), '...' => '...'));
}
// UserController.php
public function index()
{
Session::flash('title', 'Users Page');
// ...
}
// layout.blade.php
<head>
<title>{{ Session::get('title') }}</title>
...
I know this has already been answered but I would like to add that I've published a package that can be easily implemented to track page views for Laravel (if they are Eloquent ORM instances) in specific date ranges: last day, week, month or all time.
https://github.com/marcanuy/popularity
In Laravel, we all pass data to our view in pretty much the same way
$data = array(
'thundercats' => 'Hoooooooooooh!'
);
return View::make('myawesomeview', $data);
But is there some way to add default variables to the view without having to declare it over and over in $data? This would be very helpful for repeating variables such as usernames, PHP logic, and even CSS styles if the site demands it.
Use View Composers
View composers are callbacks or class methods that are called when a
view is created. If you have data that you want bound to a given view
each time that view is created throughout your application, a view
composer can organize that code into a single location. Therefore,
view composers may function like "view models" or "presenters".
Defining A View Composer :
View::composer('profile', function($view)
{
$view->with('count', User::count());
});
Now each time the profile view is created, the count data will be bound to the view. In your case, it could be for id :
View::composer('myawesomeview', function($view)
{
$view->with('id', 'someId');
});
So the $id will be available to your myawesomeview view each time you create the view using :
View::make('myawesomeview', $data);
You may also attach a view composer to multiple views at once:
View::composer(array('profile','dashboard'), function($view)
{
$view->with('count', User::count());
});
If you would rather use a class based composer, which will provide the benefits of being resolved through the application IoC Container, you may do so:
View::composer('profile', 'ProfileComposer');
A view composer class should be defined like so:
class ProfileComposer {
public function compose($view)
{
$view->with('count', User::count());
}
}
Documentation and you can read this article too.
There are couple of ways, so far I have been experiment with some.
1.Use singleton, you can put it in routes.php
App::singleton('blog_tags', function() {
return array(
'Drupal' => 'success',
'Laravel' => 'danger',
'Symfony' => 'dark',
'Wordpress' => 'info'
);
});
2.Use Settings bundle, download here. https://github.com/Phil-F/Setting. You can put this in controller or template.
Setting::set('title', 'Scheduler | Mathnasium');
3.Use View share, pretty much use it in your template
Controller: Views::share('theme_path', 'views/admin/');
Template: <link href="{{ $theme_path }}/assets/bootstrap.min.css"/>
4.My current sample setup, I wrote a construct in HomeController.
public function __construct()
{
// Define a theme namespace folder under public
View::addLocation('../public/views/admin');
View::addNamespace('admin', '../public/views/admin');
View::share('theme_path', 'views/admin/');
// Set default page title
Setting::set('title', 'Scheduler | Mathnasium');
Setting::set('description', 'daily customer scheduler.');
Setting::set('keywords', ['Reservation', 'Planner']);
Setting::set('page-title', '');
}
#enchance, as an alternative to using '*', as mentioned in your comment, perhaps a View::share would help you too. From the Laravel documentation:
You may also share a piece of data across all views:
View::share('name', 'Steve');
Excerpt is from http://laravel.com/docs/responses
Yep there absolutely is a way - see here on view composers.
You can use that to add data to a view or set of views.
I am new to Laravel 4 and am having a hard time grasping routes. I have a frontend to my site and a backend. All the stuff that happens on the backend I want to have displayed under example.com/dashboard/.... I also want to use resourceful controllers. What do I need to setup in routes.php to have it so I can always refer to my users controller but have it all happen under dashboard in the URL?
Example:
I link to users/edit/1 but in the URL looks like example.com/dashboard/users/edit/1. Dashboard should have an index page (so example.com/dashboard actually shows a page) but all other URLs are appended to that.
I think this is covered pretty well in the Larvel 4 Documentation.
Unless I'm misunderstanding, this should get you the desired results for your example case:
Route::get('dashboard', 'DashboardController#index');
Route::get('dashboard/users/edit/{id}', 'UsersController#edit');
etc.
// edit
Alternatively, using a Closure callback, you could do something like this:
Route::get('dashboard/users/{var1}/{var2?}', function($var1, $var2 = null)
{
$controller = new UsersController;
return $controller->{$var1}($var2);
});
Which wouldn't require you to specify each and every route. Or, as I mentioned below in comments, you could use a Resource Controller if it suits your needs.
So I'm trying to page items on my index page using the paginator and custom routes. It's all through the index action, but the index action can show items sorted by newest, votes, active or views. Right now, the URL looks like this:
items/index/sort:created/direction:desc
And if you aren't on page one, it looks like this:
items/index/sort:created/direction:desc/page:2
I'd like to use the router to have it look like this:
newest/
I can get that far with this route:
Router::connect(
'/newest/*',
array('controller'=>'items', 'action'=>'index', 'sort'=>'created', 'direction'=>'desc')
);
However, the pager links don't follow the route. As soon as you click next page, you're back to:
items/index/sort:created/direction:desc/page:2
How can I make this follow the router and give me what I want? Keep in mind, it's all from the same controller action, I'm trying to route the sort parameters of pagination basically.
For me your code is working (I've tested your example). Have you done something unusual with the paginator helper?
Here is my Routes:
Router::connect('/newest/*',array('controller'=>'tests', 'action'=>'index', 'sort'=>'age', 'direction'=>'desc'));
Router::connect('/oldest/*',array('controller'=>'tests', 'action'=>'index', 'sort'=>'age', 'direction'=>'asc'));
And here are the urls which I've seen when I sort by age column:
http://localhost/cakephp/1.3.0/newest/page:1
http://localhost/cakephp/1.3.0/newest/page:2
http://localhost/cakephp/1.3.0/newest/page:3
And oldest:
http://localhost/cakephp/1.3.0/oldest/page:1
http://localhost/cakephp/1.3.0/oldest/page:2
http://localhost/cakephp/1.3.0/oldest/page:3
And it's working with all links in the pager (first, prev, 1,2,3 next, last).
You want to include the passed args I think. Something like this,
$this->params = $this->passedArgs();
Have a check here also, http://book.cakephp.org/view/46/Routes-Configuration
Otherwise I would extend the HTML Helper to create my own link method which read in the parameters from the url and created a link accordingly. Then you could manage your own links from your own helper :)
Don't forget that you need to have checks in the index action to deal with this. Personally I would be far more inclined to create an action in the controller for each of these.
function newest(){
}
function votes(){
}
function active(){
}
//etc