Method open does not exist, Laravel, Form facade - laravel

I am learning laravel following a tutorial. I am stuck with this error
ErrorException in Macroable.php line 81:
Method open does not exist. (View: path\to\project\resources\views\form.blade.php)
I am using FormFacade. earlier I was facing an error saying:
Call to undefined method Illuminate\Foundation\Application::bindShared()
which I overcame by replacing bindShared with singleton all over the file
/path/project/vendor/illuminate/html/HtmlServiceProvider.php
form.blade.php
<html>
<head>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
</head>
<body>
<h1>Create a new form</h1>
<hr/>
{{ Form::open() }}
{{ Form::close() }}
</body>
</html>
HtmlServiceProvider.php
use Illuminate\Support\ServiceProvider;
class HtmlServiceProvider extends ServiceProvider {
/**
* Indicates if loading of the provider is deferred.
*
* #var bool
*/
protected $defer = true;
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
$this->registerHtmlBuilder();
$this->registerFormBuilder();
$this->app->alias('html', 'Illuminate\Html\HtmlBuilder');
$this->app->alias('form', 'Illuminate\Html\FormBuilder');
}
/**
* Register the HTML builder instance.
*
* #return void
*/
protected function registerHtmlBuilder()
{
$this->app->singleton('html', function($app)
{
return new HtmlBuilder($app['url']);
});
}
/**
* Register the form builder instance.
*
* #return void
*/
protected function registerFormBuilder()
{
$this->app->singleton('form', function($app)
{
$form = new FormBuilder($app['html'], $app['url'], $app['session.store']->getToken());
return $form->setSessionStore($app['session.store']);
});
}
/**
* Get the services provided by the provider.
*
* #return array
*/
public function provides()
{
return array('html', 'form');
}
}
Plese Help.

illuminate/html was deprecated for Laravel 5.0, and has not been updated to work with Laravel 5.1+.
You need to replace it with the laravelcollective/html package.

Add in your config/app.php provider:
Collective\Html\HtmlServiceProvider::class,
and add alias:
'Html' => Collective\Html\HtmlFacade::class,
and replace form open and close :
{!! Form::open() !!}
{!! Form::close() !!}
notes:
This is for laravel 5.

Related

Request Validation Not Working for PUT method In Laravel 8

My Route
Route::put('dataedit/{id}', [empDataController::class, 'empDataEdit'])->middleware('guest')->name('emp.data.edit');
My Controller
public function empDataEdit(empDataValidation $request, $id){
$id = Crypt::decrypt($id);
$DataAddCheck = EmpData::find($id)->update($request->all());
if($DataAddCheck){
return back()->with('successMsg', 'Data Added Successfully');
}
else{
return back()->with('successMsg', 'Something Went Wrong Try Again!');
}
}
Note : I add use App\Http\Requests\empDataValidation; in controller Top.
My Request Validation
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class empDataValidation extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'empName' => ['required'],
];
}
}
My blade (Just Important part)
<form id="msform" method="post" enctype="multipart/form-data"
action="{{ route('emp.data.edit', Crypt::encrypt($data->id)) }}">
#csrf
#method('PUT')
Note: When I use Request $request in controller It works Fine but when I use empDataValidation $request It not working, In my create controller empDataValidation $requestworks fine. Please help to solve this issue.

{{ auth()->user()->email }} / {{ Auth::user()->email }} not working in x-component

php artisan make:component Navbar, created:
App\View\Components\Navbar.php
app\resources\views\components\navbar.blade.php
Placing {{ auth()->user()->email }} or {{ Auth::user()->email }} in the blade file, gave this error:
Trying to get property 'email' of non-object.
Tried to fix this by changing my App\View\Components\Navbar.php to:
<?php
namespace App\View\Components;
use Illuminate\View\Component;
class Navbar extends Component
{
public $email;
/**
* Create a new component instance.
*
* #return void
*/
public function __construct($email = null)
{
$this->email = 'info#example.com';
}
/**
* Get the view / contents that represent the component.
*
* #return \Illuminate\Contracts\View\View|\Closure|string
*/
public function render()
{
return view('components.navbar');
}
}
And added {{ $email }} to my blade file and it worked.
However, I want to display the e-mail address from the authenticated user, so I changed App\View\Components\Navbar.php to:
<?php
namespace App\View\Components;
use Illuminate\View\Component;
use Illuminate\Support\Facades\Auth;
class Navbar extends Component
{
public $email;
/**
* Create a new component instance.
*
* #return void
*/
public function __construct($email = null)
{
$this->email = Auth::user()->email;
}
/**
* Get the view / contents that represent the component.
*
* #return \Illuminate\Contracts\View\View|\Closure|string
*/
public function render()
{
return view('components.navbar');
}
}
And I got the same error again.
The error you're having because the user is not authenticated. Maybe add a check before calling the component in the blade file, wrap the component between #auth directive. Something like this
#auth
<x-navbar></x-navbar>
#endauth

