Laravel slug breaks with slash - php

I have my slug stored in my database. In my controller i retrieve my slug en then add a view to it.
It all works fine if i have a url like domain.com/prices.
But when i have a url like domain.com/prices/somethingelse then the app breaks.
Looks like i cannot handle the /
In my datebase i have the right url..
This is my controller:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Content;
use App\Models\Product;
use App\Models\Brand;
use App\Models\Thumbnail;
use App\Models\Content_blocks;
use App\Models\Basiscontent;
use App\Models\Contentcategory as Contentcategories;
use App\Models\View as viewValue;
use App\Models\Banners as Banner;
use App\Models\Aanbieding;
use Illuminate\Http\Request;
use Illuminate\View\View as template;
use Illuminate\Support\Facades\View;
class ContentController extends Controller
{
/**
* Gebruikerslijst
*
* #param Request $request
* #param string $slug
* #param string $value
*
* #return template
*/
public function index(Request $request, string $slug = '', string $value = '', int $id = null): template
{
if ($slug == '') {
$slug = '/';
}
$content = Content::getContentBySlug($slug);
if ($content === null) {
return abort(404);
}
$pageSlug = $content->slug;
$view = $content->view()->first();
if ($view === null) {
$view = 'index';
} else {
// $pageView = $content->view()->first()->value;
// $view = $pageSlug !== $pageView ? 'index' : $pageView;
$view = $content->view()->first()->value;
};
$id = $content->id;
$content_blocks = Content_blocks::getContentBlock($id);
$content_block_thumb = Content_blocks::getContentThumb($id);
// dd(Content_blocks::categorie());
// dd($contentcategory = Contentcategories::all());
// $content_block_thumb = Content_blocks::getContentBlock();
// dd(Content::getContentBySlug($slug)->title);
// dd(Content_blocks::getContentBlock($id)->id);
// dd(Thumbnail::getFile(1));
$content_blocks_cat = Content_blocks::orderBy("order", "ASC");
// dd($content_blocks_cat->get());
return view::make($view)
->with('products', Product::all()->sortBy('order'))
->with('brands', Brand::all())
->with('banners', Banner::all())
->with('aanbiedingen', Aanbieding::all())
->with('contentcategory', Contentcategories::all())
->with('basiscontent', Basiscontent::all())
->with('content', $content)
// ->with('content_blocks', Content_blocks::all());
->with('content_blocks', $content_block_thumb)
->with('content_blocks_cat', $content_blocks_cat->get());
// ->with('thumbnail', Thumbnail::getFile($content_block_thumb->thumbnail_id));
// ->with('thumbnail', Thumbnail::getFile(1));
}
}
Route:
Route::get('{slug?}', '\App\Http\Controllers\ContentController#index');
Hope you can help me out.
Thanks!

For extra slashes, you need to add another layer check for the route:
Route::get('{slug1}/{slug2?}', '\App\Http\Controllers\ContentController#index');
Add as many for the route depths as needed. You'll need to adjust your function to accept the additional paramters as well.

Related

Codeigniter 4 Call to a member function get() on null

