I'm getting the hang of mustache for a project I've started during the weekend.
I'm using the PHP implementation. I have, however a couple of inquiries as I'm not used to the system.
How do you handle template inheritance, or reuse?
I know of partials, but how should I use them? I'm doing something like this, ala include:
top.mustache:
<!DOCTYPE html>
<html lang='es'>
<head>
<meta charset=utf-8" />
<link rel="stylesheet" href="/media/style.css" type="text/css" media="screen" />
</head>
<body>
<header><h1>Top</h1>
</header>
<section>
bottom.mustache:
</section>
<footer>potaje</footer>
</body>
</html>
And a view to render this template:
{{>top}}
<form action="/album/" method="post">
<p><label for="name">Name</label> <input type="text" name="name" value=""/></p>
<p><label for="description">Description</label> <textarea name="description" rows="8" cols="40"></textarea></p>
<p><input type="submit" value="Save" /></p>
</form>
{{>bottom }}
Is this the right approach?
Here is an example of how the php implementation of Mustache works. Of note is that Mustache.php will not expand the included partials/templates, so you have to hand them to mustache as seen below. This example was pieced together on an older cakephp framework.
<?
# php cannot recognize multiple acceptable file extensions for partials,
# so toggle it to mustache's extension
$this->ext = '.mustache';
# Mustache says it's logic-less, but that's not exactly true.
# Render out the basic header which calls the logo partial and has
# a {{# logged_in? }} condition which dictates which user box we
# show. Thus, we need to render out the html for both the logged in
# and logged out user boxes
$basic_header_html = $this->renderElement('basic_header');
$logo = $this->renderElement('shared/logo');
$logged_in = $this->renderElement('shared/logged_in_user_box');
$logged_out = $this->renderElement('shared/logged_out_user_box');
$m = new Mustache($basic_header_html,
array('logged_in?' => !empty($this->Auth->userData),
'cache_buster' => time(),
'display_name' => 'StackOverflow Customer'),
array('shared/logo' => $logo,
'shared/logged_in_user_box' => $logged_in,
'shared/logged_out_user_box' => $logged_out));
?>
<!DOCTYPE html>
<html>
<head>
<title>Mustache Test</title>
</head>
<body>
<?= $m->render(); ?>
</body>
</html>
basic_header.mustache
<div id="header" class="basic">
{{> shared/logo }}
{{# logged_in? }}
{{> shared/logged_in_user_box }}
{{/ logged_in? }}
{{^ logged_in? }}
{{> shared/logged_out_user_box }}
{{/ logged_in? }}
</div>
shared/logo.mustache
<a class="logo" href="/foo/bar"><img alt="" src="/images/logo.png?{{ cache_buster }}" /></a>
shared/logged_in_user_box.mustache
Hello {{display_name}}, you are logged in.
shared/logged_out_user_box.mustache
Hello. You are not logged in.
ynkr's answer is right for older versions, but I just upgraded to version 2.4.1 and there your approach should work if you're using the filesystemloader.
See https://github.com/bobthecow/mustache.php/wiki/Template-Loading#partials-loading for details.
Related
There are many questions here that are similar to mine, such as:
Pass variable to a component Laravel 9
Cannot access Blade Component variables inside the view
Passing variable from component into a slot
but I have not found a resolution to my problem in any of them. I've also scoured the doc at: https://laravel.com/docs/9.x/blade#components
I would have thought this would be a simple task.
I have the following structure, in Resources/views:
start.blade.php (uses)
components/layout.blade.php (uses)
components/head.blade.php
From my controller, I call:
$data =
[
'total' => $total,
'uses_form' => true
];
return view('start', $data);
Inside start.blade.php, I have:
<x-layout>
<x-slot name="uses_form">
{{ $uses_form }}
</x-slot>
<!-- additional html -->
</x-layout>
Inside layout.blade.php:
<!DOCTYPE html>
<html lang="en">
<x-head :uses_form:$uses_form />
<!-- also tried: #include('includes.header', ['uses_form' => $uses_form])-->
<body>
<div class="container-fluid">
{{ $slot }}
</div><!--container-fluid-->
</body>
</html>
Finally, in head.blade.php:
<head>
<link type='text/css' rel='stylesheet' href='/css/vendor/bootstrap.min.css' />
#if ($uses_form === true)
<link type='text/css' rel='stylesheet' href='/css/form.css' />
#endif
</head>
This results in an:
Undefined variable $uses_form
at:
head.blade.php: line 3
How can I get the variable to be recognized in head.blade.php?
I'm open to other approaches, such as generated the conditional style include, at a higher level, but I rather keep this check in head.blade.php for maintainability.
Using Laravel version 9.48.0
Edit (Additional Notes)
If I var_dump $uses_form from the top of layout.blade.php, I get the following:
object(Illuminate\View\ComponentSlot)#301 (2) {
["attributes"]=> object(Illuminate\View\ComponentAttributeBag)#299 (1) {
["attributes":protected]=> array(0) { }
}
["contents":protected]=> string(1) "1"
}
So, it's already changed form.
You can try to pass the variable $uses_form from the parent component layout.blade.php to the child component head.blade.php using following changes and I hope it will helpful to you.
layout.blade.php look like:
<!DOCTYPE html>
<html lang="en">
<x-head :uses-form="$uses_form"/>
<body>
<div class="container-fluid">
{{ $slot }}
</div><!--container-fluid-->
</body>
</html>
head.blade.php look like:
<head>
<link type='text/css' rel='stylesheet' href='/css/vendor/bootstrap.min.css' />
#if ($usesForm === true)
<link type='text/css' rel='stylesheet' href='/css/form.css' />
#endif
</head>
I got it working. There were a few things needing adjusting, but, mainly, I needed to modify the component classes to accept the parameter data.
Another change that was needed, was to pass the data to the layout component, at the top of start.blade.php, like so:
<x-layout :hasForm="$hasForm">
Also, as indicated in another answer and in comments, I needed to place the variable in quotes.
Finally, I'm not sure if this was part of problem, but I changed the uses_form variable from snake_case to camelCase.
The changes, from the question are such:
Controller:
$data =
[
'total' => $total,
'hasForm' => true
];
return view('start', $data);
start.blade.php
<x-layout :hasForm="$hasForm">
<!-- additional html -->
</x-layout>
app/View/Components/Layout.php
class Layout extends Component
{
public $hasForm;
public function __construct($hasForm)
{
$this->hasForm = $hasForm;
}
}
layout.blade.php
<!DOCTYPE html>
<html lang="en">
<x-head :hasForm:"$hasForm" />
<body>
<div class="container-fluid">
{{ $slot }}
</div><!--container-fluid-->
</body>
</html>
app/Views/Components/Head.php
class Head extends Component
{
public $hasForm;
public function __construct($hasForm)
{
$this->hasForm = $hasForm;
}
}
head.blade.php
<head>
<link type='text/css' rel='stylesheet' href='/css/vendor/bootstrap.min.css' />
#if ($hasForm === true)
<link type='text/css' rel='stylesheet' href='/css/form.css' />
#endif
</head>
Hope this may help someone else, down the line.
how to create a function to fetch variables, retrieve them, and access them on the preview page, getting data from a user by the related id in another table?
I need to create a function that looks for the parameter passed by url in the database, more specifically in the table "company", column "name"
the user types company / name in the address bar and laravel should search for this name and find it (if any), with that name in hand, I need it sent to the view page, where it will load bootstrap classes from the personalite table, that is related to the user through the id, I've tried everything, but I don't have much experience
I found this code that does not have much to do with my question, but it was the closest I came, but I didn't copreendi very well, in the end, it didn't work out and I need to finish my project :(
public function retorna_disciplina($id)
{
$prontuario = session('prontuario');
$cargo = session('cargo');
if($cargo == "P")
{
$disciplina = DB::table('oferecimento_disciplina')
->where('id_professor','=', $prontuario)
->where('dsa', '=', $id)
->first();
if(count($disciplina)>0)
{
$postagens = DB::table('postagens')
->where('dsa', '=', $id)
->get();
return view('disciplinas.disciplina')->with([
'disciplina' => $disciplina,
'postagens' => $postagens
]);
}
else{
Redirect::to('/perfil')->withErros("A disciplina não existe ou você não tem permissão de acesso");
}
}
}
I created a route and it seems to work well
Route::get('/company/{name}', "company/index_controller#search_base_home(name)");
I created a model, a controller and 2 views, 1 if the laravel finds the name and another if not (a search page)
my problem is really creating the function, I'm not getting
tell me what i need to do to put this into practice i would be very grateful for the help
There may be something wrong with the code, disagreements or something, sorry if that is the case, just an example for you to understand my question better
Right now I'm trying hard with this here, but nothing, I don't know, doesn't seem to get the url name
$this->validate($request, [
'name' => 'required|unique:company|name',
]);
#if (count($errors) > 0)
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
the view code is this (companybase_lg.blade.php)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>iofrm</title>
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="https://brandio.io/envato/iofrm/html/css/fontawesome-all.min.css">
<link rel="stylesheet" type="text/css" href="https://brandio.io/envato/iofrm/html/css/iofrm-style.css">
<link rel="stylesheet" type="text/css" href="https://brandio.io/envato/iofrm/html/css/iofrm-theme1.css">
</head>
<body>
<div class="form-body">
<div class="website-logo">
<a href="index.html">
<div class="logo">
<img class="logo-size" src="images/logo-light.svg" alt=""><!--- db class here --->
</div>
</a>
</div>
<div class="row">
<div class="img-holder"><!--- db class here --->
<div class="bg"></div>
<div class="info-holder">
</div>
</div>
<div class="form-holder"><!--- db class here --->
<div class="form-content">
<div class="form-items">
<h3>Get more things done with Loggin platform.</h3>
<p>Access to the most powerfull tool in the entire design and web industry.</p>
<div class="page-links">
LoginRegister
</div>
<form>
<input class="form-control" type="text" name="username" placeholder="E-mail Address" required><!--- db class here ---><!--- db class here --->
<input class="form-control" type="password" name="password" placeholder="Password" required><!--- db class here --->
<div class="form-button">
<button id="submit" type="submit" class="ibtn">Login</button> <!--- db class here --->
Forget password?
</div>
</form>
<div class="other-links">
<span>Or login with</span>FacebookGoogleLinkedin
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://brandio.io/envato/iofrm/html/js/jquery.min.js"></script>
<script src="https://brandio.io/envato/iofrm/html/https://brandio.io/envato/iofrm/html/js/popper.min.js"></script>
<script src="https://brandio.io/envato/iofrm/html/js/bootstrap.min.js"></script>
<script src="https://brandio.io/envato/iofrm/html/js/main.js"></script>
</body>
</html>
FINAL PART
I tried to get the data to fill in with the classes, but returns nothing related to the name, I don't know if I made a mistake somewhere ...
#foreach($companies as $company)
<div class="{{ $companies->personalite->div_class_1 }}"></div>
<div class="{{ $companies->personalite->div_class_2 }}"></div>
<div class="{{ $companies->personalite->div_class_3 }}"></div>
<div class="{{ $companies->personalite->div_class_4 }}"></div>
#endforeach
so I need to take div_class_1 which is in the personalite table and put in div
each user has their classes in this table and is related to it by an ID number, I created a column "name" in the table to do the test but so far nothing
I don't understand the whole question. But I can answer this part of your question.
Question : I need to create a function that looks for the parameter passed by url in the database, more specifically in the table "company", column "name"
Route
Route::get('companies/{name}', 'CompaniesController#searchByName');
Controller
public class CompaniesController extends Controller
{
public function searchByName($name)
{
$company = Company::where('name', $name)->first();
return view('your_blade_view', compact('company'));
}
}
I'm having problems with Laravel since i removed Entrust.
Everything was working fine until i tried installing Entrust. I removed it because it kept saying the following message the same as this question Laravel cache store does not support tagging
Laravel cache store does not support tagging
I removed everything to do with Entrust and removed any changes I had to make but since then whenever I try to go to another page after logging in, it redirects back to the login page. I log back in and it redirects to the dashboard as it should but as soon as i go to another page, it redirects me back to login again.
Any ideas how to fix this?
UPDATE
I think i've narrowed down to the problem.
I created a new project and started again. I created the Auth, created a couple test controllers and views.
I logged in as normal and I got redirected to the Home contoller. I then went to another page and it loaded fine as it should. The views are using the default layout in views/layouts/app.blade.php. As soon as I change it to a custom layout the problem occurs again but is okay if i change it back to app.blade.php
Here is my new default.blade.php but i don't see why this doesn't work anymore
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>#yield('title')</title>
<link rel="icon" type="image/png" href="public/css/favicon-32x32.png" sizes="32x32">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/themes/smoothness/jquery-ui.css">
{{ HTML::style('css/bootstrap.css') }}
#if (!empty($styles))
#foreach($styles as $style)
{{ HTML::style($style . '.css') }}
#endforeach
#endif
{{ HTML::style('css/app.css') }}
{{ HTML::style('css/media.css') }}
</head>
<body class="{{ $body_class or '' }}">
<div class="wrapper">
#include('layouts.header')
#yield('content')
<div class="push"></div>
</div>
<div class="footer navbar-primary">
<div class="row">
<div class="col-xs-12">
<footer>
<p>© Copyright #php echo date('Y'); #endphp Axminster Tools & Machinery</p>
</footer>
</div>
</div>
</div>
<script>
window.website_url = '{{ URL::to('/') }}';
</script>
{{ HTML::script('assets/src/jquery/dist/jquery.min.js') }}
{{ HTML::script('assets/src/jquery-ui/jquery-ui.min.js') }}
{{ HTML::script('js/bootstrap.min.js') }}
{{ HTML::script('js/validate.js') }}
#if(isset($jsVars))
<script>
#foreach($jsVars as $key => $val)
var {{ $key }} = {{ $val }};
#endforeach
</script>
#endif
<script>
$(function() {
$("#searchform").submit(function(e) {
$("#searchform").attr("action", "/search/term/" + encodeURI($("#keywords").val()));
});
});
</script>
#if (!empty($scripts))
#foreach($scripts as $script)
{{ HTML::script($script . '.js') }}
#endforeach
#endif
</body>
</html>
I eventually found the problem.
After doing a new installation i tested the Auth and it worked. As soon as I copied across some of my template files I found the problem occurred again. After looking at the template layout files, I found I was using this for the logout link
Change password
I did this within the first few days of learning Laravel and it was never a problem before...don't know why.
I changed it to this and it all works as expected
Logout
<form id="logout-form" action="{{ url('/logout') }}" method="POST" style="display: none;">
{{ csrf_field() }}
</form>
I am working with a part of my application that sends out emails the moment, I want the emails to use a base layout (branding etc) and then an individual template loaded in within that, that is specific to the email type, I know that you can do layouts in views like this when using a controller and view,
protected $layout = 'layouts.master';
however I cannot find a suitable way to use this when sending an email like this,
Mail::send('emails.organisations.admin_removed', $array, function($message) use ($array) {
$message->to("email#email.com", "Simon Ainley")
->from('sender#email.com', 'Email Sender')
->subject("Email Sender - Subject");
});
Is it possible to have a master email template and then feed in sub views?
Yeah! this is possible.
Your main template (emails.orgainsations.template_layout.blade.php)
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="description" content=""/>
<meta name="author" content=""/>
<title>{{config('app.project_name')}}</title>
<style>
//your css goes here
</style>
</head>
<body>
<table width="600" cellspacing="0" cellpadding="0" border="0" class="wrap">
<tbody>
<tr>
<td class="header">
<h1 class="logo" title="Logo"><img src="{{ asset('assets/images/logo-mail.png') }}" alt="logo" /></h1>
</td>
</tr>
<tr>
<td style="padding: 20px; border: 1px solid #8a35e1; color: #323232;">
#yield('content')
</td>
</tr>
</tbody>
</table>
</body>
Your child template (emails.organisations.admin_removed)
#extends('emails.orgainsations.template_layout')
#section('content')
<p>
your mail content goes here
</p>
#endsection
And, in mail sending code, call the child template as usual
Mail::send('emails.organisations.admin_removed', $array, function($message) use ($array) {
$message->to("email#email.com", "Simon Ainley")
->from('sender#email.com', 'Email Sender')
->subject("Email Sender - Subject");
});
What you want to do is create a master blade template and the extension is done in the child blade templates. Then you pass the child template to your Mail::send() method.
So you have your master: emails/layouts/master.blade.php
<html>
<head>
<title>Email Master</title>
</head>
<body>
Dear {{ $recipient }}
<div class="container">
#yield('content')
</div>
Kind regards,
#include('emails/signature')
</body>
</html>
Then extend in the child template: emails/layouts/organisations/admin/remove.blade.php
#extends('emails.layouts.master')
#section('content')
<p>You have been removed</p>
#endsection
Then pass the child view to the send method:
Mail::send('emails.layouts.organisations.admin.remove', $array, function($message) use ($array) {
$message->to("email#email.com", "Simon Ainley")
->from('sender#email.com', 'Email Sender')
->subject("Email Sender - Subject");
});
I've glossed over a lot of details here so I highly recommend checking out the docs for further in-depth details: https://laravel.com/docs/5.2/blade
You should also try to familiarise yourself with all the different directives blade offers to take full advantage of all its features.
I have master layout of laravel blade template main.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>#yield('title','My Site')</title>
</head>
<body>
#yield('container','Content area')
{{ HTML::script('assets/js/jquery-1.9.0.js') }}
</body>
</html>
I extended it for another view index.blade.php
#extend('main')
I want to add javascript links to master layout(main.blade.php) if exists in child layout(index.blade.php)
added code in index.blade.php
$extraJs = array('plugins1.js','plugins2.js');
#section('extraJs')
{{ $extraJs }}
#stop
So, How can I add javascript to master layout if exists in child blade?
In php:
<?php
if(isset($extraJs)):
foreach($extraJs as $js):
?>
<script src="assets/js/<?php echo $js ?>" type="text/javascript" />
<?php endforeach; endif; ?>
You can just add a yield in your main.blade.php, like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>#yield('title','My Site')</title>
</head>
<body>
#yield('container','Content area')
{{ HTML::script('assets/js/jquery-1.9.0.js') }}
#yield('javascripts')
</body>
</html>
Then, in your child layout, you add a section for it, like you did. For example:
#section('javascripts')
#foreach($scripts as $script)
{{ HTML::script('ets/js/' . $script) }}
#endforeach
#stop
If you add another child view which doesn't need to use extra javascripts, Laravel won't complain because the section is optional.
I wouldn't really encourage this method but since you asked. It is definitely possible to pass something "up" in the view tree. You can just define a PHP variable in your view and it will be available anywhere in the layout.
index.blade.php
<?php $extraJs = array('plugins1.js','plugins2.js'); ?>
main.blade.php
#if(isset($extraJs))
#foreach($extraJs as $js)
<script src="{{ asset('assets/js/'.$js) }}" type="text/javascript" />
#endforeach
#endif
As you can see I also converted your code in the layout to blade and made use of the asset() function to generate absolute URLs
Note Instead of doing it this way there are other methods. For example View composers or defining the plugins in the controller.