Laravel DataTables doesn't show any results

I was following this guide to show all partners in my admin section: https://yajrabox.com/docs/laravel-datatables/master/quick-starter
Unfortunately, there are no errors, but I don't see also the list with all items. There are results in the database, but for me, it seems it is not making the query, that's why there are no results (in the debuggbar i don't see a query with the 'partners' table).
route.php
Route::get('partners', [PartnerController::class, 'index'])->name('partners.index');
PartnerController:
namespace App\Domains\Partner\Http\Controllers\Backend;
use App\Domains\Partner\DataTable\PartnersDataTable;
use App\Domains\Partner\Models\Partner;
use App\Domains\Partner\Services\PartnerService;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class PartnerController extends Controller
{
public function index(PartnersDataTable $dataTable)
{
return $dataTable->render('backend.partner.index');
}
}
PartnersDataTable:
namespace App\Domains\Partner\DataTable;
use App\Domains\Partner\Models\Partner;
use Yajra\DataTables\Html\Button;
use Yajra\DataTables\Html\Column;
use Yajra\DataTables\Html\Editor\Editor;
use Yajra\DataTables\Html\Editor\Fields;
use Yajra\DataTables\Services\DataTable;
class PartnersDataTable extends DataTable
{
/**
* Build DataTable class.
*
* #param mixed $query Results from query() method.
* #return \Yajra\DataTables\DataTableAbstract
*/
public function dataTable($query)
{
return datatables()
->eloquent($query);
}
public function query(Partner $model)
{
return $model->newQuery();
}
/**
* Optional method if you want to use html builder.
*
* #return \Yajra\DataTables\Html\Builder
*/
public function html()
{
return $this->builder()
->setTableId('partners-table')
->columns($this->getColumns())
->minifiedAjax()
->dom('Bfrtip')
->orderBy(1)
->buttons(
Button::make('create'),
Button::make('export'),
Button::make('print'),
Button::make('reset'),
Button::make('reload')
);
}
/**
* Get columns.
*
* #return array
*/
protected function getColumns()
{
return [
Column::make('id'),
Column::make('title'),
];
}
/**
* Get filename for export.
*
* #return string
*/
protected function filename()
{
return 'Users_' . date('YmdHis');
}
}
index.blade.php:
#extends('backend.layouts.app')
#section('title', __('Partners'))
#section('breadcrumb-links')
#endsection
#section('content')
<x-backend.card>
<x-slot name="header">
#lang('Partners')
</x-slot>
#if ($logged_in_user->hasAllAccess())
<x-slot name="headerActions">
<x-utils.link
icon="c-icon cil-plus"
class="card-header-action"
:href="route('admin.partners.create')"
:text="__('Create partner')"
/>
</x-slot>
#endif
<x-slot name="body">
{!! $dataTable->table() !!}
</x-slot>
</x-backend.card>
#endsection
#push('after-scripts')
<script src="{{ asset('vendor/datatables/buttons.server-side.js') }}"></script>
{{$dataTable->scripts()}}
#endpush
Here is what is $dataTable->scripts() producing:
<script src="http://kitty/vendor/datatables/buttons.server-side.js"></script>
<script type="text/javascript">$(function(){window.LaravelDataTables=window.LaravelDataTables||{};window.LaravelDataTables["partners-table"]=$("#partners-table").DataTable({"serverSide":true,"processing":true,"ajax":{"url":"http:\/\/kitty\/admin\/partners","type":"GET","data":function(data) {
for (var i = 0, len = data.columns.length; i < len; i++) {
if (!data.columns[i].search.value) delete data.columns[i].search;
if (data.columns[i].searchable === true) delete data.columns[i].searchable;
if (data.columns[i].orderable === true) delete data.columns[i].orderable;
if (data.columns[i].data === data.columns[i].name) delete data.columns[i].name;
}
delete data.search.regex;}},"columns":[{"data":"id","name":"id","title":"Id","orderable":true,"searchable":true},{"data":"title","name":"title","title":"Title","orderable":true,"searchable":true}],"dom":"Bfrtip","order":[[1,"desc"]],"buttons":[{"extend":"create"},{"extend":"export"},{"extend":"print"},{"extend":"reset"},{"extend":"reload"}]});});
</script>
the reason why your data isn't displaying on the table is because of this line of code:
->buttons(
Button::make('create'),
Button::make('export'),
Button::make('print'),
Button::make('reset'),
Button::make('reload')
);
comment this line of code and the data will be displayed properly.

Laravel using loadViewComponentsAs method from SurviceProvider without creating the package

When installing jetstream with it's authentication/authorization system laravel developer receive scaffolding with lots of views and view-components.
Firstly those views are in vendor\laravel\jetstream\resources\views\components\ folder.
Then when developer publishes views according to jeststream installation: https://jetstream.laravel.com/1.x/installation.html#livewire-components
php artisan vendor:publish --tag=jetstream-views
Those views/components appears at resources\views\vendor\jetstream\components.
The links to those views on the blade templates are:
<x-jet-welcome />
or to unify
<x-jet-someJetElement />
This corresponds with laravel blade documentation: https://laravel.com/docs/8.x/packages#view-components
We need to register those aliases in SurviceProvider:
public function boot()
{
$this->loadViewComponentsAs('courier', [
Alert::class,
Button::class,
]);
}
And then use them like this:
<x-courier-alert />
<x-courier-button />
My question is if we can register those aliases without creating a package?
So what I did:
Added aliases in AppServiceProvider - default service provider for users.
<?php
namespace App\Providers;
use App\View\Components\Alert;
use App\View\Components\Button;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
$this->loadViewComponentsAs('nopackage', [
Alert::class,
Button::class,
]);
}
}
Created two components app\View\Components:
Alert.php:
<?php
namespace App\View\Components;
use Illuminate\View\Component;
class Alert extends Component
{
/**
* Create a new component instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Get the view / contents that represent the component.
*
* #return \Illuminate\View\View|string
*/
public function render()
{
return view('components.alert');
}
}
Button.php:
<?php
namespace App\View\Components;
use Illuminate\View\Component;
class Button extends Component
{
/**
* Create a new component instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Get the view / contents that represent the component.
*
* #return \Illuminate\View\View|string
*/
public function render()
{
return view('components.button');
}
}
Created two view components resources\views\components:
alert.blade.php:
<div>
<h2>Hello from Alert!</h2>
</div>
button.blade.php:
<div>
<h2>Hello from button!</h2>
</div>
Created view resources\views\bladetest.blade.php:
<h1>
Hello from blade test!
</h1>
<x-nopackage-Alert/>
Created route:
Route::view('/bladetest', 'bladetest');
And it does not work: "Unable to locate a class or view for component [nopackage-Alert]."
What I am doing wrong?