i have one project in CI3 and update for CI4
i have problem in my template, i receive Call to a member function get() on null.
my view not working call $this->traducao->get('search_string'); please help-me for update in class and libraries
My Function in Libraries
<?php
namespace App\Libraries;
use Config\Database;
class menus {
public $listMenus;
public $listSeo;
public function __construct(){
$this->set();
}
public function set(){
$db = Database::connect();
$builder = $db->table('menu');
$query = $builder->where("parente", 0)
->where("ativo", 1)
->orderBy('posicao', 'asc')
->get()->getResultArray();
if(is_array($query)){
$menusPai = $query;
}
$query2 = $builder->where("parente > 0")
->where("ativo", 1)
->orderBy('posicao', 'asc')
->get()->getResultArray();
if(is_array($query)){
$menusFilhos = $query2;
}
// $menusFilhos = ($query2->countAllResults() > 0) ? $query2->getResultArray() : false;
$menus = [];
foreach ($menusPai as $key => $value)
{
$this->listSeo[$value['link']]['pagina_titulo'] = $value['pagina_titulo'];
$this->listSeo[$value['link']]['pagina_keywords'] = $value['pagina_keywords'];
$this->listSeo[$value['link']]['pagina_description'] = $value['pagina_description'];
$menus[$value['id']]['filhos'] = [];
$menus[$value['id']]['dados'] = $value;
if ($menusFilhos)
{
foreach ($menusFilhos as $k => $v)
{
if ($v['parente'] == $value['id'])
{
$this->listSeo[$v['link']]['pagina_titulo'] = $v['pagina_titulo'];
$this->listSeo[$v['link']]['pagina_keywords'] = $v['pagina_keywords'];
$this->listSeo[$v['link']]['pagina_description'] = $v['pagina_description'];
$menus[$value['id']]['filhos'][] = $v;
}
}
}
}
$this->listMenus = $menus;
}
public function get(){
return $this->listMenus;
}
public function seo($tag){
$uri = new \CodeIgniter\HTTP\URI();
print_r($uri);
$uri = ($this->CI->uri->uri_string() == '') ? '/' : $this->CI->uri->uri_string();
return $this->listSeo[$uri][$tag];
// return $this->listSeo[$uri][$tag];
}
}
My ControllerBase
<?php
namespace App\Controllers;
use CodeIgniter\Controller;
use App\Libraries\My_parser;
use App\Libraries\Preferencia;
use App\Models\index_model;
use App\Libraries\Traducao;
use App\Libraries\Menus;
class BaseController extends Controller
{
protected $helpers = [];
public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
{
// Do Not Edit This Line
parent::initController($request, $response, $logger);
$this->_db = \Config\Database::connect();
$this->My_parser = new My_Parser();
$this->_model = new \App\Models\index_model();
$this->traducao = new Traducao();
}
public function output($data, $status){
$this->output
->set_status_header(200)
->set_content_type('application/json', 'utf-8')
->set_output(
json_encode(
array(
'status'=> $status,
'response'=> $data
),
JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
)
)->_display();
exit;
}
}
And my view
<div class="container">
<h2 class="text-center no-m"><?= $this->traducao->get('HOME_EMPRESAS_PARCEIRAS_TITULO') ?></h2>
and my index.php loading views layout
<?= $this->extend('template/head.php',array('css'=> $css, 'metatags'=> $metatags)) ?>
<?= $this->extend('template/header.php') ?>
<?= $this->extend('template/navbar.php') ?>
<?= $this->section('content')?>
<?= $this->endSection()?>
The short answer is it doesn't exist in the View because you never gave it to the View.
$this->traducao belongs to the Controller. It may have been constructed with the Controller but there's no immediate reason that any View would have access to it (or any data that wasn't passed directly to the View).
All incoming requests should be routed through Controllers; that is their most important purpose. Where is the Controller that's actually handling the request to your index.php file?
Any and all Views should be displayed by a Controller because that is where you have the ability to pass data (i.e. $this->traducao) into the View.
If this is actually CI4 as tagged, then you have a problem with CI3 code still being present as well; for example, $this->output isn't used to return Controller responses in CI4, it's $this->response instead.

How to fix this Uncaught UnexpectedValueException: Invalid route action

I'm trying to convert a closure-based routes to use a single action controller
So on my fuzzy.php inside routes folder i did this
write the codes
Route::get('theme/{file?}', 'FuzzyController')->name('fuzzy-theme.get');
and on my FuzzyController.php inside Core\Controllers\Assets
<?php
//namespace App\Http\Controllers;
namespace Core\Controllers\Assets;
// use App\User;
use App\Http\Controllers\Controller;
class FuzzyController extends Controller
{
/**
* Show the profile for the given user.
*
* #param int $id
* #return View
*/
public function __invoke(Request $request, $file = null)
{
$path = base_path(config('path.themes', 'themes').'/'.settings('active_theme', 'default'))."/$file";
$fileArray = explode('/', $file);
$lastFile = end($fileArray);
$extension = explode(".", $lastFile);
$fileExtension = end($extension);
$isCss = 'css' === $fileExtension ? true : false;
if (! in_array($fileExtension, config('downloadables', []))) {
return abort(403);
}
if (\File::exists($path)) {
$headers = [
'Cache-Control' => 'public',
'Content-Type' => 'text/css'
];
return response()->file($path, $isCss ? $headers : []);
}
return abort(404);
// return view('user.profile', ['user' => User::findOrFail($id)]);
}
}
can some explain why do i get an invalid route action thanks :D
The issue is because you haven't used namespace in your route definition. Change your route definition to:
Route::get('theme/{file?}', 'Core\Controllers\Assets\FuzzyController')->name('fuzzy-theme.get');
Hope this helps.

