I am using Cakephp2.0 i created a custom function
<?php echo GenerateNavHTML($navarray); ?>
<?php
function GenerateNavHTML($nav)
{
if(!empty($nav)) {
if(isset($nav[0]['parent'])) {
$parentid=$nav[0]['parent'];
}else{
$parentid=1;
}
if($parentid==0) {
$html = '<ul style="display: block;" class="nav">';
}else {
$html='<ul>';
}
foreach($nav as $page) {
$html.='<li>';
$html .= '"'.$this->Html->url('Logout',array('controller'=>'users','action'=>'logout')).'"';
$html .= '</li>';
}
$html.='</ul>';
return $html;
}
}
?>
and it give
Fatal error: Cannot redeclare GenerateNavHTML()
But there is no redeclaration of function.
if i write
<?php
function GenerateNavHTML($nav)
{
if(!empty($nav)) {
if(isset($nav[0]['parent'])) {
$parentid=$nav[0]['parent'];
}else{
$parentid=1;
}
if($parentid==0) {
$html = '<ul style="display: block;" class="nav">';
}else {
$html='<ul>';
}
foreach($nav as $page) {
$html.='<li>';
$html .= '';
$html .= '</li>';
}
$html.='</ul>';
return $html;
}
}
?>
and it is working fine
i want to use cakephp syntax
Thanks
In MVC, this code should be part of a Helper, not just a standalone 'function'.
Creating your own Helper
This may sound hard, but it really isn't. It has many advantages as well; by moving your code to a Helper, it's easier to re-use and maintain.
For example;
Create a 'Navigation' helper (of course, give it a logical name);
app/View/Helper/NavigationHelper.php
class NavigationHelper extends AppHelper
{
/**
* Other helpers used by *this* helper
*
* #var array
*/
public $helpers = array(
'Html',
);
/**
* NOTE: In general, convention is to have
* functions/methods start with a lowercase
* only *Classes* should start with a capital
*
* #param array $nav
*
* #return string
*/
public function generateNavHTML($nav)
{
$html = '';
if (!empty($nav)) {
if (isset($nav[0]['parent'])) {
$parentid = $nav[0]['parent'];
} else {
$parentid = 1;
}
if ($parentid == 0) {
$html = '<ul style="display: block;" class="nav">';
} else {
$html = '<ul>';
}
foreach ($nav as $page) {
$html .= '<li>';
$html .= '"' . $this->Html->url('Logout', array('controller' => 'users', 'action' => 'logout')) . '"';
$html .= '</li>';
}
$html .= '</ul>';
}
// NOTE: moved this 'outside' of the 'if()'
// your function should always return something
return $html;
}
/**
* You can add other methods as well
* For example, a 'Convenience' method to create a link to the Homepage
*
* Simply use it like this:
* <code>
* echo $this->Navigation->logoutLink();
* </code>
*/
public function logoutLink()
{
return $this->Html->link(__('Log out'), array(
'controller' => 'users',
'action' => 'logout',
'confirm' => __('Are you sure you want to log out')
));
} }
Once you created that file, you can use it in any view or element;
echo $this->Navigation->generateNavHTML($navarray);
You don't even have to add it to the 'Helpers' array of your controller, because CakePHP 2.3 uses 'autoloading' to do that for you
If you need other functionality (related to 'Navigation'), you can just add a 'method' to the Helper, I added a 'logoutLink()' method just to illustrate this
For more information, read this chapter Creating Helpers
Try this:
<?php echo $this->GenerateNavHTML($navarray); ?>
And declare the function before all for secure
Related
Greetings,
i'm using a multiple file upload input in Yii2.
The multiole file input is saving very well the files selected inside a folder called audio.
The problen is i cannot inside foreach loop save the name and path of each file in the database model Faixas.php inside a field called ficheiro.
Here is my code:
Controller:
public function actionCreate()
{
$model = new Faixas();
if (Yii::$app->request->isPost) {
$model->files = UploadedFile::getInstances($model, 'files');
if ($model->upload()) {
return $this->render('create', ['model' => $model]);
}
}
return $this->render('create', ['model' => $model]);
}
The Model as a function named upload() to save the files in folder, but the part to save inside the model->ficheiro is not working (don't figure it out ?):
public function rules()
{
return [
[['nome', 'ficheiro', 'dummy1', 'dummy2', 'dummy3', 'dummy4', 'dummy5'], 'string', 'max' => 255],
[['files'], 'file', 'skipOnEmpty' => false, 'extensions' => 'mp3, ogg, webm', 'maxFiles' => 30],
];
}
public function upload()
{
$model = new Faixas();
if ($this->validate()) {
foreach ($this->files as $file) {
$file->saveAs('audio/' . $file->baseName . '.' . $file->extension);
// this part in not working, why ????
$filePath = 'audio/' . $file->baseName . '.' . $file->extension;
$model->ficheiro = $filePath;
$model->save();
}
return true;
} else {
return false;
}
}
And finally the view, which renders the input:
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
<?= $form->field($model, 'files[]')->fileInput(['multiple' => true, 'accept' => 'audio/*']) ?>
<button>Submit</button>
Any ideas on the way to get it done?
Many thanks...
The entire Faixas.php model class:
<?php
namespace app\models;
use Yii;
/**
* This is the model class for table "faixas".
*
* #property integer $id
* #property string $nome
* #property string $ficheiro
* #property string $dummy1
* #property string $dummy2
* #property string $dummy3
* #property string $dummy4
* #property string $dummy5
*/
class Faixas extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'faixas';
}
public $files;
/**
* #inheritdoc
*/
public function rules()
{
return [
[['nome', 'ficheiro', 'dummy1', 'dummy2', 'dummy3', 'dummy4', 'dummy5'], 'string', 'max' => 255],
[['files'], 'file', 'skipOnEmpty' => false, 'extensions' => 'mp3, ogg, webm', 'maxFiles' => 30],
];
}
public function upload()
{
if ($this->validate()) {
foreach ($this->files as $file) {
$file->saveAs('audio/' . $file->baseName . '.' . $file->extension);
$model = new Faixas();
// this part in not working, why ????
$filePath = 'audio/' . $file->baseName . '.' . $file->extension;
$model->ficheiro = $filePath;
$model->save();
}
return true;
} else {
return false;
}
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => Yii::t('app', 'ID'),
'nome' => Yii::t('app', 'Nome'),
'ficheiro' => Yii::t('app', 'Ficheiro'),
'dummy1' => Yii::t('app', 'Dummy1'),
'dummy2' => Yii::t('app', 'Dummy2'),
'dummy3' => Yii::t('app', 'Dummy3'),
'dummy4' => Yii::t('app', 'Dummy4'),
'dummy5' => Yii::t('app', 'Dummy5'),
];
}
// coloca o Audio na GridView
public function getAudio()
{
return \Yii::$app->request->BaseUrl.'/'.$this->ficheiro;
}
}
Seems you create the model in wrog place. You create a $model = new Faixas(); ouuside the loop. try creating inside.
public function upload()
{
if ($this->validate()) {
foreach ($this->files as $file) {
$file->saveAs('audio/' . $file->baseName . '.' . $file->extension);
$model = new Faixas();
$filePath = 'audio/' . $file->baseName . '.' . $file->extension;
$model->ficheiro = $filePath;
$model->save();
}
return true;
} else {
return false;
}
}
SOLVED... removed from the model file the rule:
[['files'], 'file', 'skipOnEmpty' => false, 'extensions' => 'mp3, ogg, webm', 'maxFiles' => 30],
Now the foreach() loop saves every file Path in the database.
Many thanks to all that somehow tried to achieve a solution.
I am trying to create a file upload on cakephp, I haven't been able to find any decent tutorials for cakephp 3.0 that go in detail, and I don't understand how to install plugins.
I have this in my add section
echo $this->Form->create('filename', array('action' => 'upload', 'type' => 'file'));
echo $this->Form->file('filename');
I haven't added anything in the controller yet
/**
* Index method
*
* #return void
*/
public function index()
{
$this->paginate = [
'contain' => ['Courses']
];
$this->set('contents', $this->paginate($this->Contents));
$this->set('_serialize', ['contents']);
}
/**
* View method
*
* #param string|null $id Content id.
* #return void
* #throws \Cake\Network\Exception\NotFoundException When record not found.
*/
public function view($id = null)
{
$content = $this->Contents->get($id, [
'contain' => ['Courses']
]);
$this->set('content', $content);
$this->set('_serialize', ['content']);
}
/**
* Add method
*
* #return void Redirects on successful add, renders view otherwise.
*/
public function add()
{
$content = $this->Contents->newEntity();
if ($this->request->is('post')) {
$content = $this->Contents->patchEntity($content, $this->request->data);
if ($this->Contents->save($content)) {
$this->Flash->success('The content has been saved.');
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error('The content could not be saved. Please, try again.');
}
}
$courses = $this->Contents->Courses->find('list', ['limit' => 200]);
$this->set(compact('content', 'courses'));
$this->set('_serialize', ['content']);
}
/**
* Edit method
*
* #param string|null $id Content id.
* #return void Redirects on successful edit, renders view otherwise.
* #throws \Cake\Network\Exception\NotFoundException When record not found.
*/
public function edit($id = null)
{
$content = $this->Contents->get($id, [
'contain' => []
]);
if ($this->request->is(['patch', 'post', 'put'])) {
$content = $this->Contents->patchEntity($content, $this->request->data);
if ($this->Contents->save($content)) {
$this->Flash->success('The content has been saved.');
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error('The content could not be saved. Please, try again.');
}
}
$courses = $this->Contents->Courses->find('list', ['limit' => 200]);
$this->set(compact('content', 'courses'));
$this->set('_serialize', ['content']);
}
/**
* Delete method
*
* #param string|null $id Content id.
* #return void Redirects to index.
* #throws \Cake\Network\Exception\NotFoundException When record not found.
*/
public function delete($id = null)
{
$this->request->allowMethod(['post', 'delete']);
$content = $this->Contents->get($id);
if ($this->Contents->delete($content)) {
$this->Flash->success('The content has been deleted.');
} else {
$this->Flash->error('The content could not be deleted. Please, try again.');
}
return $this->redirect(['action' => 'index']);
}
but after this no idea what to do.
First of all, you need to decide on WHEN you're going to handle uploads. I've managed to create a dirty (but working) approach using beforeMarshal method and afterSave method (I'll explain why these two at the end).
If you create your file input like:
<?= $this->Form->file('submittedfile', ['class' => 'form-control input-upload', 'style' => 'height:100px']) ?>
or for hasMany association:
<?= $this->Form->file('images.'.$i.'.submittedfile', ['class' => 'form-control input-upload', 'style' => 'height:100px']) ?>
and you define the right associations:
$this->hasMany('Images', [
'foreignKey' => 'model_id'
]);
you could process those files before the Entity gets patched and saved:
public function beforeMarshal(Event $event, \ArrayObject $data, \ArrayObject $options) {
$images = array();
$dir = md5(time().$data['name']);
for ($i = 0; $i < count($data['images']); $i++) {
$image = $data['images'][$i]['submittedfile'];
if (!empty($image['name'])) {
if(!isset($data['id'])) {
$data['temp_dir'] = $dir;
}
else {
$dir = $data['id'];
}
if ($this->Images->uploadFile(array('img', 'model', $dir), $image) === true) {
$images[] = array('name' => pathinfo($image['name'], PATHINFO_FILENAME), 'ext' => pathinfo($image['name'], PATHINFO_EXTENSION));
}
}
}
$data['images'] = $images;
}
This is of course an example. I've decided to check, if there's an ID property set on the Entity (like for edit), because if it's not (like for create), you have to somehow identify the right path.
Here you've got a file uploading function:
public function uploadDir($path = array()) {
return $this->wwwRoot . implode(DS, $path);
}
public function uploadFile($path = array(), $filetoupload = null) {
if (!$filetoupload) {
return false;
}
$dir = new Folder($this->uploadDir($path), true, 755);
$tmp_file = new File($filetoupload['tmp_name']);
if (!$tmp_file->exists()) {
return false;
}
$file = new File($dir->path . DS . $filetoupload['name']);
if (!$tmp_file->copy($dir->pwd() . DS . $filetoupload['name'])) {
return false;
}
$file->close();
$tmp_file->delete();
return true;
}
If you added your images while there was no subdirectory with main entity ID, you have to rename the directory as soon as you get the ID:
public function afterSave(Event $event, Entity $entity, \ArrayObject $options) {
if(!empty($entity->temp_dir)) {
$this->Images->renameFolder(array('img', 'model', $entity->temp_dir),$entity->id);
}
}
calling:
public function renameFolder($path = array(), $newName) {
$oldPath = $this->wwwRoot . implode(DS, $path);
$nameToChange = array_pop($path);
array_push($path, $newName);
$newPath = $this->wwwRoot . implode(DS, $path);
return rename($oldPath, $newPath);
}
Using beforeMarshal you're able to inject your file data into Entity structure before the whole Entity is ready for saving (with associations).
Using afterSave you're able to identify the main object ID and call the set of objects you've uploaded before.
Remember to set recursive rights for saving files onto the directory, as well as rights for creating and renaming directories.
I am writing a custom module for site map in drupal 7. What I had done is below.
function escorts_sitemap_render_menu ($menu)
{
$output = "<ul>";
foreach ($menu as $item)
{
$link = $item["link"];
if ($link["hidden"])
{
continue;
}
$output .= "<li>" . $link["title"] . "</li>";
if ($item["below"])
{
$output .= sitemap_render_menu($item["below"]);
}
}
$output .= "</ul>";
return $output;
}
function escorts_sitemap_content ()
{
$output = "<h1>Escorts Sitemap</h1>";
$output .= "<ul class=\"site_map_list\">";
$output .= sitemap_render_menu(menu_tree_all_data("main-menu"));
return $output;
}
function escorts_sitemap_menu ()
{
$items = array();
$items["sitemap"] = array (
"title" => "Escorts Sitemap",
"page callback" => "escorts_sitemap_content",
"access arguments" => array("access content"),
"type" => MENU_CALLBACK);
return $items;
}
then in template.php I implemented hook_theme too, below is the code :
function escorts_theme() {
return array(
'escorts_sitemap_content' => array(
'render element' => 'content',
'template' => 'page--sitemap',
'path' => drupal_get_path('theme', 'escorts') . '/templates'
),
);
}
But it is not appearing as I have my custom template file page--sitemap.tpl.php, can any one please guide me. But now what should I write in page--sitemap.tpl.php in order to render my sitemap
Maybe You should try next:
function escorts_theme() {
return array(
'escorts_sitemap_content' => array(
'variables' => array('content' => NULL)
/**
* I would not call template like this, cause it looks like
* pattern page--[node-type]
*/
'template' => 'page--sitemap',
)
);
}
And inside of menu callback function
function escorts_sitemap_content () {
$output = "<h1>Escorts Sitemap</h1>";
$output .= "<ul class=\"site_map_list\">";
$output .= sitemap_render_menu(menu_tree_all_data("main-menu"));
return theme('escorts_sitemap_content', $output);
}
This is one of ways. Also look in preprocess functions, and Drupal theme layer at all. And maybe ready module XML sitemap will be useful. Also be careful, if file is really located there.
And in template file just paste
<?php print $content; ?>
Regards
since yesterday i try to implement multiple file upload in my project, the database get's updated with the new filenames, but the files were not uploaded (to localhost).
So my view looks like this now:
<?php echo $this->Form->create('Upload', array('type' => 'file')); ?>
<fieldset>
<br/>
<?php echo $this->Form->input('files.', array('type' => 'file', 'multiple' => 'multiple', 'label' => '')); ?>
</fieldset>
<?php echo $this->Form->end(__('upload'));?>`
I added in my controller foreach():
$files = $this->request->data['Upload']['files'];
$counter = 0;
foreach ($files as $row) {
$counter += 1;
$uploads = $this->Upload->find('all');
$exists=false;
foreach ($uploads as $upl) {
if (strcmp($upl['Upload']['name'], $row['name'])==0)
$exists=true;
}
print_r($exists);
if ($exists) {
continue;
} else {
$this->Upload->create();
$this->Upload->set('name', $row['name']);
$this->Upload->set('type', $row['type']);
$this->Upload->set('size', $row['size']);
$this->Upload->save();
}
}
if($counter > 1) {
$this->Session->setFlash(__('Files uploaded'));
} else if($exists && $counter == 1) {
$this->Session->setFlash(__('File could not be uploaded. File already exists.'));
} else {
$this->Session->setFlash(__('File uploaded'));
}
In my logs it gives me the following errors:
Warning (512): FileUpload: A file was detected, but was unable to be processed due to a misconfiguration of FileUpload. Current config -- fileModel:'Upload' fileVar:'file' [APP/Plugin/file_upload/Controller/Component/FileUploadComponent.php, line 403]
And the other on:
Warning (2): Invalid argument supplied for foreach() [APP/Plugin/file_upload/Controller/Component/FileUploadComponent.php, line 341]
My FileUploadComponent is the following
* #link http://www.webtechnick.com
* #author Nick Baker
* #version 4.0.4
* #license MIT
And line 341 in FileUploadComponent is the following:
function processAllFiles(){
foreach($this->uploadedFiles as $file){
$this->_setCurrentFile($file);
$this->Uploader->file = $this->options['fileModel'] ? $file[$this->options['fileVar']] : $file;
$this->processFile();
}}
Maybe some of you know this problem already and can give me a hint for this?
So i just disabled the FileUploadComponent and inserted
if ($exists) {
continue;
} else {
--> move_uploaded_file($row['tmp_name'], WWW_ROOT . 'files/' . $row['name']);
$this->Upload->create();
$this->Upload->set('name', $row['name']);
$this->Upload->set('type', $row['type']);
$this->Upload->set('size', $row['size']);
$this->Upload->save();
}
Now it works fine :)
I have an entityform block and I want to add bootstrap classes to its input!
How can I do this and what files should I edit?
I'm using latest version of entityform and entity block on drupal.org
thank you
You need to add these functions to your template.php file inside your theme folder (replace THEME_NAME with the actual name of your theme):
function THEME_NAME_textfield($variables) {
$element = $variables['element'];
$element['#attributes']['type'] = 'text';
element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength'));
_form_set_class($element, array('form-text'));
$element['#attributes']['class'][] = 'form-control';
$extra = '';
if ($element['#autocomplete_path'] && drupal_valid_path($element['#autocomplete_path'])) {
drupal_add_library('system', 'drupal.autocomplete');
$element['#attributes']['class'][] = 'form-autocomplete';
$attributes = array();
$attributes['type'] = 'hidden';
$attributes['id'] = $element['#attributes']['id'] . '-autocomplete';
$attributes['value'] = url($element['#autocomplete_path'], array('absolute' => TRUE));
$attributes['disabled'] = 'disabled';
$attributes['class'][] = 'autocomplete';
$extra = '<input' . drupal_attributes($attributes) . ' />';
}
$output = "<div class='input-wrapper'>";
$output .= '<input' . drupal_attributes($element['#attributes']) . ' />';
$output .= "</div>";
return $output . $extra;
}
function THEME_NAME_button($variables) {
$element = $variables['element'];
$element['#attributes']['type'] = 'submit';
element_set_attributes($element, array('id', 'name', 'value'));
$element['#attributes']['class'][] = 'form-' . $element['#button_type'];
$element['#attributes']['class'][] = 'btn btn-default';
if (!empty($element['#attributes']['disabled'])) {
$element['#attributes']['class'][] = 'form-button-disabled';
}
$value = $element['#attributes']["value"];
if( isset($element['#attributes']["button-type"]) && $element['#attributes']["button-type"] == "search" ) {
$value = $element['#attributes']["icon"];
unset($element['#attributes']["icon"]);
}
return '<button' . drupal_attributes($element['#attributes']) . '>' . $value . '</button>';
}
function THEME_NAME_select($variables) {
$element = $variables['element'];
element_set_attributes($element, array('id', 'name', 'size'));
_form_set_class($element, array('form-select', 'form-control'));
return '<select' . drupal_attributes($element['#attributes']) . '>' . form_select_options($element) . '</select>';
}
These functions will add the classes you need for the button, textfield and select input types. Also you will need to include the bootstrap files in your theme.