blade variables inside a string that can be compiled in the view - laravel

In my database I have two tables, Pages and Articles.
In my Pages table I have the following:
+----+------------------+--------------+
| id | content | slug |
+----+------------------+--------------+
| 1 | {{$articleBody}} | /news/{slug} |
+----+------------------+--------------+
In my Articles table I have the following:
+----+----------------+--------------+
| id | content | slug |
+----+----------------+--------------+
| 1 | Blah blah balh | /news/1 |
+----+----------------+--------------+
I also have a standard blade file called wrapper.blade.php:
<body>{{$pageContent}}</body>
In my web.php file I do the following to return Page (ID:1) and Article:
return view("wrapper", ["Article"=> Article::find(1), "pageContent" => Page::find(1)->content]);
The idea is that I can change the Page content around Article in a CMS manner that includes.
I have tried:
return view("wrapper", ["articleBody"=> Article::find(1)->content, "pageContent" => Blade::compileString(Page::find(1)->content)]);
But I haven't had much luck.

When you use blade , first thing that it does, is to compile the file to something understandable by PHP. For example {{ => <?php or #if(...) #endif => <?php if(...){} ?>.
when you use {{first_name}} in your string the {{ and }} are not there in the file.blade.php when the blade is caching the views.
after the caching of blade files is done, the server run the php file and {{first_name}} will be placed in the file and treated as string.
something that you are looking for is str_replace().
lets say your string is $String = "Hello something_unique, how are you?"
then in your blade file use {{ str_replace("something_unique", $first_name, $String ); }}. I think it is what you are looking for.

you should use
$string = "Hello".$first_name.", how are you ? "

Related

How to make multiple roles in Spatie Laravel package?

Is possible with Spatie's laravel-permission package to achieve something like what Facebook have with their permissions for pages?
Case study,
On Facebook you can create a page, then automatically you'll become Admin (assuming it's a role) of that page.
Then you can invite you friend and make him/her a Publisher role
After that, your friend can also invite you to their Page and make you an Editor ( that's another role for you)
so at the end you will have two roles for two different profiles/Pages.
I want to achieve something like that on my app.
EDIT
what i know for now is that i can use:
$user->assignRole('editor');
and i can check if the user has a roles with :
$user->hasRole('writer')
But the thing is how do i link that role with the page that i want them to manage?
Like if you have admin role in one page and editor role in another page.
and if you just check if $user->hasRole('admin') the results will always be true. so i want to know if there is anything i can do to assign and also check which page are you admin for.
I hope i am making sense.
Assuming your table structure looks like this:
Pages table
|---------------------|------------------|------------------|------------------|
| id | name | created_at | updated_at |
|---------------------|------------------|------------------|------------------|
| 12 | PHP masters | 2019-02-31 | 2019-03-12 |
|---------------------|------------------|------------------|------------------|
Pages admin
|---------------------|------------------|------------------|------------------|
| id | page_id | role_id | user_id |
|---------------------|------------------|------------------|------------------|
| 1 | 12 | 2 | 2 |
|---------------------|------------------|------------------|------------------|
Roles table
|---------------------|------------------|------------------|------------------|
| id | name | created_at | updated_at |
|---------------------|------------------|------------------|------------------|
| 12 | Editor | 2019-02-31 | 2019-03-12 |
|---------------------|------------------|------------------|------------------|
| 12 | System Admin | 2019-02-31 | 2019-03-12 |
|---------------------|------------------|------------------|------------------|
| 12 | Page Admin | 2019-02-31 | 2019-03-12 |
|---------------------|------------------|------------------|------------------|
Now inside User model add this method
#do not forget to import Roles
#use Spatie\Permission\Models\Role;
public function can_manage($page_id) : bool;
{
#Backdoor for the system admin
if ($this->hasRole(['System Admin'])) {
return true;
}
#now we check if the user has the role for that page
$role = Role::select('name')
->join("page_admins", 'page_admins.role_id', '=', 'roles.id')
->where("page_id", $page_id)
->where("user_id", $this->id)
->first();
#return true if roles was found
if (!empty($role)) {
return true;
}
#else false
return false;
}
Lastly if you want to check if the user can access the page's admin you use:
#for jwt-auth
#$user = $request->user();
if ( $user->can_manage($page_id) )
{
#then do you things
}
Now that you saw how to check if someone is among page administration, you can get creative with that. you can create a method that :
#Get user role in the page
#etc
Yes. You can create the roles with artisan and assign them in php.
php artisan permission:create-role editor
php artisan permission:create-role publisher
$user->assignRole(['editor', 'publisher']);
all of this is easily available in the documentation

Laravel routes prefix and ressources resulting in 404 not found

I've this Laravel routing issue. I don't really understand why my route:list tells me that an {} empty is appended to the URL? I believe this is the reason why my calls returns 404 not found.
I'd like DepartmentController to be inside my grouped body as I need the ID for other purposes. If I move ressource outside the prefix/group this scenarie works, but the other dosen't. This is my preferred way of structuring my routes, but it troubles me that / dosen't just use the prefixed URL, but it for some reason append it with {}
What am I doing wrong?
Calling URL: /department/1/edit
Result: 404 Not Found
Routes:
Route::prefix( 'department/{department_id?}' )->group( function () {
Route::resource( '/', 'DepartmentController' );
}
php artisan route:list:
| | GET|HEAD | department/{department_id?}/{} | show | App\Http\Controllers\DepartmentController#show | web |
| | PUT|PATCH | department/{department_id?}/{} | update | App\Http\Controllers\DepartmentController#update | web |
| | DELETE | department/{department_id?}/{} | destroy | App\Http\Controllers\DepartmentController#destroy | web |
| | GET|HEAD | department/{department_id?}/{}/edit | edit | App\Http\Controllers\DepartmentController#edit | web |
| | GET|HEAD | department/{department_id?}/create | create | App\Http\Controllers\DepartmentController#create | web |
| | POST | department/{department_id?} | store | App\Http\Controllers\DepartmentController#store | web |
| | GET|HEAD | department/{department_id?} | index | App\Http\Controllers\DepartmentController#index | web |
Update:
If I make a custom route like this:
Route::get( 'customedit', 'DepartmentController#editasddas' );
and request the url: /department/1/editasddas. It works as it's suppose to, but there is actually a reason why I'm using the ressource: to keep the routes as clean as possible. The ressource-routes have been implemented for that reason aswell, and I just need to implement the basic CRUD operations. Is this a bug in Laravel, or is this basically not possible? - really strange I think. It's not that complex.
I think you have this issue because how Route::resource creates subroutes itself (automatically adding a resource parameter within URLs, the parameter being {} at the end).
Also, note you are currently generating a index route with a department parameter, and that's not really useful.
Best solution for me is to move out your parameter:
Route::prefix( 'department' )->group( function () {
Route::resource( '/', 'DepartmentController' );
});
In the other hand, the department_id parameter will not be facultative. And you will need to add the parameter within each other custom routes (but that's what Route::resource does with its own routes after all).
Second one is to keep your prefix and declare each route individually. But you will need to change the default route names because department.index and department.show will have the exact same methods (GET and HEAD) and URLs (department/{department_id}).
Route::prefix('department/{department_id}')->group(function() {
Route::match(['get', 'head'], '/', 'DepartmentController#index')->name('department.index');
Route::match(['get', 'head'], '/show', 'DepartmentController#show')->name('department.show');
/* Declare all the others. */
});
The Route::resource method alone will achieve what you're looking for:
Route::resource( 'department', 'DepartmentController' );
Check the docs on this here, https://laravel.com/docs/5.8/controllers#resource-controllers

Route isn't passing variables to controller when used in blade

I'm using a named route in a view, passing two variables with it, but it throws the error that no arguments are passed.
I know that I could just construct the url for the href, but from what I've read so far is that what I'm trying should work just fine too (and I'm not seeing what I'm doing different from the documentation examples really).
link in show.blade.php
Change Name
in the browser the link shows up as
http://localhost/tasks/create?colony_slug=labr-oclh&action_name=change_name
route in web.php
Route::get('tasks/create/{colony_slug}/{action_name}', 'TaskController#create')->name('tasks.create');
TaskController#create
// CREATE ACTION
// =========================================================================
/**
* Show the form for creating a new resource.
*
* #param string $colony_slug
* #param string $action_name
*
* #return \Illuminate\Http\Response
*/
public function create($colony_slug, $action_name)
{
dd($colony_slug . " " . $action_name);
}
the error
Too few arguments to function App\Http\Controllers\TaskController::create(), 0 passed and exactly 2 expected
the routes list
| | GET|HEAD | tasks | tasks.index | App\Http\Controllers\TaskController#index | web,auth
|
| | POST | tasks | tasks.store | App\Http\Controllers\TaskController#store | web,auth
|
| | GET|HEAD | tasks/create/{colony_slug}/{action_name} | tasks.create | App\Http\Controllers\TaskController#create | web,auth
|
| | PUT|PATCH | tasks/{task} | tasks.update | App\Http\Controllers\TaskController#update | web,auth
|
| | DELETE | tasks/{task} | tasks.destroy | App\Http\Controllers\TaskController#destroy | web,auth
|
| | GET|HEAD | tasks/{task} | tasks.show | App\Http\Controllers\TaskController#show | web,auth
|
| | GET|HEAD | tasks/{task}/edit | tasks.edit | App\Http\Controllers\TaskController#edit | web,auth
|
|
As discovered through comment questions, the issue is your custom route conflicting with a Resource Controller route. Specifically in the route name (via named()), which should always be unique even if they use the same URI.
There are a couple solutions you can use, depending on what your functionality goal is:
Solution for: I only want one "Create Task" route
Disable the task.create route created by the resource controller by using the except() modifier:
Route::resource('tasks', 'TasksController')->except(['create']);
Leave your other route definition as-is. This will remove the URI /tasks/create from your app, and leave the one with the additional parameters.
Solution for: I want to use both
The route paths themselves are okay, and are only conflicting via the name. Name your custom route something different, and use it when you want to use the extra parameters.
Route::get('tasks/create/{colony_slug}/{action_name}', 'TaskController#create')->name('tasks.create-custom');
Solution for: I want to specify defaults on my Create Task form
I'm guessing that you're using these parameters in order to set some default values in your Create Task form. If that's what your end goal is, using the default Resource Controller route + query string parameters would work equally well, and won't involve extra routes.
Remove your extra custom route, and stick with the defaults from the Resource Controller
Declare a Illuminate\Http\Request dependency in your create() controller method:
public function create(Request $request)
{
// ...
}
Check for query string values in the request, and add them as defaults to your form.
As I look to all the code you provide it looks correct to me.
Maybe you should check your routes file. Remember routes have presedence top to botton, if you had another route with similar name it could be that this one is having precedence over the one you are tryint to use.

Laravel eloquent with archive table

I have two tables with same schema.
TABLE: items, items_archive
+-------------+-------------------
| partno |qty | brand|| category |
+--------------------------------+
| | | | |
| | | | |
| | | | |
+--------+----+------+-----------+
Is there any way to create a eloquent model which i can use to query from both at same time?
Item::where('brand', 'acer') => which will query will do something like union.
You should be able to take an approach like this:
$a = Item::where('brand', 'acer');
$b = ItemArchive::where('brand', 'acer');
$results = $a->union($b)->get();`
In this, we are creating 2 models with search queries, but not executing them. Finally, we union them together and the get() the results. You can then loop through the $results array for all the data.
Alternatively, you could hide all this logic inside your Item model:
public function retrieveAllWithArchive($brand)
{
return $this->where('brand', $brand)->union((new ItemArchive)->where('brand', $brand))->get();
}
Then, call it from anywhere with:
$results = (new Item)->retrieveAllWithArchive($brand);
Hope this helps!

Laravel blade template not rendering table properly

I'm quite new to Laravel, but have recently taken over a project from someone and trying to get the mail blade templates to render but I am having problems.
The code used for the enquiry email template is as follows:
#component('mail::message')
#New customer enquiry
We have received a new customer enquiry.
#component('mail::table')
| **Name** | **Email** | **Telephone** |
| ---------------------------------------------- |:---------------------:| -----------------------:|
| {{$enquiry->firstname}} {{$enquiry->lastname}} | <{{$enquiry->email}}> | {{$enquiry->telephone}} |
#endcomponent
Thanks,<br>
{{ config('app.name') }}
#endcomponent
But the table always renders as raw HTML, here is a screenshot of how the email looks in MailCatcher:
I've checked a couple of other posts that concern this kind of issue but usually it's due to the attempt to render more than one table in a mail template, but this is just a single table. Is there a component I have missed or is it just MailCatcher not rendering correctly?
When using Markdown to render emails, avoid using indents excessively. Your code should look like this
#component('mail::message')
#New customer enquiry
We have received a new customer enquiry.
#component('mail::table')
| **Name** | **Email** | **Telephone** |
| ---------------------------------------------- |:---------------------:| -----------------------:|
| {{$enquiry->firstname}} {{$enquiry->lastname}} | <{{$enquiry->email}}> | {{$enquiry->telephone}} |
#endcomponent
Thanks,<br>
{{ config('app.name') }}
#endcomponent
You didn't show how the html which is not being rendered is being loaded.
But it's possible you need to use {!! !!} instead of {{ }} for the variables that contain html.

Resources