A Logical Mistake on OOP - php

I'm learning Yii Framework . I'm working with a framework first time, i need some advices.
I have a getSocials() function on my Controller .
private function getSocials($id)
{
$socials=Socials::model()->find("socials_user=$id");
foreach ($socials as $social)
{
$type = $social["socials_type"];
$allSocial .= "<li>$type</li>";
}
return $allSocial;
}
(it's private because i'm calling it from another function only).
I'll explain it line by line,
$socials=Socials::model()->find("socials_user=$id");
Getting datas from database which socials_user collumn equals to $id, via Socials model.
foreach ($socials as $social)
$socials returning as an array because there are a few lines which socials_user collumn equals to $id on database .
$allSocial .= "<li>$type</li>";
On foreach loop, adding <li>...</li> to end of string, so $allSocial will be <li>...</li><li>...</li>...
BUt i'm getting Undefined variable: allSocial error . When i remove dot from front of equal symbol (=), it's working. But this time on foreach loop, it's overwriting always and finally $allSocial containing only last <li>...</li>
Are there any logical mistake ?

$allSocial is not defined anywhere, you cant attach a string to an undefined variable. Try it like this:
private function getSocials($id)
{
$socials=Socials::model()->find("socials_user=$id");
$allSocial = '';
foreach ($socials as $social)
{
$type = $social["socials_type"];
$allSocial .= "<li>$type</li>";
}
return $allSocial;
}

You need to define $allSocial before you try to concatenate anything to it. You may also want to consider returning an array instead so you can easily access the different strings.
private function getSocials($id) {
$socials=Socials::model()->find("socials_user=$id");
$allSocial = array();
foreach ($socials as $social)
{
$type = $social["socials_type"];
$str = "<li>$type</li>";
array_push($allSocial, $str);
}
return $allSocial;
}

find function will return only one record which is not an array so foreach will never execute
replace the code with following to get it working right :
private function getSocials($id)
{
$socials=Socials::model()->findAll('socials_user=:socials_user',
array(':socials_user'=>1));
$allSocial = '';
foreach ($socials as $social)
{
$type = $social["socials_type"];
$allSocial .= "<li>$type</li>";
}
return $allSocial;
}

Related

How to use array values outside foreach loop?

How can I use an array values outside a foreach loop in Laravel 5.4?
Here is the code :
public function index(Request $request)
{
$name = $request->input('keyword');
$category = $request->input('category');
$catkeywords = array(DB::table('keywords')->pluck($category));
foreach ($catkeywords as $catkeyword) {
$string = implode(',',$catkeyword);
}
echo $string;
}
I don't know why it doesn't work !
I just want the returned keywords from database to combine them with some text and to use for some API queries.
In other words, I want the list of keywords outside of the loop.
For using in an API query like this :
http://api-url/query?id=domain1.com,domain2.com,domain3.com
$catkeywords returns a json formatted list of keywords.
Now I want to combine these keywords with a user-inputted value and add a ".com" suffix,
then separate them using commas and use them on query url as a variable.
P.S : I'm using guzzlehttp for sending requests to the API. So it should be placed on :
'DomainList' => $domainlist
How can I do that ?
If you're using laravel, you should consider taking advantages of their collections:
https://laravel.com/docs/5.4/collections#method-implode
public function index(Request $request)
{
$name = $request->input('keyword');
$category = $request->input('category');
$catkeywords = DB::table('keywords')->implode($category, ',');
echo $catkeywords;
}
Laravel collections have a command for imploding the array, so there's no need to use pluck and loop through the array unless you plan on doing other operations on the data too.
EDIT: Based on updated question, it sounds like you're looking for something like this:
public function index(Request $request)
{
$name = $request->input('keyword');
$category = $request->input('category');
$catkeywords = DB::table('keywords')->pluck($category); //You don't need to wrap this in an array()
$keywords = []; //Create a holding array
foreach ($catkeywords as $catkeyword) {
$keywords[] = $catkeyword . '.com'; //Push the value to the array
}
echo implode(',', $keywords); //Then implode the edited values at the end
}
when you use pluck() method then it return array of given name
so you dont have need to use foreach loop
just use
$catkeywords = array(DB::table('keywords')->pluck($category));
echo implode(',',$catkeyword);
You try do that
public function index(Request $request)
{
$name = $request->input('keyword');
$string = '';
$category = $request->input('category');
$catkeywords = array(DB::table('keywords')->pluck($category));
foreach ($catkeywords as $catkeyword) {
$string .= implode(',',$catkeyword);
}
echo $string;
}

