I have a "basic" problem, but I can't figure where.
I have a problem between the controller and the model.
I went on the Internet and I saw a lot of "Class 'App\Http\Controllers\App{something}' not found" solved problem, but none worked for me.
Could it be because I did a copy-past form my native project?
I'm only looking for the "index" part. I can't work on the rest since I can't see what I'm doing.
MyController:
<?php
namespace App;
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use app\Article;
class ArticleController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
session_start();
$article = App\Article::Blog();
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
session_start();
// si je reçois des données de formulaire,
if (isset($_POST['titre'], $_POST['description'], $_POST['contenu'])
){
$admin = Add();
// si la création a réussi,
if ($add) {
//rediriger vers
header('location: /Chef/Controleur/controleur-blog.php');
echo "Well done!". '<br>';
echo "You have add an article!";
}
}
else {
// afficher le formulaire
echo "Error. Please try again.";
require __DIR__.'/Controleur/controleur_piedpage.php';
}
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function edit($id)
{
require __DIR__.'/../Modele/modele.php';
$article = Article();
// si je reçois des données de formulaire,
if (isset($_POST['titre'], $_POST['description'], $_POST['contenu'])){
$admin = Edit();
// si la création a réussi,
if ($edit) {
//rediriger vers
header('location: /Chef/Controleur/controleur-blog.php');
echo "You have edit an article!";
}
}
else {
// afficher le formulaire
require __DIR__.'/Controleur/controleur-entete.php';
require __DIR__.'/Controleur/controleur-recherche.php';
require __DIR__.'/../Vue/edit.php';
echo "Error. Please try again.";
require __DIR__.'/Controleur/controleur_piedpage.php';
}
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function destroy($id)
{
require __DIR__.'/../Modele/modele.php';
$admin = Delete();
$article = Article();
if ($delete) {
//rediriger vers
header('location: /Chef/Controleur/controleur-blog.php');
}
else {
// afficher le formulaire
require __DIR__.'/Controleur/controleur-entete.php';
require __DIR__.'/Controleur/controleur-recherche.php';
require __DIR__.'/../Vue/delete.php';
echo "Error. Please try again.";
require __DIR__.'/Controleur/controleur_piedpage.php';
}
}
}
My Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Article extends Model {
function Blog() {
if(isset($_POST['register'])) if(('role'== 0) && ('role' == 1)) {
$todoread = [];
$pdo = prepareStatement('SELECT * FROM article ORDER BY id DESC LIMIT 100');
$pdo->execute();
$todoread = $pdo->fetchAll(PDO::FETCH_ASSOC);
return $todoread;
}
}
function Edit(){
$pdo_statement = prepareStatement('UPDATE article
SET titre=:titre, description=:description, contenu =:contenu
WHERE id=:id');
$pdo_statement->bindParam(':id', $_GET['id']);
$pdo_statement->bindParam(':titre', $_POST['titre']);
$pdo_statement->bindParam(':description', $_POST['description']);
$pdo_statement->bindParam(':contenu', $_POST['contenu']);
$pdo_statement->execute();
return true;
}
function Article(){
if(isset($_GET['id'])) {
$sql = "SELECT * FROM article WHERE id = :id";
$article = prepareStatement($sql);
$article->bindParam(':id', $_GET['id']);
$article->execute();
return $article->fetch();
}
}
function Delete() {
if (isset($_POST['submit'])) {
$pdo_statement = prepareStatement('DELETE FROM article WHERE id =:id');
$pdo_statement->bindParam(':id', $_GET['id']);
$pdo_statement->execute();
$pdo_statement->fetchAll(PDO::FETCH_ASSOC);
return true;
}
}
function Add(){
if (isset($_POST['submit'])) {
$pdo_statement = prepareStatement(
'INSERT INTO article (titre, description, contenu)
VALUES (:titre, :description, :contenu)');
$pdo_statement->bindParam(':titre', $_POST['titre']);
$pdo_statement->bindParam(':description', $_POST['description']);
$pdo_statement->bindParam(':contenu', $_POST['contenu']);
$pdo_statement->execute();
return true;
}
}
}
The View:
#extends('layouts.app')
#section('title', 'Blog')
#section('content')
<br>
<br>
<br>
<?php if(!isset($_SESSION['nom'])): ?>
<h1 class="center"> Welcome to my blog ! </h1>
<h2 class="center"> Tips, tutorials and more on chatbots, artificials intelligence </h2>
<p>
To access the blog, please register yourself <br>
You'll find the link to the registration here or you can login here.
</p>
<?php else: ?>
<h1 class="center"> Welcome to my blog <?= $_SESSION ['nom'] ?> ! </h1>
<h2 class="center"> Enjoy the tips and tutorials of this blog! </h2>
<br>
<button class="ui small black button"> Add an article </button>
<br>
<?php
foreach ($blog as $ligne) {
?>
<br>
<button class="ui small black button"> Edit the article</button>
<button class="ui small black button"> Delete the article </button> <br>
<?php echo $ligne['titre'].'<br>'; ?><br>
<?php echo $ligne['description'].'<br>'; ?><br>
<?php echo $ligne['contenu'].'<br>'; ?> <br> <br> <!-- créer un template : https://openclassrooms.com/courses/adoptez-une-architecture-mvc-en-php/creer-un-template-de-page !-->
<?php
}
?>
<br>
<?php endif; ?>
#endsection
Thank you for your help!!
To fix your issue, change:
<?php
namespace App;
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use app\Article;
In your controller to:
<?php
namespace App\Http\Controllers; // <- removing duplicate namespace
use Illuminate\Http\Request;
use App\Article; // <- Case sensitive, use App\, not app\
Other than that, I would really encourage you to read the documentation of Laravel, because this code is not really using Laravel.
You do not have to use session_start() as in Laravel you have Session.
You do not have to work with superglobals as $_POST, because you can use Laravel's Request objects.
You should not handle request data in your models, that's what your controller and/or services are for, this layer (request data) should not 'bleed' into your models like this.
You are using PDO statements, and totally bypass Laravel's Eloquent ORM.
I also see a lot of conditional requires, something that you should not do if you were using Laravel's service container.
With all of this, you are practically skipping every bit of functionality of Laravel and you are basically using the entire framework just for routing.
Related
I cannot access to the attribute "price" in my Mail class in Laravel. I´ve got an error
Undefined index: price (View: C:\laragon\www\hr-english\resources\views\external__emails\registered-course.blade.php)
I think the problem is the controller. I had to do a query to the database to check the price of the course, because in my registered_courses table I have a foreign key related to courses which return to me the title of the course and its price.
When I got from the query those data and send the variables to the blade, it appears the error shown at the top.
My controller
public function store(Request $request)
{
try {
$data = $this->getData($request);
$email = Auth::user()->email;
$name = Auth::user();
$msg = $data;
$price = DB::table('courses')->select('price')->where('id', '=', $request['course_id'])->get();
RegisteredCourse::create($data);
Mail::to($email)->queue(new RegistCourse($msg, $email, $name, $price));
return redirect()->route('registeredCourse.index')
->with('sucess_message', 'Registered course was sucessfully added');
} catch(Exception $exception) {
return back()->withInput()
->withErrors(['unexpected_error' => 'Unexpected error occurred while trying to process your request.']);
}
}
My Mailable
class RegistCourse extends Mailable
{
use Queueable, SerializesModels;
public $subject = 'Registered Course';
public $msg;
public $email;
public $name;
public $price;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($msg, $email, $name, $price)
{
$this->msg = $msg;
$this->email = $email;
$this->name = $name;
$this->price = $price;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->view('external__emails.registered-course');
}
}
This is my blade template
<body>
<div class="container">
<div class="row">
<div>
<img src="{{asset('images/logo_leon.png')}}" alt="logo_leon" width="55" id="logo_login"><span style="color:gray">HOLYROOD ENGLISH SCHOOL</span>
</div>
<br>
<div>
<p>Thank you very much for your purchase, {{$name['name']}}. You have just registered in one of our courses.</p>
<p>
<table>
<tr>
<th>Name</th>
<th>Course</th>
<th>Date of purchase</th>
</tr>
<tr>
<td>{{$msg['course_id']}}</td>
<td>{{$price['price']}}</td>
</tr>
</table>
</p>
</p>
<p>See you in class. Surely we enjoy learning English.</p>
<p>If you have any questions, do not hesitate to contact us through any of our contact forms.</p>
<br>
<p>Equipo Holyrood English School</p>
</div>
</div>
</div>
</body>
</html>
In your code:
$data = $this->getData($request);
$email = Auth::user()->email;
$name = Auth::user(); // Should be Auth::user()->name (if name exists)
$msg = $data;
// The get() method returns an array even if there is one row.
$price = DB::table('courses')->select('price')->where('id', '=', $request['course_id'])->get();
So, $price should be $price[0]->price in the view or use first() method instead of get(). So, the name should be the property of the user model, Auth::user() will result in an object.
pay attention to the '->with' function that I use to send the datas to the view.
YOUR MAILING CLASS:
class SuccessBooking extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* #return void
*/
public $booking;
public $user;
public $pdf_path;
public $rideCode;
public function __construct($user, $booking, $pdf_path, $rideCode)
{
$this->booking = $booking;
$this->user = $user;
$this->pdf_path = $pdf_path;
$this->rideCode = $rideCode;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->from('noreply#coride.com', "Co Ride Receipt")
->view('email/successbookinginvoice')
->attach(public_path($this->pdf_path))
->with([
'user' => $this->user,
'code' => $this->rideCode,
'path' => public_path($this->pdf_path),
'booking' => $this->booking,
]
);
}
}
YOUR BLADE TEMPLATE
#section('content')
{{--below we access a particular item in the object user--}}
<h5>Dear {{$user->firstName}}, congratulations on your successful booking.</h5>
{{--below we just access code, it's not an object--}}
<h5>Dear {{$code}}, congratulations on your successful booking.</h5>
#endsection
I am using a multi auth guard for my laravel app and everything seems to be working fine....registration, login etc perfect. but i need to get values of an authenticated user of a specific guard in my views but it kept saying undefined property
Here is the code to my model :
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Agent extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'firstname', 'lastname', 'aid', 'city', 'state', 'email', 'password', 'bankname', 'accountnumber',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
}
and for my view :
#extends('layouts.app')
#section('title')
OneNaira© Welcome Back {{ auth()->user()->firstname }}
#endsection
#section('footer')
<!--FOOTER-->
<div class="ui stackable pink inverted secondary pointing menu" id="footer">
<div class="ui container">
<a class="item">© OneNaira, 2019.</a>
<div class="right menu">
<a class="item">
<script>
var todaysDate = new Date();
document.write(todaysDate);
</script>
</a>
</div>
</div>
</div>
#endsection
and for the login controller
<?php
namespace App\Http\Controllers\Agent\Auth;
use Auth;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ThrottlesLogins;
class LoginController extends Controller
{
/**
* Show the login form.
*
* #return \Illuminate\Http\Response
*/
public function showLoginForm()
{
return view('agent.auth.login',[
'title' => 'Welcome Back, Sign Into Your OneNaira Initiative Agent Dashboard',
'loginRoute' => 'agent.login',
'forgotPasswordRoute' => 'agent.password.request',
]);
}
/**
* Login the agent.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\RedirectResponse
*/
public function login(Request $request)
{
$this->validator($request);
if(Auth::guard('agent')->attempt($request->only('aid','password'),$request->filled('remember'))){
//Authentication passed...
return redirect()
->intended(route('agent.dashboard'));
}
//Authentication failed...
return $this->loginFailed();
}
/**
* Logout the agent.
*
* #return \Illuminate\Http\RedirectResponse
*/
public function logout()
{
Auth::guard('agent')->logout();
return redirect()
->route('agent.login')
->with('status','Agent has been logged out!');
}
/**
* Validate the form data.
*
* #param \Illuminate\Http\Request $request
* #return
*/
private function validator(Request $request)
{
//validation rules.
$rules = [
'aid' => 'required|exists:agents,aid|min:8|max:191',
'password' => 'required|string|min:4|max:255',
];
//custom validation error messages.
$messages = [
'aid.exists' => 'These credentials do not match our records.',
];
//validate the request.
$request->validate($rules,$messages);
}
/**
* Redirect back after a failed login.
*
* #return \Illuminate\Http\RedirectResponse
*/
private function loginFailed()
{
return redirect()
->back()
->withInput()
->with('error','Login failed, please try again!');
}
}
I figured it out : {{ Auth::guard('agent')->user()->firstname }}
maybe someone can help me. I have done a product list from my database. It shows product image, title, content, price
When I select on one of the products, it opens in the new window. And I cant see any product details (no image, no title, no content) , just empty page.
See all attachments:
my BrackController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\file;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Collection;
class BracController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
return view('insertBrac');
}
public function showBrac()
{
$user=file::all();
return view('apyrankes', compact('user'));
}
public function view_brac()
{
$object = \DB::table('braclets')->where('BrackID' , request('brackId'))->first();
return view('view_object', array('user' => $object));
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
{
$user = new file;
$user->Title= Input::get('title');
$user->Content= Input::get('content');
$user->Price= Input::get('price');
if (Input::hasFile('image'))
{
$file=Input::file('image');
$file->move(public_path(). '/uploads', $file->getClientOriginalName());
$user->Image = $file->getClientOriginalName();
}
$user->save();
return redirect( "insertBrac" );
}
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
}
My product list:
apyrankes.blade.php
<div class="header">
#include('header')
</header>
<body>
<div class="content-products">
#foreach($user as $users)
<div id="myDiv">
<div class="products">
<img src="{{ $users->Image}}" alt="{{ $users->Title}}" width="200px" height="200px"><br>
{{ $users->Title}}<br>
{{ $users->Content}}<br>
{{ $users->Price}}€<br>
Plačiau
</div>
</div>
#endforeach
</div>
</body>
And when I select one of the product from product list on apyrankes.blade.php
it opens in view_object.blade.php , but I cannot see there any details of the select product, just empty page:
My view_object.blade.php
<div class="header">
#include('header')
</header>
<body>
<Br>
<br>
<Br>
<div class="content-products">
<div id="myDiv">
<div class="products">
#if($user)
<img src="{{ $user->Image}}" alt="{{ $user->Title}}" width="200px" height="200px"><br>
{{ $user->Title}}<br>
{{ $user->Content}}<br>
{{ $user->Price}}€<br>
#endif
</div>
</div>
</div>
</body>
Because you did
Plačiau</div>
The name of the variable you need to fetch is product
$object = \DB::table('braclets')->where('BrackID' , request('product'))->first();
I set up a class for deleting comments left by users under an item model in a web page:
<?php
namespace App\Policies;
use App\Comment;
use App\Model_comment;
use App\User;
use App\Post;
class CommentPolicy
{
/**
*
* Defines if User can delete a Comment
*
* #param User $user
* #param Comment $comment
* #param Post $post
* #return bool
*/
public function deleteComment(User $user, Comment $comment, Post $post)
{
return ($user->id === $comment->user_id || $user->id === $post->user_id);
}
/**
* #param User $user
* #param Model_comment $model_comment
* #return bool
*/
public function deleteModelComment(User $user, Model_comment $model_comment)
{
return ($user->id === $model_comment->user_id);
}
}
Now I am trying to use this to show a button for deleting the comment.
While the "deleteComment" for posts comments is working the "deleteModelComment" is not passing at all, not any errors given.
The class is registered correctly under Auth Service Provider.
I am invoking it in the blade view like this:
#can('deleteModelComment', $c)
<button id="deletecmnt_{{$c->id}}" class="fa fa-minus pull-right"
aria-hidden="true"
data-token="{{ csrf_token() }}"></button>
#endcan
$c is the Model_comment. Any clue?
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');
}