I have a controller in already done in Livewire and I’m trying to create a new Laravel controller and corresponding Laravel blade file (the purpose is that I was asked to complete the form in Laravel and then migrate it to livewire), and the question is that is it possible to access those Livewire variables into a Laravel controller and blade or need to create the new blade file and controller in Livewire right away? because I am still new in Livewire
public $application_type;
public $token;
public $application_id;
public $creditRows = [];
public $gigRows = [];
public $invIncomeRows = [];
public $loansRows = [];
public function render()
{
$country = country('my');
$states = $country->getDivisions();
$income_informations = DB::table('income_informations')->get();
$bank_names = DB::table('bank_names')->get();
$salutations = DB::table('salutations')->get();
$genders = DB::table('genders')->get();
return view('livewire.individual-loan-application-form-component',
compact('states', 'income_informations', 'bank_names', 'salutations', 'genders'));
}
Thanks a lot
Livewire works the same as Laravel when it comes to passing variables; they share the variables to the given view. If you were to include child components or parts, then the variables would be accessible there. However if you want them in a completely different view, you'd need to redefine those variables in a different controller/Livewire component.
I have a custom view that creates a tab on a node page. I have several content types, but I only want the tab to show on some of them. If this were a regular route, I'd just throw a custom_access under requirements, but there doesn't seem to be a way to do that with routes created outside a routing.yml file.
Is there a reasonable way to do this?
You need to create custom route subscriber. File custom_module.services.yml:
services:
custom_module.route_subscriber:
class: Drupal\custom_module\Routing\RouteSubscriber
tags:
- { name: event_subscriber }
File RouteSubscriber.php:
<?php
namespace Drupal\custom_module\Routing;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;
/**
* Listens to the dynamic route events.
*/
class RouteSubscriber extends RouteSubscriberBase {
/**
* {#inheritdoc}
*/
protected function alterRoutes(RouteCollection $collection) {
if($route = $collection->get('view.<view_name>.<view_bundle>')){ // Need to change view_name and view_bundle.
$route->setRequirement(
'_custom_access',
'\Drupal\custom_module\Routing\RouteSubscriber::viewsAccess'
);
}
}
public function viewsAccess() {
return AccessResult::allowedIf(
// Add condition when view has access
);
}
}
I'm using ML.NET in an ASP.NET Core application, and I am using the following code in Startup:
var builder = services.AddPredictionEnginePool<Foo, Bar>();
if (File.Exists("model.zip"))
{
builder.FromFile(String.Empty, "model.zip", true);
}
If model.zip doesn't exist, I create it later in the middleware. How do I add it to the PredictionEnginePool that is injected?
There are no options to load a model via PredictionEnginePool, and instantiating or injecting a PredictionEnginePoolBuilder isn't an option as it requires IServiceCollection (so must be configured during Startup.ConfigureServices).
The only option I can see at the moment is to set a flag if the file doesn't exist at startup, and then restart the service after model.zip is created in the middleware later on (using IApplicationLifetime.StopApplication), but I really don't like this as an option.
PredictionEnginePool is designed in such a way that you can write your own ModelLoader implementation. Out of the box, Microsoft.Extensions.ML has 2 loaders, File and Uri. When those don't meet your needs, you can drop down and write your own.
See https://github.com/dotnet/machinelearning-samples/pull/560 which changes one of the dotnet/machine-learning samples to use an "in-memory" model loader, it doesn't get the model from a file or a Uri. You can follow the same pattern and write whatever code you need to get your model.
public class InMemoryModelLoader : ModelLoader
{
private readonly ITransformer _model;
public InMemoryModelLoader(ITransformer model)
{
_model = model;
}
public override ITransformer GetModel() => _model;
public override IChangeToken GetReloadToken() =>
// This IChangeToken will never notify a change.
new CancellationChangeToken(CancellationToken.None);
}
And then in Startup.cs
services.AddPredictionEnginePool<ImageInputData, ImageLabelPredictions>();
services.AddOptions<PredictionEnginePoolOptions<ImageInputData, ImageLabelPredictions>>()
.Configure(options =>
{
options.ModelLoader = new InMemoryModelLoader(_mlnetModel);
});
How can I in Laravel 5 make global variable which will be available in all Blade templates?
Option 1:
You can use view::share() like so:
<?php namespace App\Http\Controllers;
use View;
//You can create a BaseController:
class BaseController extends Controller {
public $variable1 = "I am Data";
public function __construct() {
$variable2 = "I am Data 2";
View::share ( 'variable1', $this->variable1 );
View::share ( 'variable2', $variable2 );
View::share ( 'variable3', 'I am Data 3' );
View::share ( 'variable4', ['name'=>'Franky','address'=>'Mars'] );
}
}
class HomeController extends BaseController {
//if you have a constructor in other controllers you need call constructor of parent controller (i.e. BaseController) like so:
public function __construct(){
parent::__construct();
}
public function Index(){
//All variable will be available in views
return view('home');
}
}
Option 2:
Use a composer:
Create a composer file at app\Composers\HomeComposer.php
NB: create app\Composers if it does not exists
<?php namespace App\Composers;
class HomeComposer
{
public function compose($view)
{
//Add your variables
$view->with('variable1', 'I am Data')
->with('variable2', 'I am Data 2');
}
}
Then you can attached the composer to any view by doing this
<?php namespace App\Http\Controllers;
use View;
class HomeController extends Controller{
public function __construct(){
View::composers([
'App\Composers\HomeComposer' => ['home'] //attaches HomeComposer to home.blade.php
]);
}
public function Index(){
return view('home');
}
}
Option 3:
Add Composer to a Service Provider, In Laravel 5 I prefer having my composer in App\Providers\ViewServiceProvider
Create a composer file at app\Composers\HomeComposer.php
Add HomeComposer to App\Providers\ViewServiceProvider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use View;
use App\Composers\HomeComposer;
use Illuminate\Support\Facades\Blade;
class ViewServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
//add to all views
view()->composer('*', HomeComposer::class);
//add to only home view
//view()->composer('home', HomeComposer::class);
}
}
Create a new Service Provider as suggested in here
Add your new Service Provider to the configuration file (config/app.php).
In the boot method of your new Service Provider use:
View::share( 'something_cool', 'this is a cool shared variable' );
Now you are ready to use $something_cool in all of your views.
Hope this helps.
Searching for solution of the same problem and found the best solution in Laravel documentation. Just use View::share in AppServiceProvider like this:
View::share('key', 'value');
Details here.
You can do this with view composers. View composers are executed when a template is loaded. You can pass in a Closure with additional functionality for that view. With view composers you can use wildcards. To make a view composer for every view just use a *.
View::composer('*', function($view)
{
$view->with('variable','Test value');
});
You can also do this without a closure as you can see in the docs.
View::composer('*', 'App\Http\ViewComposers\ProfileComposer');
The profile composer class must have a compose method.
View composers are executed when a view is rendered. Laravel has also view creators. These are executed when a view is instantiated.
You can also choose to use a BaseController with a setupLayout method. Then every view which you will load is loaded through the setupLayout method which adds some additional data. However, by using view composers you're pretty sure that the code is executed. But with the BaseController approach you've more flexibility because you can skip the loading of the extra data.
EDIT: As mentioned by Nic Gutierrez you can also use view share.
Also, you can do this in the Route.php file:
view()->share('variableName', $variable);
I would rather use middleware with the view() facade helper. (Laravel 5.x)
Middleware is easier to mantain and does not make a mess in the controllers class tree.
Steps
Create the Middleware
/app/Http/Middleware/TimezoneReset.php
To create a middleware you can run php artisan make:middleware GlobalTimeConfig
share() the data you need shared
<?php
namespace App\Http\Middleware;
use Closure;
class GlobalTimeConfig
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$time_settings = [
'company_timezone' => 'UTC',
'company_date_format' => 'Y-m-d H:i:s',
'display_time' => true,
];
view()->share('time_settings', $time_settings);
return $next($request);
}
}
Register the newly created middleware
Add the middleware to your middleware route group as per example below
/app/Http/Kernel.php
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\GlobalTimeConfig::class,
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
Access data from templates
Access the data from any template with the given key in the View::share() method call
eg.:
Company timezone: {{ $time_settings['company_timezone'] }}
EDIT:
Nic Gutierrez's Service Provider answer might be a better (or the best) solution.
and you can give array not just View::share('key', 'value');
can put array like View::share(['key'=>'value','key'=>'value'])
You can add in Controller.php file:
use App\Category;
And then:
class Controller extends BaseController {
public function __construct() {
$categories = Category::All();
\View::share('categories', $categories);
}
}
you can flash it into the session, you can define it in the .env file (static vars)
My template layout blade doesn't render when the url is a subfolder.
I made a test example to check:
URL/tests is okay
but
URL/tests/1/edit loses the outer layout template and only renders the content.
Testcontroller:
class TestController extends AdminController {
protected $layout = 'layouts.admin';
public function index()
{
// load the view
$this->layout->content=View::make('tests.index');
}
public function edit($id)
{
//
$course=Course::find($id);
return View::make('tests.edit')->with(array('course'=>$course));
}
}
layout admin.blade.php
<html><body>
{{ $content }}
</body>
</html>
tests/index.blade.php
hello
/tests renders source full layout html code and works fine on proper site examples
tests/edit.blade.php
edit
/tests/1/edit renders with NO layout HTML
There are various ways of using blade but I thought the easiest was with protected layout but there seem to be issues?
Any help appreciated.
In the edit method instead of
return View::make('tests.edit')->with(array('course'=>$course));
use:
$this->layout->content= View::make('tests.edit')->with(array('course'=>$course));
In your AdminController which is the base controller of your TestController, add the layout setings, put this code in your AdminController
protected $layout = 'layouts.master';
protected function setupLayout()
{
if ( ! is_null($this->layout))
{
$this->layout = View::make($this->layout);
}
}
Now you use any view with layout using something like this:
$this->layout->content = View::make('tests.edit')->with(array('course'=>$course));
Here, tests.edit means that edit.blade.php (also could edit.php if not blade) file is in app/views/tests/ directory.
In your index method you have used:
$this->layout->content=View::make('tests.index');
So the layout showed up because you set data to layout but in other example you didn't set data to layout so layout is not rendered, it's returning only the view as given below:
return View::make('tests.edit')->with(array('course'=>$course));
So, setup the layout in the base controller class so in your every controller you don't have to setup the layout, but always set data to the content variable of layout using this:
$this->layout->content = 'your data';