Well, let's say that I have 100 calls to "form_input" function. Theses calls includes text(70) and uploads(30).
My uploads were simple before. Now I change a bit and add: image preview and file name preview. but I do not want to change all places (30), I can and it's easy, but Ido not want for now.
I do not want to change "core" files, if this is the way, I prefer to use the function with other name.
form_input($p1, $p2, $p3){
if($p1['type']=='file'){
//do my lovely upload
}else{
//call built-in form_input (this is not a recursive call)
form_input($p1, $p2, $p3);
}
}
There are various ways to do this.
Make it a class. Make a new class with your custom form functions and just instantiate it when you need it. While helpers in CodeIgniter are supposed to be classless, this will work well and organize your code better. For example,
class CustomFormHelper {
function form_input() {
// your code
}
}
$form_helper = new CustomFormHelper();
$form_helper->form_input();
Change the function name. As a commenter said, just change the function name, it should be a quick fix.
Make a multifunction. This isn't the cleanest solution but if you want to unify both, this should do the trick.
function form_input_unified($fn, $args) {
if ($fn == 1) {
// execute original...
} elseif ($fn == 2) {
// do it new way.
}
}
Related
Given following code:
class Picture {
public function getAbsolutePathAttribute() {
return "absolute_path"
}
}
$picture = new Picture();
echo $picture->absolute_path; // prints "absolute_path"
$picture->absolute_path = "I will override you no matter what";
echo $picture->absolute_path; // prints "absolute_path"
Is there way of overriding an eloquent mutator attribute?
I have tried a magic method:
setAbsolutePathAttribute($value) {
$this["attributes"] = $value;
}
However it did not work.
So I don't recommend trying to solve this by overriding the mutator. You might be able to, but the less you touch the core of Laravel the better. Why? Because you never know what future Laravel code could look like.
A core change could possibly break your internal override the next time you do a minor or major Laravel version upgrade.
So, 2 ways to solve this, given your simple example:
1. Create a default value at the database level
Laravel migrations feature a default column modifier, it looks something like this: ->default('something')
That way you don't need the mutator at all for getting that default value you're looking for.
You can read more about them here: https://laravel.com/docs/5.6/migrations#column-modifiers
2. Make your accessor smarter
Your example is pretty simple, so I'll just work with it:
class Picture {
public function getAbsolutePathAttribute() {
if(is_null($this->absolute_path)) {
return "absolute_path";
}
return $this->absolute_path;
}
}
That way it only does something if there is no value present.
In my default layout, I have a snippet that check if $this->fetch('noindex') is true. This allow me to don't index specific pages by adding $this->assign('noindex', true); in my views. But what I want, is assigning this variable to true, only when the prefix is admin. To this problem, I have found two solutions with one not working.
Solution 1: In the AppController
public function beforeRender(Event $event)
{
if($this->request->param('prefix') === 'admin'){
$this->set('noindex', true);
}
}
This way allow me to check the prefix, but I would have to do $this->assign('noindex', $noindex); in every views. So this is not a great solution.
Solution 2: In the AppView (not working)
In my AppView, I can assign variables for my layouts without having to do it in all views.
public function initialize()
{
$this->assign('noindex', true);
}
But I can't do it depending on the prefix.
Solution 3: A mix (not working)
In the doc, we can see the event list of the AppView, so I though I could use the two solutions to do something working. But nothings happen.. I think that this is not the way I should use these.
// In AppController
public function beforeRender(Event $event)
{
if($this->request->param('prefix') === 'admin'){
$this->set('noindex', true);
}
}
// In AppView
public function afterRender()
{
$this->assign('noindex', $noindex);
}
So what do you think is the best way to achieve this ?
I don't get the real problem you try to solve. I assume you want do to this:
if ($this->request->param('prefix') === 'admin'){
echo $this->Html->meta('robots', 'noindex, nofollow');
}
Either put this directly in the layout file or create a custom helper and put it in a method of it and call it
echo $this->MyHelper->conditionalNoFollow();
in your layout(s).
And by the way, assign doesn't set a variable but a blocks content. No idea if this is your intend or not.
Before comment please read carefully... Im working on an framework like wordpress widgets and sidebars. These are predefined functions. In our framework I need to pass arguments which create dynamic function definitions. create_function() does not fulfil my requirement.
I have a situation in which I need to create dynamic functions. So, I have created an array which contain function's names. Please refer below example which describe the situation.
E.g.
$dynArr = array(
'function_one',
'function_another',
'function_another_one',
);
foreach ($dynArr as $key => $val) {
function $key() {
// FUNCTION DESCRIPTION HERE
}
}
Is there any solution to do this with PHP or using wordpress filters etc.
Maybe this will help you:
$function = function()
{
echo 'Im annonymous function';
};
$function();
PHP 5.3 required to work ;-)
The most universal way to do it is using eval():
eval('function abc() { echo "hello"; }');
abc();
Propably this is what you need to do as you mentioned wordpress. But I would suggest to go against it, it's inefficient and dangerous, and instead generate a php file instead, if the body of the functions doesn't change that often.
Apologies if I'm using the wrong terminology to describe what I'm trying to do...
I have a model/controller called Report which users can view like so:
example.com/reports/view/123
Each report hasAndBelongsToMany File objects. I need to make those files accessible like so:
example.com/reports/view/123/file/456
Or
example.com/reports/view/123/456
^ ^
| |
report file
I'm intentionally NOT creating a separate action for files (example.com/files/view...) because access to the file is relative to the report.
What is the correct way to do this in CakePHP?
My first guess is to add logic inside of ReportsController::view that checks for the existence of the second parameter (file) and manually render() a different view (for the file) conditionally. But I'm not sure if this is "the CakePHP way".
You are in the right path, modify your action to accept an optional parameter.
public function view($file = null) {
$somethingElse = null;
if (isset($file)) {
//your logic
$somethingElse = $this->Foo->bar();
}
$this->set(compact('somethingElse'));
}
Regarding to the view, I don't know your requirements, but I think you don't need to create a different view, you can either put a conditional in your view to show something, or (my favourite approach) create an element that will be displayed only if $somethingElse contains something. That is:
//View code
if (!empty($somethingElse)) {
echo $this->element('yourAwesomeElement', compact('somethingElse'))
}
Then in yourAwesomeElement
foreach ($somethingElse as $something) {
echo $something;
}
The good thing is that your element will be reusable for future views that could need this.
I needed to create dynamic breadCrumbs that must be realized automatically by the application. So I have the following structure in the URL for navagation:
nav=user.listPMs.readPM&args=5
then i could have a function-file whose sole purpose would be to define the user.listPMs.readPM function itself:
file: nav/user.listPMs.readPM.php
function readPM($msgId)
{
/*code here*/
}
Of course this ends up cluttering the global scope since i'm not wrapping the function withing a class or using namespaces. The best solution here seems to be namespacing it, no doubt right? But I also thought of another one:
file: nav/user.listPMs.readPM.php
return function($msgId)
{
/*code here*/
};
Yep, that simple, the file is simply returning an anonymous function. I think this is amazing because i don't need to care about naming it - since i've already properly named the file that contains it, creating a user function and yet having to name it would seem just redundant. Then in the index I would have this little dirty trick:
file: index.php
if($closure = #(include 'nav/'.$_GET['nav']))
{
if($closure instanceof Closure)
{
$obj = new ReflectionFunction($closure);
$args = explode(',',#$_GET['args']);
if($obj->getNumberOfParameters($obj)<=count($args))
call_user_func_array($closure,$args);
else
die('Arguments not matching or something...');
} else {
die('Bad call or something...');
}
} else {
die('Bad request etc.');
}
Don't even need to mention that the breadCrumbs can be nicely built latter just by parsing the value within the $_GET['nav'] variable.
So, what do you think, is there a better solution to this problem? Have you found another way to explore Closures and/or Reflection?
I like the basic idea. But the implementation is pretty much terrible. Imagine that I set nav=../../../../../../etc/passwd. That would (depending on your server configuration) allow me to access your password file, which certainly is no good.