Change the view in the reset password email using Laravel 5.3

I'm using Laravel 5.3 and I'm working now on the reset password option on my CRM.
my CRM is multi-language therefore I need to change the email template / the view that sent to the customer based on his language, actually, I just need to change from RTL to LTR - this value is set on a cookie that called "user_direction".
I'm using the Laravel default bootstrap auth that includes ResetPassword class.
this is what is have now:
<?php
namespace Illuminate\Auth\Notifications;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\MailMessage;
class ResetPassword extends Notification
{
public $token;
public function __construct($token)
{
$this->token = $token;
}
public function via($notifiable)
{
return ['mail'];
}
public function toMail($notifiable)
{
$url = url('password/reset',$this->token);
$subject = trans('global.reset_password_email_subject');
$greeting = trans('global.reset_password_email_greeting');
$line_01 = trans('global.reset_password_email_line_01');
$action = trans('global.reset_password_email_action');
$line_02 = trans('global.reset_password_email_line_02');
return (new MailMessage)
->subject($subject)
->greeting($greeting)
->line($line_01)
->action($action, $url)
->line($line_02);
}
}
and this is the idea of what i want to have but i dont know how to write it right:
public function toMail($notifiable)
{
$url = url('password/reset',$this->token);
$subject = trans('global.reset_password_email_subject');
$greeting = trans('global.reset_password_email_greeting');
$line_01 = trans('global.reset_password_email_line_01');
$action = trans('global.reset_password_email_action');
$line_02 = trans('global.reset_password_email_line_02');
$view = "notifications::email";
if($request->cookie('user_direction') == "rtl"):
$view = "notifications::email-rtl";
endif;
return (new MailMessage)
->view($view)
->subject($subject)
->greeting($greeting)
->line($line_01)
->action($action, $url)
->line($line_02);
}
thank you for your help!
after watching some tutorials on youtube it worked for me, i wrote it this way:
first I add "use Cookie;"
public function toMail($notifiable)
{
$user_language_direction = Cookie::get('user_direction');
$url = url('password/reset',$this->token);
$subject = trans('global.reset_password_email_subject');
$greeting = trans('global.reset_password_email_greeting');
$line_01 = trans('global.reset_password_email_line_01');
$action = trans('global.reset_password_email_action');
$line_02 = trans('global.reset_password_email_line_02');
$view = "notifications::email";
if($user_language_direction == "rtl")
$view = "notifications::email-rtl";
return (new MailMessage)
->view($view,array())
->subject($subject)
->greeting($greeting)
->line($line_01)
->action($action, $url)
->line($line_02);
}
You can change the reset passwords view by overriding the function in
use Illuminate\Foundation\Auth\ResetsPasswords Trait.
Simply add the following function in class
App\Http\Controllers\Auth\ResetPasswordController
modify your view.
/**
* Display the password reset view for the given token.
*
* If no token is present, display the link request form.
*
* #param \Illuminate\Http\Request $request
* #param string|null $token
* #return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function showResetForm(Request $request, $token = null)
{
return view('auth.passwords.reset')->with(
['token' => $token, 'email' => $request->email]
);
}

Laravel get Model by Table Name

Is there any way to get a model by table name?
For example, I have a "User" model, its table is defined as protected $table = "users"
Now, what I want to do is to get the model by table name which is equal to "users".
This function is more like the reverse of Model::getTable();
I have searched everywhere but I could not find a solution, perhaps I might be missing something simple?
EDIT
I am building something like an API :
Route::get('/{table}', 'ApiController#api');
Route::get('/{table}/filter', 'ApiController#filter');
Route::get('/{table}/sort', 'ApiController#sort');
Route::get('/{table}/search', 'ApiController#search');
so in the address bar, for example when I search for the "users", I could just hit on the URL:
api/users/search?id=1
then on the controller, something like:
public function search(){
// get all the params
// get the model function
$model = //function to get model by table name
// do some filtering, then return the model
return $model;
}
Maybe something like this will help you:
$className = 'App\\' . studly_case(str_singular($tableName));
if(class_exists($className)) {
$model = new $className;
}
studly_case() and str_singular() are deprecated functions.
You can use the Illuminate\Support\Str facade.
$className = 'App\\' . Str::studly(Str::singular($tableName));
I know that it is an old question, but it can help someone:
public function getModelFromTable($table)
{
foreach( get_declared_classes() as $class ) {
if( is_subclass_of( $class, 'Illuminate\Database\Eloquent\Model' ) ) {
$model = new $class;
if ($model->getTable() === $table)
return $class;
}
}
return false;
}
It will return the class name, so you need to instantiate it.
You must determine for which table name which class to call.
I see 2 ways to do this.
Use Laravel's models naming convention as #IgorRynkovoy suggested
or
Use some kind of dictionary
public function search($tableName)
{
$dictionary = [
'table_name' => 'CLASS_NAME_WITH_NAMESPACE',
'another_table_name' => 'CLASS_NAME_WITH_NAMESPACE',
];
$className = $dictionary[$tableName];
$models = null;
if(class_exists($className)) {
$models = $className::all();
}
// do some filtering, then return the model
return $models;
}
Alternative variant.
I have my base model App\Models\Model
This model have static method getModelByTable, ofcourse you can store this method anywhere you want.
public static function getModelByTable($table)
{
if (!$table) return false;
$model = false;
switch ($table) {
case 'faq':
$model = Faq::class;
break;
case 'faq_items':
$model = FaqItems::class;
break;
}
if ($model) {
try {
$model = app()->make($model);
} catch (\Exception $e) {
}
}
return $model;
}
Inherit from the following, instead of from Model.
use Illuminate\Support\Str;
class EnhancedModel extends \Illuminate\Database\Eloquent\Model
{
/**
* The table associated with the model. Copies $table in Model
*
* #var string
*/
protected static string $tableName;
/**
* Get the table associated with the model. Copies getTable() in Model
*
* #return string
*/
public static function getTableName(): string
{
return static::$tableName ?? Str::snake(Str::pluralStudly(class_basename(static::class)));
}
/**
* Get the table associated with the model. Overrides getTable() in Model
*
* #return string
*/
public function getTable(): string
{
return $this::getTableName();
}
}
To override the auto-guessed table name, add this to your EnhancedModel descendent class:
protected static string $tableName = 'the_table_name';
Looks Laravel 6 make some changes. The following works fine for me
use Illuminate\Support\Str;
....
$className = 'App\\' . Str::studly(str::singular($table_name));
if(class_exists($className)) {
$model = new $className;
}