How to update specific fields in a PUT request?

I have a settings table where I store things like website title, social network links and other things... I make then all acessible by seting a cache variable.
Now, my question is, how can I update this table? By example... If I have the following blade form:
{!! Form::model(config('settings'), ['class' => 's-form', 'route' => ['setting.update']]) !!}
{{ method_field('PUT') }}
<div class="s-form-item text">
<div class="item-title required">Nome do site</div>
{!! Form::text('title', null, ['placeholder' => 'Nome do site']) !!}
</div>
<div class="s-form-item text">
<div class="item-title required">Descrição do site</div>
{!! Form::text('desc', null, ['placeholder' => 'Descrição do site']) !!}
</div>
<div class="s-form-item s-btn-group s-btns-right">
Voltar
<input class="s-btn" type="submit" value="Atualizar">
</div>
{!! Form::close() !!}
In the PUT request how can I search in the table by the each name passed and update the table? Here are the another files:
Route
Route::put('/', ['as' => 'setting.update', 'uses' => 'Admin\AdminConfiguracoesController#update']);
Controller
class AdminConfiguracoesController extends AdminBaseController
{
private $repository;
public function __construct(SettingRepository $repository){
$this->repository = $repository;
}
public function geral()
{
return view('admin.pages.admin.configuracoes.geral.index');
}
public function social()
{
return view('admin.pages.admin.configuracoes.social.index');
}
public function analytics()
{
return view('admin.pages.admin.configuracoes.analytics.index');
}
public function update($id, Factory $cache, Setting $setting)
{
// Update?
$cache->forget('settings');
return redirect('admin');
}
}
Repository
class SettingRepository
{
private $model;
public function __construct(Setting $model)
{
$this->model = $model;
}
public function findByName($name){
return $this->model->where('name', $name);
}
}
Model
class Setting extends Model
{
protected $table = 'settings';
public $timestamps = false;
protected $fillable = ['value'];
}
ServiceProvider
class SettingsServiceProvider extends ServiceProvider
{
public function boot(Factory $cache, Setting $settings)
{
$settings = $cache->remember('settings', 60, function() use ($settings)
{
return $settings->lists('value', 'name')->all();
});
config()->set('settings', $settings);
}
public function register()
{
//
}
}
Migration
class CreateSettingsTable extends Migration
{
public function up()
{
Schema::create('settings', function (Blueprint $table) {
$table->increments('id');
$table->string('name', 100)->unique();
$table->text('value');
});
}
public function down()
{
Schema::drop('settings');
}
}
Ok, step by step.
First, let's think about what we really want to achieve and look at the implementation in the second step.
Looking at your code, I assume that you want to create an undefined set of views that contain a form for updating certain settings. For the user, the settings seem to be structured in groups, e.g. "General", "Social", "Analytics", but you don't structure your settings in the database like that. Your settings is basically a simple key/value-store without any relation to some settings group.
When updating, you want a single update method that handles all settings, disregarding which form the update request is sent from.
I hope I'm correct with my assumptions, correct me if I'm not.
Okay cool, but, come on, how do I implement that?
As always, there are probably a thousand ways you can implement something like this. I've written a sample application in order to explain how I would implement it, and I think it's pretty Laravelish (what a word!).
1. How should my data be stored?
We already talked about it. We want a basic key/value-store that persists in the database. And because we work with Laravel, let's create a model and a migration for that:
php artisan make:model Setting --migration
This will create a model and the appropriate migration. Let's edit the migration to create our key/value columns:
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateSettingsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('settings', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->text('value');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('settings');
}
}
In the Setting model, we have to add the name column to the fillable array. I'll explain why we need to below. Basically, we want to use some nice Laravel APIs and therefore we have to make the name-attribute fillable.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Setting extends Model {
/**
* #var array
*/
protected $fillable = ['name'];
}
2. How do I want to access the settings data?
We discussed this in your last question, so I won't go into detail about this and I pretend that this code already exists. I'll use a repository in this example, so I will update the SettingsServiceProvider during development.
3. Creating the repositories
To make the dependencies more loosely coupled, I will create an Interface (Contract in the Laravel world) and bind it to a concrete implementation. I can then use the contract with dependency injection and Laravel will automatically resolve the concrete implementation with the Service Container. Maybe this is overkill for your app, but I love writing testable code, no matter how big my application will be.
app/Repositories/SettingRepositoryInterface.php:
<?php
namespace App\Repositories;
interface SettingRepositoryInterface {
/**
* Update a setting or a given set of settings.
*
* #param string|array $key
* #param string $value
*
* #return void
*/
public function update($key, $value);
/**
* List all available settings (name => value).
*
* #return array
*/
public function lists();
}
As you can see, we will use the repository for updating settings and listing our settings in a key/value-array.
The concrete implementation (for Eloquent in this example) looks like this:
app/Repositories/EloquentSettingRepository.php
<?php
namespace App\Repositories;
use App\Setting;
class EloquentSettingRepository implements SettingRepositoryInterface {
/**
* #var \App\Setting
*/
private $settings;
/**
* EloquentSettingRepository constructor.
*
* #param \App\Setting $settings
*/
public function __construct(Setting $settings)
{
$this->settings = $settings;
}
/**
* Update a setting or a given set of settings.
* If the first parameter is an array, the second parameter will be ignored
* and the method calls itself recursively over each array item.
*
* #param string|array $key
* #param string $value
*
* #return void
*/
public function update($key, $value = null)
{
if (is_array($key))
{
foreach ($key as $name => $value)
{
$this->update($name, $value);
}
return;
}
$setting = $this->settings->firstOrNew(['name' => $key]);
$setting->value = $value;
$setting->save();
}
/**
* List all available settings (name => value).
*
* #return array
*/
public function lists()
{
return $this->settings->lists('value', 'name')->all();
}
}
The DocBlocks should pretty much explain how the repository is implemented. In the update method, we make use of the firstOrNew method. Thats why we had to update the fillable-array in our model.
Now let's bind the interface to that implementation. In app/Providers/SettingsServiceProvider.php, add this to the register-method:
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->bind(
\App\Repositories\SettingRepositoryInterface::class,
\App\Repositories\EloquentSettingRepository::class
);
}
We could have added this to the AppServiceProvider, but since we have a dedicated service provider for our settings we will use it for our binding.
Now that we have finished the repository, we can update the existing code in the boot-method of our SettingsServiceProvider so that it uses the repository instead of hardcoding App\Setting.
/**
* Bootstrap the application services.
*
* #param \Illuminate\Contracts\Cache\Factory $cache
* #param \App\Repositories\SettingRepositoryInterface $settings
*/
public function boot(Factory $cache, SettingRepositoryInterface $settings)
{
$settings = $cache->remember('settings', 60, function() use ($settings)
{
return $settings->lists();
});
config()->set('settings', $settings);
}
4. Routes and controller
In this simple example, the homepage will show a form to update some settings. Making a PUT/PATCH-request on the same route will trigger the update method:
<?php
get('/', ['as' => 'settings.index', 'uses' => 'Admin\SettingsController#index']);
put('/', ['as' => 'settings.update', 'uses' => 'Admin\SettingsController#update']);
The index-method of our controller will return a view that contains the form. I've commented the update method throughout to explain what each line does:
app/Http/Controllers/Admin/SettingsController.php:
<?php
namespace App\Http\Controllers\Admin;
use Illuminate\Contracts\Cache\Factory;
use Illuminate\Http\Request;
use App\Repositories\SettingRepositoryInterface;
class SettingsController extends AdminBaseController {
/**
* #var \App\Repositories\SettingRepositoryInterface
*/
private $settings;
/**
* SettingsController constructor.
*
* #param \App\Repositories\SettingRepositoryInterface $settings
*/
public function __construct(SettingRepositoryInterface $settings)
{
$this->settings = $settings;
}
/**
* Shows the setting edit form.
*
* #return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function index()
{
return view('settings.index');
}
/**
* Update the settings passed in the request.
*
* #param \Illuminate\Http\Request $request
* #param \Illuminate\Contracts\Cache\Factory $cache
*
* #return \Illuminate\Http\RedirectResponse
*/
public function update(Request $request, Factory $cache)
{
// This will get all settings as a key/value array from the request.
$settings = $request->except('_method', '_token');
// Call the update method on the repository.
$this->settings->update($settings);
// Clear the cache.
$cache->forget('settings');
// Redirect to some page.
return redirect()->route('settings.index')
->with('updated', true);
}
}
Note the first statement in the update method. It will fetch all POST-data from the request, except the method and CSRF token. $settings is now an associative array with your settings sent by the form.
5. And last, the views
Sorry for the Bootstrap classes, but i wanted to style my example app real quick :-)
I guess that the HTML is pretty self-explanatory:
resources/views/settings/index.blade.php:
#extends('layout')
#section('content')
<h1>Settings example</h1>
#if(Session::has('updated'))
<div class="alert alert-success">
Your settings have been updated!
</div>
#endif
<form action="{!! route('settings.update') !!}" method="post">
{!! method_field('put') !!}
{!! csrf_field() !!}
<div class="form-group">
<label for="title">Title</label>
<input type="text" class="form-control" id="title" name="title" placeholder="Title" value="{{ config('settings.title', 'Application Title') }}">
</div>
<div class="form-group">
<label for="Facebook">Facebook</label>
<input type="text" class="form-control" id="facebook" name="facebook" placeholder="Facebook URL" value="{{ config('settings.facebook', 'Facebook URL') }}">
</div>
<div class="form-group">
<label for="twitter">Twitter</label>
<input type="text" class="form-control" id="twitter" name="twitter" placeholder="Twitter URL" value="{{ config('settings.twitter', 'Twitter URL') }}">
</div>
<input type="submit" class="btn btn-primary" value="Update settings">
</form>
#stop
As you can see, when I try to get a value from the config, I also give it a default value, just in case it has not been set yet.
You can now create different forms for different setting groups. The form action should always be the settings.update route.
When I run the app, I can see the form with the default values:
When I type some values, hit the update button and Laravel redirects me to the form again, I can see a success message and my settings that now persist in the database.
You can inject the Request class. Lets update the title:
// Injecting Illuminate\Http\Request object
public function update(Request $request, $id, Factory $cache, Setting $setting)
{
$newTitle = $request->get('title');
$cache->forget('settings');
return redirect('admin');
}
To change the value in db, then could do:
$titleSetting = App\Setting::where('name', 'title')->first();
$titleSetting->value = $newTitle;
$titleSetting->save();
The whole code looks like:
public function update(Request $request, $id)
{
$newTitle = $request->get('title');
\Cache::forget('settings');
$titleSetting = App\Setting::where('name', 'title')->first();
$titleSetting->value = $newTitle;
$titleSetting->save();
return redirect('admin');
}

Resources