Combine four foreach into one foreach?

I am trying to add 4 foreach into one. I know how to add 2 foreach into one like this :
foreach (array_combine($images, $covers) as $image => $cover) {
But i want to add more two foreach $titles as $title and $albums as $album.
I am not sure want like this :
foreach (array_combine($images, $covers) as $image => $cover) {
foreach (array_combine($titles, $albums) as $title => $album) {
echo "$image-$cover-$title-$album"
It show me duplicate of every output.I mean output is
demo-demo1-demo2-demo3demo-demo1-demo2-demo3
Need output only
demo-demo1-demo2-demo3
Put the for each statement in a function. Then create a loop that calls it.
public function loopMe($images, $covers)
{
foreach (array_combine($images, $covers) as $image => $cover) {
$this->loopMe($image,$cover);
}
}
It looks like your second for loop is being called multiple times per item in the first for loop. So you want to make sure that you are only calling the second for loop once per image cover. or set an index cap on the second for loop. For instance if you are tyring to map the first item in the first for loop to the first item in the second for loop you should use an index.
public function loopMe($images)
{
for ($i = 0; $i < count($images); $i++) {
echo $images[$i] . '-'. $title[$i] . '-' . $cover[$i] . '-'. $album[$i];
}
}
I think you are approaching this problem from the wrong angle. From what I can tell, you are trying to output the properties of something. I think what you want to do is approach this from an object-oriented approach by creating a class and using a method to output the contents of your object.
Something like this:
class MyAlbumThing {
protected $image;
protected $cover;
protected $title;
protected $album;
public __construct($image, $cover, $title, $album) {
$this->image = $image;
$this->cover = $cover;
$this->title = $title;
$this->album = $album;
}
public getImage() {
return $this->image;
}
public getCover() {
return $this->cover;
}
public getTitle() {
return $this->title;
}
public getAlbum() {
return $this->album;
}
public getString() {
return $this->image . '-' .
$this->cover . '-' .
$this->title . '-' .
$this->album;
}
}
Then, you can instantiate this class and print your properties:
MyAlbumThing album = new MyAlbumThing("demo", "demo1", "demo2", "demo3");
echo $album->getString();
Would output:
demo-demo1-demo2-demo3
Also, if you hav a lot of these things, then you would use a foreach, like so:
$myAlbumArray = new array();
$myAlbumArray[] = new MyAlbumThing("demo", "demo1", "demo2", "demo3");
$myAlbumArray[] = new MyAlbumThing("anotherdemo", "anotherdemo1", "anotherdemo2", "anotherdemo3");
$lengthOfArray = sizeof(myAlbumArray);
for ($i = 0; $i < $lengthOfArray; $i++) {
echo $myAlbumArray[$i]->getString();
}
Sorry for any errors in my syntax, I wrote that in the browser without the help of my IDE.
I highly recommend learning more about object-oriented PHP programming. I found this article especially helpful while I was learning: http://code.tutsplus.com/tutorials/object-oriented-php-for-beginners--net-12762
EDIT:
Please mark this answer as correct if you did indeed find this helpful for your problem.

I need some help accessing a member function in a protected array in PHP

Right now I'm trying to write a function that would allow me to access member functions. The code in question looks a little like this:
protected $formName;
protected $formClass;
protected $formAction;
protected $formMethod;
protected $formObjArray = array(); //outputs in order. So far it should only take newLine, selectTag, inputTag, textTag.
protected $submitBtnVal;
protected $encType;
function __construct($args) {
$this->formName = $args['formName'];
$this->formAction = $args['formAction'];
if (isset($args['formClass'])) $this->formClass = $args['formClass'];
if (isset($args['encType'])) $this->encType = $args['encType'];
//default should be POST. Hell, you should never really be using GET for this..
//also, the default submit value is Submit
$this->formMethod = isset($args['formMethod']) ? $args['formMethod'] : "POST";
$this->submitBtnVal = isset($args['submitBtnVal']) ? $args['submitBtnVal'] : "Submit";
}
//get functions
function getFormName () { return $this->formName; }
function getFormAction () { return $this->formAction; }
function getFormMethod () { return $this->formMethod; }
function getSubmitBtnVal () { return $this->submitBtnVal; }
function getEncType () { return $this->encType; }
//set functions
function setFormName ($newName) { $this->fromName = $newName; }
function setFormAction ($newAction) { $this->formAction = $newAction; }
function setFormMethod ($newMethod) { $this->formMethod = $newMethod; }
function setEncType ($newEType) { $this->encType = $newEType; }
function addTag($newTag) {
if ($newTag instanceof formTag || $newTag instanceof fieldSetCont || $newTag instanceof newLine
|| $newTag instanceof noteTag)
$this->formObjArray[] = $newTag;
else throw new Exception ("You did not add a compatible tag.");
}
I'd like to be able to call $myForm->getTagByName("nameA")->setRequired(true);
How would I do that? Or would I need to do something more like..
$tagID = $myForm->getTagByName("nameA");
$myForm->tagArray(tagID)->setRequired(true);
Nothing in your code seems to be protected so you should have no trouble accessing any of it.
It looks like all your tags are in $formObjArray so it should be trivial to filter than array and return tags that match the name you've passed in. The trouble you will have is that, getTagByName really should be getTagsByName and should return an array because you can have more than one tag with the same name. Since it will return an array, you can not call setRequired on the return value, arrays don't have such a method. You'll need to do it more like:
$tags = $myForm->getTagsByName("nameA");
foreach ($tags as $tag) {
$tag->setRequired(true);
}
Exactly what are you stuck on? Maybe I don't understand the question very well.
So maybe the filtering has you stuck? Try this (if you you're using at least php 5.3)
function getTagsByName($tagname)
{
return array_filter($this->formObjArray, function($tag) use($tagname) {
return $tag->getName() == $tagname;
});
}
No ifs or switches.
Prior to 5.3, you don't have lambda functions so you need to do it differently. There are several options but this may be the simplest to understand:
function getTagsByName($tagname)
{
$out = array();
foreach ($this->formObjArray as &$tag) {
if ($tag->getName() == $tagname) {
$out[] = $tag;
}
}
return $out;
}
In your addTag method, you are storing new tags in $this->formObjArray using the [] notation, which will just append the new tag to the end of the array. If your tag objects all have a getName() method, then you can do something like this:
$this->formObjArray[$newTag->getName()] = $newTag;
Then, you can easily add a getTagByName() method:
public function getTagByName($name) {
if (array_key_exists($name, $this->formObjArray) {
return $this->formObjArray($name);
}
else {
return null;
}
}
Please beware of the solutions suggesting you to iterate through all the tags in your array! This could become very costly as your form gets larger.
If you need to use the [] construct because the order of the elements added is important, then you can still maintain a separate index by name, $this->tagIndex, that will be an associative array of name => tag. Since you are storing object references, they will not be using much space. Assuming that getTagByName will be used many times, this will save you a lot of resources over iterating the tags array on every call to getTagByName.
In that case, your addTag method would look like this:
$this->formObjArray[] = $newTag;
$this->tagIndex[$newTag->getName()] = $newTag; // it seems that you're doubling the memory needed, but you're only storing object references so this is safe
EDIT : Here is some modified code to account for the fact that multiple tags can have the same name:
In your addTag() method, do:
$this->formObjArray[] = $newTag;
$tag_name = $newTag->getName();
if (!array_key_exists($tag_name, $this->tagIndex)) {
$this->tagIndex[$tag_name] = array();
}
$this->tagIndex[$tag_name][] = $newTag
You can then rename getTagByName to getTagsByName and get the expected result.
As mentioned in the comments, this is only useful if you will call getTagsByName multiple times. You are trading a little additional memory usage in order to get quicker lookups by name.

Defining a function with name from a variable?

I need to create a column-system for Wordpress with shortcodes, which is not a problem, but I'm trying to make it with less code.
I have an array with the data needed, I loop through it, create a unique-named function and set it as shortcode-function. The third step is a mystery. How can I create a function from a variable.
Here's an example, how it should be done:
$data[] = "first";
$data[] = "second";
foreach($data as $key => $value) {
function $value($atts,$content) {
return '<div class="'.$value.'">'.$content.'</div>';
}
add_shortcode($value,$value);
}
However, it seems that it's not possible to make it work like that in PHP. Is there any way to make this work, as I would not want to write all the (identical) functions separated. I could make the shortcode something like [col first]text[/col] but the client wants to have different names for every one of them.
you can use the double dollar syntax to use the value of a variable as a variable identifier,
Example:
$variable = "test";
$$variable = "value of test"
echo $test; //or echo $$variable;
I have never tried but you way want to try:
foreach($data as $key => $value)
{
function $$value($atts,$content)
{
}
add_shortcode($value,$value);
}
or a function like create_function
if your using PHP 5.3 or greater then you can do something like so:
$$value = function()
{
}
which should work fine
I'm not sure how WP invocates the functions, but if it uses call_user_func then you might cheat by using an object with virtual methods:
class fake_functions {
function __call($name, $params) {
return '<div class="'.$name.'">'.$params[1].'</div>';
}
}
$obj = new fake_functions();
foreach ($data as $value) {
add_shortcode($value, array($obj,$value));
}

PHP global declaration

I'm using PHP's global declaration to make an array available to a number of functions in a script. The variable is declared at the top of the script and is referenced with global in each of the functions which uses it, as follows:
<?php
$myarray = array(1, 2, 3);
function print_my_array() {
global $myarray;
print '<ul>';
foreach($myarray as $entry) {
print '<li>'.$entry.'</li>';
}
print '</ul>';
return 0;
}
print_my_array();
?>
Sometimes, but not always, the array is not set when the function is called, generating an error when the foreach is called. In the actual code, the array used is given a very unique name and so should not be causing any collisions with anything else. Am I mis-using the global declaration?
No, the snippet is correct. The problem you're having is the problem of using global variables – they can be accessed and changed from anywhere (perhaps accidental), thereby creating hard-to-find bugs.
By using globals you can hit quite a few gotchas, they'll also make you code less reusable.
Here's an example of your function which can be re-used many times across the site.
(untested)
<?php
function arrayTags($items, $open = '<li>', $close = '</li>')
{
if (is_array($items) && count($items) != 0)
{
$output = null;
foreach ($items as $item) {
$output .= $open . $item . $close;
}
return $output;
}
else
{
return '';
}
}
// Default, <li>
echo '<ul>' . arrayTags($myarray) . '</ul>';
// or, spans:
echo '<div id="container">' . arrayTags($myarray, '<span>', '</span>') . '</div>';
The least you could do is check if the array is null at the top of the function, before you run the foreach. that would at least prevent the error:
function print_my_array() {
global $myarray;
if(!empty($myarray)) {
print '<ul>';
foreach($myarray as $entry) {
print '<li>'.$entry.'</li>';
}
print '</ul>';
}
}
Also, I wouldn't just return 0 for the hell of it. You may want to incorporate whether or not the array was empty into what you return from this function.
$myarray = array(1, 2, 3);
In short you have to only declare it like so:
$myarray = array();
and if you want to populate it with values do that in the class constructor:
public function __construct(){
$myarray = array(1,2,3);
}
I'm no guru, but in my experience it seems that php doesn't like to execute function calls outside of a function within a class.
THIS DOES NOT WORK:
class MyClass {
public $mystring = myfunction();
public function myFunction(){
return true; //and your function code
}
}
so when you use array() it doesn't actually trigger any function call, it just creats an empty variable of type array. when you use array(1,2,3), it has to effectively run the 'create array' which is like a function.
I know annoying, I'd like it to be different, but I don't know a way of doing what you want in php. Let me know if there is a nice way I'd love to hear it!

Categories