I am trying to build a dynamic page system with cakephp 3.
Using slugs I can show pages and content. But on the homepage, it is just using the default view template.
I have the routes as followed:
$routes->connect('/', ['controller' => 'pages', 'action' => 'display', 'home']);
$routes->connect('/:slug', ['controller' => 'pages', 'action' => 'view'], ['pass' => ['slug'], 'slug' => '[^\?/]+']);
Which works for the none homepage pages.
But I want to use the homepage as / (e.g. localhost:8000/)
And not /home (e.g. localhost:8000/home).
Currently the view function in the pages controller looks like this:
public function view($slug = null)
{
$pages = TableRegistry::getTableLocator()->get('webpages');
$page = $pages->findBySlug($slug)->firstOrFail();
$this->set(compact('page'));
}
Any idea?
Seems I already found the solution.
I changed the routing to just the following line:
$routes->connect('/*', ['controller' => 'pages', 'action' => 'view']);
Then I changed the view as followed:
public function view($slug = null)
{
$pages = TableRegistry::getTableLocator()->get('webpages');
if($slug == null){
$query = $pages->find('all', [
'conditions' => ['ishome' => 1]
]);
} else {
$query = $pages->find('all', [
'conditions' => ['slug' => $slug]
]);
}
$page = $query->first();
$this->set(compact('page'));
}
I use the answer from the following comment, but had to modify it a bit, since that code was used for an older version of cakephp (I am using cakekphp 3.8).
https://stackoverflow.com/a/3975923/6181243
Related
I need to save html tags in features section of the create/edit product page.
I have changed TYPE_HTML and isCleanHTML in classes/FeatureValue.php, but the validation still ignores html tags.
Ex.
'value' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml', 'required' => true, 'size' => 255),
Thank you.
See example
You have to use definition of FeatureValue and change it so it can save HTML as well as need to change code in file where it is saving product custom feature value. Rather than changing in core files, I will make use of Overrides.
Follow below mentioned steps.
1) Create file Product.php file on path override\classes and put below code in it. This will save HTML in value field.
<?php
/**
* #override Product.php
*/
class Product extends ProductCore
{
/**
* Add new feature to product
*/
public function addFeaturesCustomToDB($id_value, $lang, $cust)
{
$row = array('id_feature_value' => (int)$id_value, 'id_lang' => (int)$lang, 'value' => pSQL($cust, true));
return Db::getInstance()->insert('feature_value_lang', $row);
}
}
2) Create FeatureValue.php file on path override\classes and put below code in it. Changing definition so that it can validate HTML.
<?php
/**
* #override FeatureValue.php
*/
class FeatureValue extends FeatureValueCore
{
/**
* #see ObjectModel::$definition
*/
public static $definition = array(
'table' => 'feature_value',
'primary' => 'id_feature_value',
'multilang' => true,
'fields' => array(
'id_feature' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true),
'custom' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
/* Lang fields */
'value' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml', 'required' => true, 'size' => 255),
),
);
}
3) To autoload newly created override class files; delete class_index.php file from var\cache\dev and var\cache\prod folder.
Hope it will help you!
Here is my store function
public function store(Request $request)
{
$post = new Post();
$post->author()->associate(auth()->user());
$post->fill($request->all());
$post->save();
return response()->json($post);
}
As a response i get:
I don't want all the data so I tried to take only the data I have defined like this:
$post = $post->only([
'id',
'title',
'content',
'published_at',
'author'
]);
And response now is:
Much better, but not completely. I can not define post author data in this way.
The only way is by creating a creepy relationship where you select only necessary data or like this:
$post = [
'id' => $post->id,
'title' => $post->title,
'content' => $post->content,
'published_at' => $post->published_at->toDateTimeString(),
'author' => [
'id' => $post->author->id,
'name' => $post->author->name,
'email' => $post->author->email,
]
];
So my question is... maybe there is more elegant way to achieve this.
Thank you very much!
The simplest way would probably be to just use only with the author as well:
return $post->only('id', 'title', 'content') + [
'author' => $post->author->only('id', 'name', 'email'),
];
If it was going to get any more complicated or reused somewhere else then I would suggest using something like Eloquent Resources
I would add a function to your Post model
public function jsonOutput()
{
$array['id'] = $this->id;
$array['title'] = $this->title;
$array['content'] = $this->content;
$array['author'] = [
'id' => $this->author->id,
'name' => $this->author->id
];
return $array;
}
and then call it like this
return response()->json($post->jsonOutput());
I am using the mpdf extension to generate pdf files. I have set global settings for the mpdf in the config file, hence I am able to call the function every time I want to generate a pdf from my controller action. However, I am finding it hard to change the orientation for the pdf with data that requires landscape orientation since the default orientation set in the global settings is portrait. Here are the codes:
main.pdf code for the global setting
'pdf' => [
'class' => Pdf::classname(),
'mode' => Pdf::MODE_UTF8, // leaner size using standard fonts
'format' => Pdf::FORMAT_A4,
'orientation' => Pdf::ORIENT_PORTRAIT,
'destination' => Pdf::DEST_BROWSER,
'cssFile' => '#vendor/kartik-v/yii2-mpdf/assets/kv-mpdf-bootstrap.min.css',
// any css to be embedded if required
'cssInline' => '.kv-heading-1{font-size:18px}',
'options' => [
'shrink_tables_to_fit' => 0
],
// refer settings section for all configuration options
],
Controller Action calling the global settings:
public function actionReservationsList()
{
$searchModel = new ReservationsSearch();
$dataProvider = $searchModel->search(Yii::$app->session->get('repquery'));
$dataProvider->pagination = false;
$pdf = Yii::$app->pdf;
$pdf->content = $this->renderPartial('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
$pdf->methods = [
'SetHeader' => [Yii::$app->user->identity->company->name.'||Date: ' . date("r")],
'SetFooter' => ['User: '.Yii::$app->user->identity->username.'||Page {PAGENO}'],
];
return $pdf->render();
}
So I need help in overriding the 'orientation' => Pdf::ORIENT_PORTRAIT, setting that is in the global settings main.php file from the controller action.
This work for me:
<?php
namespace backend\controllers;
use Yii;
use yii\web\Controller;
use kartik\mpdf\Pdf;
class InformesController extends Controller
{
...
public function actionImprimirInforme($id,$key)
{
$html = $this->renderPartial('informe-pdf', [
'title' => 'Informe'
]);
$pdf = new Pdf([
'format' => Pdf::FORMAT_A4,
'orientation' => Pdf::ORIENT_LANDSCAPE,
'destination' => Pdf::DEST_BROWSER,
'options' => [
'showImageErrors' => true,
]
]);
$pdf->configure([
'title' => 'Informe ',
]);
$pdf->content = $html;
$pdf->orientation = Pdf::ORIENT_LANDSCAPE;
$pdf->execute('SetFooter', ['{PAGENO} de {nbpg}']);
$pdf->filename = "Informe.pdf";
return $pdf->render();
}
}
My first answer was wrong, i have been setting the property 'orientation' into pdf component, so the dynamically assign does not work properly.
Here you have the documentation example
You need to add the contents via addPage. So if you build a array of pages, with the contents etc - you should be able to specify the orientation per page.
<?php
$mpdf = new mPDF('', 'Legal');
$mpdf->WriteHTML('
Hello World
');
$mpdf->AddPage('L'); // Adds a new page in Landscape orientation
$mpdf->WriteHTML('
Hello World
');
$mpdf->Output();
?>
Try add this line this :
$pdf = Yii::$app->pdf;
$pdf->orientation = Pdf::ORIENT_LANDSCAPE;
I'm trying to include a csv exporter in my application, And i used https://github.com/FriendsOfCake/cakephp-csvview.
It works fine on my local machine but for some reason it doesn't work on my server. It throws me View class "CsvView.csv" is missing. error. Is there a way to fix this issue?
Here's my controller for reference
public function export() {
$this->response->download('export.csv');
// $opts1['order'] = array('Blogs.created' => 'desc');
// $blogsinfos = $this->Blogs->find('all',$opts1);
$opts1['order'] = array('Incomes.title' => 'desc');
$data = $this->Incomes->find('all',$opts1)->toArray();
$_serialize = 'data';
// Give the needed the colums to extract
$_extract = ['id', 'title' ,'description' , 'created' , 'amount'];
//headings for the CSV
$_header = ['ID', 'Title' ,'Description' , 'Created' , 'Amount'];
$this->set(compact('data', '_serialize', '_header', '_extract'));
$this->viewBuilder()->className('CsvView.csv');
return;
}
Code to create the downloadable link.
<?= $this->Html->link('Monthly Report', [
'controller' => 'incomes',
'action' => 'export',
'_ext' => 'csv'
],
['class' => 'btn btn-success'])
?>
I'm using CakePHP 3.4.7.
I want to create a dynamic menu with my table (db). I have followed some instructions which are given below:
Table : "menupanal"
Step 01: I just create a super controller in app\components\Controller.php
Here is the code:
namespace app\components;
use app\models\MenuPanal;
class Controller extends \yii\web\Controller
{
public $menuItems = [];
public function init(){
$items = MenuPanal::find()
->where(['c_type' => 'MENU'])
->orderBy('id')
->all();
$menuItems = [];
foreach ($items as $key => $value) {
$this->menuItems[] =
['label' => $value['c_name'],
'items'=> [
['label' => $value['c_redirect'], 'url' => ['#']],
],
];
}
parent::init();
}
Step 02: Changed n main layout page:
echo Nav::widget([
'options' => ['class' => 'navbar-nav navbar-right'],
'items' => Yii::$app->controller->menuItems,
]);
It is working in only one level. My question::
Question : how can I add multilevel menu using Super controller ?
I am new in Yii2. Helps are highly appreciated.
Create New MenuHelper in Component folder. There is no default component folder. Please create by yourself.
<?php
namespace app\components;
use app\models\MenuPanel;
use app\models\Zuser;
use app\models\Vwrole;
use app\assets\AppAsset;
class MenuHelper
{
public static function getMenu()
{
$role_id = 1;
$result = static::getMenuRecrusive($role_id);
return $result;
}
private static function getMenuRecrusive($parent)
{
$items = MenuPanel::find()
->where(['c_parentid' => $parent])
->orderBy('c_sortord')
->asArray()
->all();
$result = [];
foreach ($items as $item) {
$result[] = [
'label' => $item['c_name'],
'url' => ['#'],
'items' => static::getMenuRecrusive($item['id']),
'<li class="divider"></li>',
];
}
return $result;
}
}
in Main Layout Page put the following code
echo Nav::widget([
'options' => ['class' => 'navbar-nav navbar-right'],
'items' => app\components\MenuHelper::getMenu(),
Enjoy Coding!!
You may use nested sets. Look at this extension for Yii: http://www.yiiframework.com/extension/nestedsetbehavior/ and its documentation. All you need to do is component with dynamic creation of menu items array for nested sets.
I found that there is a Yii2 extension version: http://www.yiiframework.com/extension/yii2-nestedsetbehavior/
Good luck
You may use this extension for multilevel dropdownMulti level Dropdown