DynamoDB and Laravel, Why I cant send data to my DDBB from a controller?

I have lost 40 minutes looking for an asnwer to this problem. =(
I have this Route in my routes.php:
Route:post('prueba', function(){
if(Request::ajax()){
$data = Input::all();
$purchase = new Purchase();
$purchase->buyer_id = '44444499999';
$purchase->payment_type = 'ewiicfifif';
$purchase->save();
return $data;
}
});
If I execute this route, everything is ok, and I can set the values in my DDBB in DynamoDB:
But, I don´t want the code in the route php, then, I have this:
Route::post('prueba', 'PruebaController#pruebaMet');
Ok, then, I have my controller:
use Auction\Purchase;
public function pruebaMet(){
if(Request::ajax()){
$data = Input::all();
$purchase = new Purchase();
$purchase->buyer_id = '12345';
$purchase->payment_type = 'Javi';
$purchase->save();
return $data;
}
}
But if I execute this route, I get nothing in my DDBB, I was thinking "maybe is the route", them, I changed all the code in my function pruebaMet() and I just put this "return "hello word", them, I can get data in my html. without problem.
Someone can help me? Why I can´t get the info in my database?
<?php
namespace Auction\Http\Controllers;
use Illuminate\Http\Request;
use Auction\Http\Requests;
use Auction\Http\Controllers\Controller;
use Input;
use Auction\Purchase;
class PruebaController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
return view('prueba');
}
public function pruebaMet(){
if(Request::ajax()){
$data = Input::all();
$purchase = new Purchase();
$purchase->buyer_id = '12345';
$purchase->payment_type = 'Javi';
$purchase->save();
return $data;
}
}
}

Categories